//tabs 高级选项卡 import win.ui.ctrl.close; import win.ui.menu; import util.metaProperty; namespace win.ui; class tabs{ ctor( tab1,tab2,... ){ { if( tab1.isForm && !tab2 ){ var vert,horz = {},{} for(hwnd,ctrl in tab1.eachControlEx("plus") ){ var x,y = ctrl.getPos(); vert[x] = vert[x]:{} ..table.push(vert[x],ctrl); horz[y] = horz[y]:{} ..table.push(horz[y],ctrl); } var _,_,w,h = tab1.getClientRect().xywh() var items = {} for(x,v in vert) { if(#v<2) continue; ..table.push(items,{..math.min(x,w-x),v}); } for(y,v in horz) { if(#v<2) continue; ..table.push(items,{..math.min(y,h-y),v}); } if(!#items) error("请在窗体上添加至少 2 个顶端对齐或左侧对齐、相同大小的 plus 控件。") ..table.sort(items,lambda(b)owner[1] ..math.abs(defRc3.top - defRc.top); this._form = this.tabList[1]._parentForm; this.selHistory = {}; this._radioGroup = "#" + tostring(this); for(i,s in this.tabList){ s.radioGroup = this._radioGroup; } ..table.sort(this.tabList,function(b){ if(this.horizontal) return owner._defRect.left < b._defRect.left; else return owner._defRect.top < b._defRect.top; }); var hTabPanel; var defRc = this.tabList[1]._defRect; var defRc2 = this.tabList[2]._defRect; var x,y,cx,cy = this.tabList[1].getPos(); this.startRect = this.tabList[1].getRect(); if(this.horizontal){ this.itemMargin = defRc2.left - defRc.right; if(!this.panel) { hTabPanel= ::User32.ChildWindowFromPointEx(this._form.hwnd,x + cx,y + cy +cy,2 | 1 | 4 ); if(!hTabPanel) hTabPanel = ::User32.ChildWindowFromPointEx(this._form.hwnd,x + cx,y - cy,2 | 1 | 4 ); } } else { this.itemMargin = defRc2.top - defRc.bottom; if(!this.panel) { hTabPanel= ::User32.ChildWindowFromPointEx(this._form.hwnd,x + cx + cx,y + cy,2 | 1 | 4 ); if(!hTabPanel) hTabPanel = ::User32.ChildWindowFromPointEx(this._form.hwnd,x - cx,y + cy,2 | 1 | 4 ); } } this.designTimeItemWidth = defRc2.width(); this.designTimeItemHeight = defRc2.height(); if(hTabPanel){ this.panel = this._form.getCtrl(hTabPanel); if(this.panel[["cls"]]!="custom") { this.panel = null; var startRect = this.tabList[1].getRect(); if(this.horizontal) startRect.inflate(0,cy); else startRect.inflate(cx,0); for(name,ctrl in this._form.eachControl("custom") ){ if(ctrl.getRect().intersectsWith(startRect)){ this.panel = ctrl; break; } } if(!this.panel){ for(name,ctrl in this._form.eachControl("custom") ){ this.panel = ctrl; break; } } } } this.forms = {}; var first = this.tabList[1]; var last = this.tabList[#this.tabList]; this.designTimeBeginRect = ..table.clone(first._defRect); if(this.horizontal){ this.designTimeBeginRect.offset(-(first._defRect.width()+this.itemMargin),0); this.keepSpace = !(last.dl || last.dr) } else { this.designTimeBeginRect.offset(0,-(first._defRect.height()+this.itemMargin)); this.keepSpace = !(last.dt || last.db) } this.template = { cls = last.cls; bkBottom=last.bkBottom; bkLeft=last.bkLeft; bkRight=last.bkRight; bkTop=last.bkTop; paddingLeft=last.paddingLeft; paddingRight=last.paddingRight; paddingTop=last.paddingTop; paddingBottom=last.paddingBottom; textPadding=last.textPadding; color=last.color; valign=last.valign; align=last.align; x=last.x; y=last.y; dl=last.dl; dt=last.dt; dr=last.dr; db=last.db; clipch=last.clipch; backgroundColor=last.backgroundColor; background=last.background; foreground=last.foreground; foreRepeat=last.foreRepeat; border=last.border; repeat=last.repeat; notify=last.notify; font=last.getFont(); iconStyle=last.iconStyle; iconText=last.iconText; iconColor=last.iconColor; focusOnClick=false; hide=1; z=1; } var ddParam = { cls = last.cls; left=last.right; top=last.top; width = 30; height = 30; dl=last.dl; dt=last.dt; dr=last.dr; db=last.db; notify=1; text = this.horizontal ? "4" : "6"; font=LOGFONT(name='Marlett';h=-16); focusOnClick=false; z=1; hide=1; }; if(this.horizontal){ ddParam.align = "left"; } else { ddParam.valign = "top"; } this.dropButton = this._form.addCtrl({ddParam})[1]; this.dropButton.skin(dropButtonStyle); this.dropButton.oncommand = function(){ var last = this.lastVisibleIndex(); if(!last) return; var menu = ..win.ui.popmenu(this._form); for(i=last+1;#this.tabList;1){ menu.add( this.tabList[i].text, function(id){ this.tabList[last].show(0/*_SW_HIDE*/); this.swap(i,last); this.tabList[last].show(4/*_SW_SHOWNOACTIVATE*/) this.selIndex = last; } ) } var rect = this.dropButton.getRect(); menu.popup(rect.right,rect.bottom); } this.margin = this.dropButton.width; this.margin = this.margin + ..math.max(this.itemMargin,10 ) this.dropButtonMargin = ..math.max(this.itemMargin,10 ) //下面创建选项卡上的浮动关闭按钮 //------------------------------------------------------------------- this.closeButton = this._form.addCtrl({{ cls = "close";width = 16;height = 16; }})[1]; this.closeButton.oncommand = function(){ if( this.closeButton.hoverTab) { this.deleteByTab(this.closeButton.hoverTab); this.closeButton.hoverTab = null; }; this.closeButton.hide = true; } this.closeButton.onMouseLeave = function(wParam,lParam){ if( !owner.hoverTab[["state"]][["hover"]] ) { owner.hide = true; owner.hoverTab = null; } } this._preMouseHover = function(wParam,lParam){ var tab = owner; if( this.onMouseHover ) this.onMouseHover(tab,wParam,lParam); if( !tab.hasCloseButton ) return; var rcTab = tab.getRect(); var rcCloseButton = this.closeButton.getRect(); var x,y; if( this.beforeShowCloseButton ){ x,y = this.beforeShowCloseButton(tab,rcTab,rcCloseButton,tab.dpiScaleX:1,tab.dpiScaleY:1); if(x===null) return; } else { x,y = rcTab.right - rcCloseButton.width() + 2,rcTab.top - 2; } x,y = ..win.toScreen(this._form.hwnd,x,y); this.closeButton.setPos(x,y); this.closeButton.show(0x4/*_SW_SHOWNOACTIVATE*/); this.closeButton.hoverTab = tab; } this._preMouseLeave = function(wParam,lParam){ if( this.onMouseLeave ) this.onMouseLeave(owner,wParam,lParam); if( !this.closeButton.state.hover ){ this.closeButton.hide = true; this.closeButton.hoverTab = null; } } this._preMouseDown = function(wParam,lParam){ var tab = owner; if( this.onMouseDown ) this.onMouseDown(tab,id,event); var hFocus = ..win.getFocus(); if( ..win.isChild(this.selForm[["hwnd"]],hFocus) ){ this.selForm.$lostFocusInTabs = hFocus; } } this._preSelectChange = function(prevTab){ var selTab = owner; this.selIndex = this.selIndex; }; this._preMouseUp = function(id,event){ var tab = owner; if( this.onMouseUp ) this.onMouseUp(tab,id,event); if( this.oncommand ) this.oncommand(tab,id,event); if( this.mode = "popup" ){ if( this.onOk ) this.onOk(this.selTab); this.popup(false); return; } if(this.selForm[["$lostFocusInTabs"]]){ ..win.setFocus(this.selForm[["$lostFocusInTabs"]]); this.selForm[["$lostFocusInTabs"]] = null; } }; this._preFocusGot = function(hFocusLost){ if( this.onFocusGot ) return this.onFocusGot(hFocusLost); } this._preMouseActivate = function(hwndTop,hitTest,message){ if( this.isPopup() ) return 3/*_MA_NOACTIVATE*/ } this._preFocusLost = function(hFocusGot){ if( this.onFocusLost ) { for(i=1;#this.tabList;1){ if( hFocusGot === this.tabList[i].hwnd ) return; } return this.onFocusLost(hFocusGot); } } this.dropButton.preadjust = function(){ this.adjustLayout(); } for(i=1;#this.tabList;1){ v = this.tabList[i]; v.onMouseDown =this._preMouseDown; v.onSelectChange = this._preSelectChange; v.onMouseUp =this._preMouseUp; v.onMouseHover = this._preMouseHover; v.onMouseLeave = this._preMouseLeave; v.onFocusGot = this._preFocusGot; v.onFocusLost = this._preFocusLost; v.onMouseActivate = this._preMouseActivate; } if(defaultStyle){ this.tabList[1].setTimeout( function(){ if(!this.style && this.tabList[1]){ var $fixDefaultStyle = { color = this.tabList[1].argbColor; foreground = this.tabList[1].foreground; } this.skin( ..table.clone(defaultStyle)); //避免将默认字体修改为白色,用户自定义样式又指定了白色背景且没有指定字体颜色 this.$fixDefaultStyle = $fixDefaultStyle; } },100 ) } } }; isVisible = function(){ return #this.tabList && !this.tabList[1].hide; }; addItems = function(items,...){ if(#items){ for(i=1;#items;1){ this.add(items[i],...); } return; } }; setItems = function(items,limit,selIndex){ var tabList = this.tabList; if(!limit) limit = #items; else limit = ..math.min(limit,#items); if( limit >= #tabList ){ for(i=1;#tabList;1){ ..table.assign(tabList[i],items[i]); } for(i=#tabList+1;limit;1){ { this.add(items[i]); } } } else { for(i=1;limit;1){ ..table.assign(tabList[i],items[i]); } for(i=#tabList;limit+1;-1){ this.delete(i); } } if( selIndex ? (selIndex<#this.tabList) ) this.selIndex = selIndex; else this.selIndex = this.selIndex; return #this.tabList; }; setItemTexts = function(items,limit,selIndex){ return this.setItems( ..table.map(items,lambda(v){text=v}),limit,selIndex); }; add = function(tabProperties,...){ if(type(tabProperties)=="string") tabProperties = {text=tabProperties} if(#tabProperties && type(tabProperties[1])=="table"){ for(i=1;#tabProperties;1){ this.add(tabProperties[i],...); } return; } var isPopup = this.isPopup(); tabProperties = ..table.assign({},this.template,tabProperties); if(isPopup){ tabProperties.dt = 1; tabProperties.dl = 1; } var last = this.tabList[#this.tabList]; var rcDesignTime = last ? last._defRect : this.designTimeBeginRect; if(this.horizontal){ tabProperties.top = rcDesignTime.top; tabProperties.bottom = rcDesignTime.bottom; tabProperties.left = rcDesignTime.right + this.itemMargin; tabProperties.right = tabProperties.left + rcDesignTime.width(); } else { tabProperties.left = rcDesignTime.left; tabProperties.right = rcDesignTime.right; tabProperties.top = rcDesignTime.bottom + this.itemMargin; tabProperties.bottom = tabProperties.top + rcDesignTime.height(); } var tab = this._form.add( { tabProperties } )[[1]]; if( tab ){ if(this.itemRegion) this.itemRegion.updateWindow(tab.hwnd,true,true) tab.onDrawString = this[["(onDrawString)"]]; tab.onDrawForegroundEnd = this[["(onDrawForegroundEnd)"]]; tab.onDrawEnd = this[["(onDrawEnd)"]]; var idx = ..table.push(this.tabList,tab); ..win.setTop(tab.hwnd); this.radioGroup = this._radioGroup; if(this.style) tab.skin(this.style); tab.onMouseDown = this._preMouseDown; tab.onSelectChange = this._preSelectChange; tab.onMouseUp = this._preMouseUp; tab.onMouseHover = this._preMouseHover; tab.onMouseLeave = this._preMouseLeave; tab.onFocusGot = this._preFocusGot; tab.onFocusLost = this._preFocusLost; tab.onMouseActivate = this._preMouseActivate if(isPopup){ tab.orphanWindow(this.transparent); return; } if(this.margin){ var rect = this._form.getClientRect(); if(this.horizontal){ var margin = this.margin * (this._form.dpiScaleX:1) if(tab.right + margin > rect.right){ var v = this.lastVisibleIndex(); if(v){ this.swap(idx,v); this.tabList[idx].hide = true; tab.predraw(); tab.show(4/*_SW_SHOWNOACTIVATE*/); this.showDropButton(true); return v; } } } else { var margin = this.margin * (this._form.dpiScaleY:1) if(tab.bottom + margin > rect.bottom){ if(v){ var v = this.lastVisibleIndex(); this.swap(idx,v); this.tabList[idx].hide = true; tab.predraw(); tab.show(4/*_SW_SHOWNOACTIVATE*/); this.showDropButton(true); return v; } } } } tab.predraw(); tab.show(4/*_SW_SHOWNOACTIVATE*/); if(...){ var frm = this.forms[idx]; if( frm ) { frm.close(); } this.forms[idx]= this.panel.preloadForm(...); } return idx; } }; adjust = function(){ }; adjustLayout = function(){ if(!this.isVisible()){ return; } if( this.tabList[1] ){ this.startRect = this.tabList[1].getRect(); } var rect = this._form.getClientRect(); if(! ( rect.width() && rect.height() ) ) return this.adjust(); var last = 1; var keepSpace = this.keepSpace && (!this.itemRegion); if(this.horizontal){ var margin = this.margin * (this._form.dpiScaleX:1) while( var tab; tab = this.tabList[last]; tab && ( ( tab.right + margin ) < rect.right ) ) { if( keepSpace ? (last>1) ){ ..win.setPos(tab.hwnd,this.tabList[last-1].right + this.itemMargin,tab.top,,,,0x1C/*_SWP_NOACTIVATE | _SWP_NOZORDER | _SWP_NOREDRAW*/) tab.predraw(); } if(tab.hide) tab.show(4/*_SW_SHOWNOACTIVATE*/); last++; } } else { var margin = this.margin * (this._form.dpiScaleY:1) while( var tab; tab = this.tabList[last]; tab && ( ( tab.bottom + margin ) < rect.bottom ) ) { if( keepSpace ? (last>1) ){ ..win.setPos(tab.hwnd,tab.left,this.tabList[last-1].bottom + this.itemMargin,,,,,0x1C/*_SWP_NOACTIVATE | _SWP_NOZORDER | _SWP_NOREDRAW*/) tab.predraw(); } if(tab.hide) tab.show(4/*_SW_SHOWNOACTIVATE*/); last++; } } if(!this.margin) return this.adjust(); this.showDropButton(false); if( ( last<= # this.tabList) && (last > 1) ) { if( this.selIndex >= last ) { this.swap(last-1,this.selIndex); this.tabList[last-1].show(4/*_SW_SHOWNOACTIVATE*/); }; for(i=last;# this.tabList;1){ this.tabList[i].hide = true; } this.showDropButton(true); } return this.adjust(); }; setPos = function(x,y){ if(!#this.tabList){ if(this.startRect )this.startRect.setPos(x,y); return; } var x1,y1 = this.tabList[1].getPos() for(i=1;#this.tabList;1){ var tab = this.tabList[i] var x2,y2 = tab.getPos(); tab.setPos(x+x2-x1,y+y2-y1); } }; getPos = function(){ if(#this.tabList){ this.startRect = this.tabList[1].getRect() } var rc = this.startRect; var len = #this.tabList; if( len > 1 ){ var x,y,cx,cy = this.tabList[len].getPos(); x,y,cx,cy = rc.left,rc.top,x+cx-rc.left,y+cy-rc.top; for(i=2;#this.tabList-1;1){ var x2,y2,cx2,cy2 = this.tabList[i].getPos(); x = ..math.min(x,x2); y = ..math.min(y,y2); cx = ..math.max(cx,x2+cx2-x); cy = ..math.max(cy,y2+cy2-y); } return x,y,cx,cy; } elseif(!len){ return rc.left,rc.top,0,0; } return rc.left,rc.top,rc.width(),rc.height(); }; hitTest = function(x,y){ for(i=1;#this.tabList;1){ var rc = this.tabList[i].getRect(true); if(::PtInRect(rc,x,y)){ return this.tabList[i],i; } } }; swap = function(a,b){ var ia = this.tabList[a]; var ib = this.tabList[b]; if(!(ia&&ib) ) return; var ax,ay = ia.getPos(); var bx,by = ib.getPos(); ib.setPos(ax,ay); ia.setPos(bx,by); this.tabList[a],this.tabList[b] = this.tabList[b],this.tabList[a]; this.forms[a],this.forms[b] = this.forms[b],this.forms[a]; return true; }; showDropButton = function(v){ if(!v) { this.dropButton.hide = true; return; } var last = this.lastVisibleItem(); if(!last) return; if(this.horizontal){ this.dropButton.setPos( last.right + this.dropButtonMargin,last.top + (last.height - this.dropButton.height) /2) } else { this.dropButton.setPos( last.left + (last.width - this.dropButton.width) /2,last.bottom + this.dropButtonMargin) } ..win.setTop(this.dropButton.hwnd); this.dropButton.redrawTransparent(); this.dropButton.show(4/*_SW_SHOWNOACTIVATE*/); }; loadForm = function(idx,...){ if(idx===null) idx = #this.forms + 1; else{ var t = type(idx); if(t!="number"){ if(t=="string") idx = {text=idx};//仅容错。 //允许省略索引参数并自动指定 return this.loadForm(null,idx,...) } elseif(idx<0) idx = #this.tabList + idx + 1; } if( this.forms[idx] ) { this.forms[idx].close(); } if(!this.tabList[idx]){ if(type(...)=="table"){ this.add( text = (...).text); } else error("请先添加对应索引的选项卡",2); } if(!this.panel){ error("请在选项卡一侧添加一个 custom 控件作为页面容器",2); } this.forms[idx] = this.panel.preloadForm(...); this.forms[idx][["onCreated"]] = function(realForm){ this.forms[idx] = realForm; var hFocus = ..win.getFocus(); if(..win.isChild(realForm.hwnd,hFocus)){ realForm["$lostFocusInTabs"] = hFocus; } } return this.forms[idx]; }; preloadForm = function(idx,show){ //此函数已废弃。 var form = this.forms[idx]; if(!form) return; if(show!==null) form.show(show); return form.this(); //fake window 自动初始化。 }; create = function(tabProperties){ var idx = this.add(tabProperties); if( idx ) this.forms[idx]= this.panel.loadForm( ..win.form(parent = this.panel) ); return this.tabList[idx],this.forms[idx]; }; indexOfTab = function(tab){ for(i=1;#this.tabList;1){ if( this.tabList[i] == tab ) return i; } }; indexOfForm = function(form){ for(i=1;#this.forms;1){ if( form == this.forms[i] ) return i; } }; delete = function(idx){ var selIndex; var tab = this.tabList[idx]; if(tab) { for(i=#this.selHistory;1;-1){ if( (this.selHistory[i] == tab ) || (!..win.isWindow(this.selHistory[i].hwnd) ) ) ..table.remove(this.selHistory,i); } selIndex = this.selIndex; if(selIndex==idx) { var preTab = ..table.pop(this.selHistory,1) var preIdx = preTab ? this.indexOfTab(preTab); if( preIdx ){ selIndex = preIdx; } else { var lastVisibleIndex = this.lastVisibleIndex(); if( lastVisibleIndex && (selIndex < lastVisibleIndex) ){ selIndex = selIndex; } elseif(selIndex == lastVisibleIndex){ } else{ selIndex = null; } } } else { selIndex = null; } var x,y = tab.getPos(); ..table.remove(this.tabList,idx); tab.close(); for(j=idx;#this.tabList;1){ var x2,y2 = this.tabList[j].getPos(); this.tabList[j].setPos(x,y); x,y = x2,y2; } }; var form = this.forms[idx]; if(form) { ..table.remove(this.forms,idx); form.close(); }; this.adjustLayout(); if(selIndex){ if(selIndex>=#this.tabList){ selIndex=#this.tabList; } this.selIndex = selIndex; } }; deleteByTab = function(tab){ for(i=1;#this.tabList;1){ if( tab == this.tabList[i] ) return this.delete(i); } }; deleteByForm = function(form){ for(i=1;#this.forms;1){ if( form == this.forms[i] ) return this.delete(i); } }; clear = function(){ for(i=1;#this.forms;1){ this.forms[i].close(); } for(i=1;#this.tabList;1){ this.tabList[i].close(); } this.tabList = {}; this.forms = {}; }; each = function(){ var i = 0; return function(){ i++; return this.tabList[i],this.forms[i],i; } }; query = function(args){ if( type(args) == "string" ){ args = {text=args} }; for(i=1;#this.tabList;1){ var tab = this.tabList[i] for(k,v in args){ if(tab[k] = v) { var form = this.forms[i]; if(form && form.hwnd){ if(this.selForm) this.selForm.show(); return form,i; } } } } }; queryTab = function(args){ if( type(args) == "string" ){ args = {text=args} }; for(i=1;#this.tabList;1){ var tab = this.tabList[i] for(k,v in args){ if(tab[k] = v) { return tab,i; } } } }; set = function(tabIndex,tabProperties){ var tab = this.tabList[tabIndex]; if(!tab) error("参数 @1 指定了错误的选项索引"); ..table.assign( tab,tabProperties ); }; setTabs = function(name,values){ for(i=1;#values;1) this.tabList[i][name] = values[i]; }; updateItemRegion = function(itemRegion){ if(itemRegion){ if(! itemRegion[["updateWindow"]] ){ error("参数必须是兼容 win.region.png 接口的对象",2) } this.template.clipch = 1; for(tab in this.each() ){ itemRegion.updateWindow(tab.hwnd,true,true) ..win.modifyStyle(tab.hwnd,,0x2000000/*_WS_CLIPCHILDREN*/) } this.itemRegion = itemRegion; } else { this.itemRegion = null; for(tab in this.each() ){ ::SetWindowRgn( tab.hwnd ,null ); tab.predraw(); } } }; isPopup = function(){ return this.mode = "popup"; }; initPopup = function(handleCtrl,transparent){ if(transparent!==null){ this.transparent = transparent;} if(!handleCtrl){ if(!this._popHandle){ this._popHandle = this._form.add({{cls="plus";text="win.ui.tabs.popHandle";left=0;top=0;width=0;height=0;notify=1;z=1}})[1] } this.$popHandle = this._popHandle; handleCtrl = this._popHandle; } else { this.$popHandle = handleCtrl; } if(!handleCtrl.handleWinUiTabs){ var oldTranslate = handleCtrl.defaultTranslateAccelerator; handleCtrl.defaultTranslateAccelerator = function(msg){ if(this.isVisible() && msg.message == 0x100/*_WM_KEYDOWN*/ ){ if(msg.wParam==0x1B/*_VK_ESC*/){ this.popup(false); if(this.onCancel)this.onCancel(); return true; } elseif(msg.wParam==0xD/*_VK_RETURN*/){ if( this.selTab ) { if( this.oncommand ) this.oncommand(this.selTab,this.selTab[["id"]],0); if( this.onOk ) this.onOk(this.selTab); } this.popup(false); return true; } } if(oldTranslate)return invoke(oldTranslate,handleCtrl,msg); } handleCtrl.wndproc = function(hwnd,message,wParam,lParam){ if(message==0x200/*_WM_MOUSEMOVE*/){ var x,y = ..win.getMessagePos(); var tab,idx = this.hitTest(x,y); for(i,tab in this.tabList){ var preHover = tab.state.hover; tab.state.hover = i == idx; if(tab.state.hover!=preHover){ tab._onStateChange(); } } }; elseif(message==0x201/*_WM_LBUTTONDOWN*/){ if(this.isVisible()){ var x,y = ..win.getMessagePos(); var rc = owner.getRect(true); if(::PtInRect(rc,x,y)){ return; } ..win.releaseCapture(); var tab,idx = this.hitTest(x,y); if(!tab){ if(this.onCancel)this.onCancel(); this.popup(false); } else { this.selIndex = idx; } } } elseif(message===0x100/*_WM_KEYDOWN*/){ if(!this.isVisible()) return; var vk = wParam; if( vk === 0x9/*_VK_TAB*/ || vk == 0x28/*_VK_DOWN*/){ this.next(); return true; } elseif(vk == 0x26/*_VK_UP*/){ this.prev(); return true; } elseif(vk == 0x20/*_VK_SPACE*/|| vk == 0xD/*_VK_RETURN*/){ if( this.selTab ) { if( this.oncommand ) this.oncommand(this.selTab,this.selTab[["id"]],0); if( this.onOk ) this.onOk(this.selTab); } this.popup(false); return true; } elseif(vk == 0x1B/*_VK_ESC*/ ){ this.popup(false); if(this.onCancel)this.onCancel(); return true; } } elseif(message == 8/*_WM_KILLFOCUS*/){ if( this.isVisible() ){ this.popup(false); if(this.onCancel)this.onCancel(); } if(this.onFocusLost){ this.onFocusLost(wParam) } } elseif(message==0x202/*_WM_LBUTTONUP*/){ if(this.isVisible()){ var x,y = ..win.getMessagePos(); var rc = owner.getRect(true); if(::PtInRect(rc,x,y)){ return; } var tab,idx = this.hitTest(x,y); if( tab ){ if( this.oncommand ) this.oncommand(tab,id,event); if( this.onOk ) this.onOk(this.selTab); this.popup(false); } } } elseif(message ==0x87/*_WM_GETDLGCODE*/){ return 4/*_DLGC_WANTALLKEYS*/ } } } handleCtrl.handleWinUiTabs = this; if( ! this.isPopup() ){ this.mode = "popup" this.margin = 0; this.template.clipBk = null; this.template.transparent = null; for(i=1;#this.tabList;1){ var tab = this.tabList[i] tab.dt = 1; tab.dl = 1; tab.focusOnClick = false; tab.clipBk = null; tab.transparent = null; tab.show(0/*_SW_HIDE*/); tab.orphanWindow(this.transparent); } } }; show = function(show){ for(i=1;#this.tabList;1){ this.tabList[i].show(show); } if(this.onVisualStateChanged){ this.onVisualStateChanged(show) } }; popup = function(show,x,y){ if(!#this.tabList) show = false; if(!show){ this.show(false) } if(!this.isPopup()){ this.initPopup(); } if(x==-1){ var pt = ::POINT() ::User32.GetCursorPos(pt) x,y = pt.x,pt.y; } elseif(x[["hwnd"]]){ this.$popBuddy = x; var _,_,cx,cy = this.getPos(); var x2,y2,cx2,cy2 = ..win.getPos(x[["hwnd"]],true) var mode = y; if(!mode || mode ==="down"){ y = y2 + cy2; x = x2; } elseif(mode ==="up"){ y = y2 - cy; x = x2; } elseif(mode ==="left"){ y = y2; x = x2 - cx; } elseif(mode ==="right"){ y = y2; x = x2 + cx2; } } if( x && y ) { this.setPos(x,y); } this.show( show ? 4/*_SW_SHOWNOACTIVATE*/: 0/*_SW_HIDE*/); if(!show){ if(this.$popHandle)this.$popHandle.checked = false; if(this.$popBuddy)this.$popBuddy.checked = false; if(this.onPopup){ this.onPopup(false) } ..win.releaseCapture(); } else { if(this.$popHandle)this.$popHandle.checked = true; if(this.$popBuddy)this.$popBuddy.checked = true; this._form.setTimeout( function(){ ..win.setFocus(this.$popHandle.hwnd); if( this.onFocusGot ) return this.onFocusGot(hFocusLost); ..win.setCapture(this.$popHandle.hwnd); if(this.onPopup){ this.onPopup(true) } },10 ) } return show; }; skin = function(style){ if(this.$fixDefaultStyle){ if( style.foreground && style.foreground.default === null ){ style.foreground.default = this.$fixDefaultStyle.foreground; } if( style.color && style.color.default === null ){ style.color.default = this.$fixDefaultStyle.color; } this.$fixDefaultStyle = null; } style.group = this._radioGroup; for(i=1;#this.tabList;1){ this.tabList[i].skin(style); } this.style = style; }; getText = lambda (tabIndex) this.tabList[tabIndex].text; @_metaProperty; } namespace tabs{ _metaProperty = ..util.metaProperty( next = function(){ var selIndex = owner.selIndex : 0; selIndex = selIndex + 1; if(selIndex>#owner.tabList){ selIndex = 1; } owner.selIndex = selIndex; }; prev = function(){ var selIndex = owner.selIndex : (#owner.tabList+1); selIndex = selIndex - 1; if(selIndex<1){ selIndex = #owner.tabList; } owner.selIndex = selIndex; }; selIndex = { _get = function(){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].checked ) return i; } }; _set = function( i ){ if(!i){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].checked ) { tabList[i].checked = false; tabList[i].state.hove = false; tabList[i].state.active = false; } } return; } var tab = owner.tabList[i]; if(!tab) error("错误的选项卡索引",2); var lastsel = owner.selHistory[#owner.selHistory]; if( ( lastsel == tab ) && tab.checked ){ if( ( !owner.forms[i] ) || (owner.forms[i] && !owner.forms[i].hide) ) return; } var lastVisible = owner.lastVisibleIndex(); if( lastVisible){ if( i > lastVisible ){ owner.tabList[lastVisible].show(0/*_SW_HIDE*/); owner.swap(i,lastVisible); owner.tabList[lastVisible].show(4/*_SW_SHOWNOACTIVATE*/); owner.selIndex = lastVisible; return; } } tab.show(4/*_SW_SHOWNOACTIVATE*/); ..table.push(owner.selHistory,owner.tabList[i]); if(#owner.selHistory > 10) owner.selHistory = ..table.slice(owner.selHistory,-10); if(owner.panel){ owner.panel.showChildren(false); var form = owner.forms[i]; if(owner.forms[i]){ //fake window 会自动初始化 form.show(true);//防止子窗体没有调用 show 方法,一定要先显示,再调用 setRect 才有效 form.setRect(owner.panel.getClientRect()); }; }; tab.checked = true; var f = owner.onSelChange || owner.onSelChanged || owner.onSelchange; if( f ) invoke(f,owner,i,owner.tabList[i],owner.forms[i]); } }; selTab = { _get = function(){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].checked ) return tabList[i]; } } _set = function(v){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i] == v ) { owner.selIndex = i; return ; } } owner.selIndex = null; } }; selText = { _get = function(){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].checked ) return tabList[i].text; } } _set = function(v){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].text == v ) { owner.selIndex = i; return ; } } owner.selIndex = null; } }; selForm = { _get = function(){ var tabList = owner.tabList; for(i=1;#tabList;1){ if( tabList[i].checked ) return owner.forms[i]; } } }; disabledText = { _get = function(){ return owner.selTab ? owner.selTab.disabledText; } _set = function(v){ if(!owner.selTab) return; var tabList = owner.tabList; for(i=1;#tabList;1){ tabList[i].disabledText = null; tabList[i].notify = !v; } if(owner.selTab) owner.selTab.disabledText = v; } }; disabled = { _get = function(){ return owner.selTab ? owner.selTab.disabled; } _set = function(v){ if(!owner.selTab) return; var tabList = owner.tabList; for(i=1;#tabList;1){ tabList[i].disabled = null; tabList[i].notify = !v; } owner.selTab.disabled = v; } }; count = { _get = function(ownerCall){ if(ownerCall) return lambda () #(owner.tabList); return #(owner.tabList) } }; lastVisibleIndex= function(){ var tabList = owner.tabList; for(i=#tabList;1;-1){ if( !tabList[i].hide ) return i; } }; lastVisibleItem = function(){ var tabList = owner.tabList; for(i=#tabList;1;-1){ if( !tabList[i].hide ) return tabList[i]; } }; onDrawString = { _set = function(d){ var tabList = owner.tabList; for(i=1;#tabList;1) { tabList[i].onDrawString = d; tabList[i].predraw(); } owner[["(onDrawString)"]] = d; }; _get = function(){ return owner[["(onDrawString)"]]; }; }; onDrawForegroundEnd = { _set = function(d){ var tabList = owner.tabList; for(i=1;#tabList;1) { tabList[i].onDrawForegroundEnd = d; tabList[i].predraw(); } owner[["(onDrawForegroundEnd)"]] = d; }; _get = function(){ return owner[["(onDrawForegroundEnd)"]]; }; }; onDrawEnd = { _set = function(d){ var tabList = owner.tabList; for(i=1;#tabList;1) { tabList[i].onDrawEnd = d; tabList[i].predraw(); } owner[["(onDrawEnd)"]] = d; }; _get = function(){ return owner[["(onDrawEnd)"]]; }; }; ) with _metaProperty{ container = { //@Deprecated _set = lambda(v) owner.panel = v; _get = lambda() owner.panel; }; strips = { //@Deprecated _set = lambda(v) owner.tabList = v; _get = lambda() owner.tabList; }; getForm = function(i){ //@Deprecated return owner.forms[i] }; getChild = getForm;//@Deprecated remove = delete;//@Deprecated } dropButtonStyle = { color = { hover = 0xff99ffcc; active = 0xffff6666; default = 0xffffffff; } } defaultStyle = { foreground={ active=0xFFFFFFFF; default=0xE60089E4; hover=0x38FFFFFF }; color = { hover = 0xff99ffcc; active = 0xffff6666; default = 0xffffffff; }; checked={ foreground={default=0xFFFFFFFF;}; color={default=0xFF42A875;}; } } } //@guide [高级选项卡使用指南](doc://library-guide/std/win/ui/tabs/_.md) /**intellisense() win.ui.tabs = 高级选项卡( win.ui.tabs )。\n高级选项卡并不是一个控件,而是用于管理一组 plus 控件( win.ui.ctrl.plus )以实现选项卡效果的管理组件。 win.ui.tabs( = 创建高级选项卡( win.ui.tabs )。\n自动查找附近合适的 custom 控件作为页面容器。\n优先选择未禁用、未隐藏、未设置透明的 custom 控件。\n如果是水平选项卡,应在下侧放置 custom 控件作为页面容器,\n如果是垂直选项卡,应在右侧放置 custom 控件作为页面容器。\n\n为了避免在启动软件时一次性加载大量子窗口导致启动速度慢,\n为每一个选项卡添加子窗口时,win.ui.tabs 默认会创建并返回伪窗口。\n直到点击该选项卡或访问伪窗口的属性与方法(fake 属性除外)时才会真正初始化相应的子窗口 win.ui.tabs(.(headerTab1,headerTab2) = 创建高级选项卡。\n参数必须指定至少2个已创建的 plus 控件模板,对象创建成功可选清除模板\n如果不需要动态增删选项卡,参数中的 plus 控件无需保持均匀间隔,\n\n动态增加选项卡时会根据模板控件的样式与位置,\n自动分析是水平排列还是垂直排列,自动分析排列间距,\n并动态添加选项卡,可选显示删除选项卡的按钮\n\n添加的选项卡数目超出显示范围时可自动折叠到下拉菜单,\n自动折叠功能会保证新增选项卡、当前选项卡位于可见位置,\n这会导致选项卡在必要时自动调整位置,\n所以同一索引并不一定指向同一选项卡 win.ui.tabs() = !win_ui_tabs. win.ui.tabs.defaultStyle = @.defaultStyle = {\n foreground={\n active=0xFFFFFFFF;\n default=0x00FFFFFF;\n hover=0x38FFFFFF\n };\n color = {\n default=0xFFFFFFFF; \n };\n checked={\n foreground={default=0xFFFFFFFF;}; \n color={default=0xFF42A875;};__/*默认选项卡样式*/\n }\n} win.ui.tabs.dropButtonStyle = @.dropButtonStyle = { \n color = { \n hover = 0xff99ffcc;\n active = 0xffff6666; \n default = 0xffffffff; \n }__/*选项卡下拉按钮默认样式*/\n} end intellisense**/ /**intellisense(!win_ui_tabs) margin = 可设置选项卡按钮尾部最少预留的边距,\n超出显示范围时自动折叠选项卡并在此显示下拉菜单,\n默认会根据下拉按钮的大小自动设置此值,\n如果设置为0则禁用自动折叠功能。\n\n此属性应设置为系统 DPI 缩放前的原始值 keepSpace = 是否保持选项之间的间距不变,\n该属性建议由aardio自动设置 dropButtonMargin = 下拉菜单按钮边距 itemMargin = 选项卡间隔距离,可以为负数 updateItemRegion(__) = 更新选项卡绘图区域,\n参数必须是兼容 win.region.png 接口的对象 selIndex = 获取或指定当前选中项索引,设为 null 清除当前选项,\n如果新的选中项已被自动折叠,则会自动移动到可见位置\n所以设置selIndex时可能导致selIndex移动位置 selTab = 获取或指定当前选中的选项卡按钮\n指定 null 或不存在于 tabs 中的控件时清除选中项,\n!ui_ctrl_plus. selText = 获取当前选中项文本,\n也可以指定一个文本用于切换到显示该文本的选项卡 selForm = 当前选中的子窗口\n!winform. lastVisibleIndex = 最后一个显示状态的选项卡索引\n在这后面是因为超出显示范围被自动隐藏的选项卡 lastVisibleItem = 最后一个显示状态的选项卡\n在这后面是因为超出显示范围被自动隐藏的选项卡\n这是一个plus控件对象\n!ui_ctrl_plus. panel = 用于构成选项卡内容区域( tab body area )的容器控件。\n必须是一个 custom 控件(win.ui.ctrl.custom 控件)。\n创建高级选项卡时,panel 属性会自动指定为附近可用的 custom 控件。\n也可以在加载子窗口以前手工指定此对象\n!winform. forms = 用于显示页面内容的子窗口数组,\n选中的子窗口将在 panel 属性指定的容器控件中显示。 forms.? = 子窗口是 win.form 对象\n!winform. tabList = 用于构成选项卡头部区域( tab header area )的选项卡按钮数组。\n所有选项卡按钮都是 plus 控件(win.ui.ctrl.plus 控件)。 tabList.? = 选项卡按钮数组包含的按钮对象。\n所有选项卡按钮都是 plus 控件(win.ui.ctrl.plus 控件)。\n!ui_ctrl_plus. adjustLayout() = 调整布局\n高级选项卡会在需要的时候自动调用此函数 getPos() = 返回x,y,cx,cy等4个值,\n分别表示高级选项卡当前左,上坐标,宽度,高度 hitTest(.(x,y) = 参数指定屏幕坐标,返回该坐标所在的选项卡,以及选项索引 adjust() = @.adjust = function(){ var x,y,cx,cy = owner.getPos(); __/*选项卡已重新调整布局*/ } showDropButton(true) = 参数为true显示下拉菜单按钮\n参数为 false 隐式该按钮\n高级选项卡会在需要的时候自动调用此函数 swap(.(tabIndex,tabIndex2) = 交换两个索引的选项卡位置\n参数 tabIndex,tabIndex2 应当是有效的选项卡索引\n这个函数如果没有弄清楚原理最好不要使用,\n高级选项卡会在需要的时候自动调用此函数,\n成功返回true,失败返回null loadForm( = 加载窗体到高级选项卡的页面容器控件,并绑定选项卡。\n选项卡必须已经匹配到可用的页面容器,\n也就是说 panel 属性不为空值。\n\n高级选项卡默认会自动查找附近合适的 custom 控件作为页面容器\n也可以手动指定 panel 指向的窗口\n\nloadForm 函数默认会加载延迟创建实际窗口的伪窗口。\n访问伪窗口的任何属性或方法都会自动创建真实窗口。 loadForm(.(tabIndex,"请输入窗体代码文件路径") = 在页面容器控件内预加载创建子窗体的代码文件,\n并绑定到参数 @tabIndex 指定索引的选项卡。\n参数 @tabIndex 可用负索引表示倒计数,-1 表示最后一个选项卡。\n在开发环境中,请注意保存外部窗体文件以后测试运行。\n\n默认会创建并返回一个伪窗口对象,\n并延迟到用户切换到所属选项卡时才会真正创建窗口。\n访问伪窗口除 fake 以外的任何属性方法也会立即创建窗口。 loadForm(.(tabIndex,winform) = 将 @winform 指定的子窗体添加到页面容器,\n并绑定到参数 @tabIndex 指定索引的选项卡。\n参数 @tabIndex 可用负索引表示倒计数,-1 表示最后一个选项卡。\n如果不指定索引(可省略参数占位)则默认取 forms 属性的数组长度并加 1 作为索引。\n返回参数 @2 指定的窗体对象。 loadForm(.(tabIndex,@tParam) = 在页面容器控件内创建子窗体并绑定到参数@1指定索引的选项卡。\n参数 @tabIndex 可用负索引表示倒计数,-1 表示最后一个选项卡。\n\n默认会创建并返回一个伪窗口对象,\n并延迟到用户切换到所属选项卡时才会真正创建窗口。\n访问伪窗口除 fake 以外的任何属性方法也会立即创建窗口。 loadForm(.(tabIndex) = 在页面容器控件创建默认子窗体并绑定到指定的选项卡。\n数 @tabIndex 指定索引,可用负索引表示倒计数,-1 表示最后一个选项卡。\n如果不指定索引则默认取 forms 属性的数组长度并加 1 作为索引。\n与其他函数同的是:此函数省略参数 @1 可不用占位,允许参数 @2 写为 参数 @1。\n省略参数 @2 则立即创建默认子窗体并加载到页面,然后返回该窗体。 loadForm(.() = 在页面容器控件创建默认子窗体并绑定到最后一个选项卡。\n返回创建的子窗口对象。 setItemTexts( = 使用文本数组更新选项卡数组,\n此函数可重用已创建的选项卡,所以有更好的性能 setItemTexts(.(texts,limit,selIndex) = 使用参数@texts指定的字符串数组创建选项卡数组,\n其中的每个字符串用于指定选项卡上的显示文本。\n可选用@limit参数指定最大显示条数,\n可选用@selIndex参数指定默认选中索引,\n此函数返回实际显示条数 setItems( = 使用控件初始化选项数组更新选项卡数组,\n此函数可重用已创建的选项卡,所以有更好的性能 setItems(.(items,limit,selIndex) = 使用参数@items指定的选项数组更新选项卡数组, \n每个选项提供控件的初始化属性并将被传入add函数。\n可选用@limit参数指定最大显示条数,\n可选用@selIndex参数指定默认选中索引,\n此函数返回实际显示条数 add(tabButtonPropertiesTable) = @.add({\n text="选项卡按钮标题";\n iconText='\uF0AD';\n foreground="\res\images\icon.png";\n hasCloseButton=true;__/*添加选项卡按钮(plus 控件) 。\n参数 @1 可以用一个表(table)指定部分创建 plus 控件的属性,未指定的属性自动补全,\ntext 属性可用于指定显示文本,foreground 属性可用于指定前景图标。\n如果指定 hasCloseButton 属性为 true,鼠标悬停在选项卡按钮上会显示关闭按钮,\n参数 @1 也可以传入一个 plus 按件初始化属性表数组,用于同时创建多个选项卡按钮。\n\n如果存在多个调用参数,\n自参数 @2 开始作为 loadForm 的调用参数以执行高级选项卡的 loadForm 方法加载子窗体,并绑定当前选项卡按钮。\n\n此函数成功返回新增的选项卡按钮索引。\n如果超出显示范围,新增选项卡按钮会自动替换到最后一个显示位置,\n并将被替换的选项卡按钮移入到下拉菜单内。*/\n}) addItems(.(arrayTabPropertiesTable) = 参数 @arrayTabPropertiesTable 指定一个属性表数组,\n遍历数组中的控件属性表并作为参数调用高级选项卡的 add 方法创建多个选项卡。\n调用参数 @arrayTabPropertiesTable 为 null 或空数组时忽略不执行任何操作 create(.(参数表) = 此函数与 add 函数用法相同\n但创建选项卡以后会同时创建对应的子窗口,\n返回 2 个值,分别为创建的选项卡按钮对象、子窗体对象。\n\n注意,调用 add,create 函数添加选项卡按钮,\n如果超出可见范围,会自动折叠其他选项卡按钮,并将新增的选项卡按钮移动到可见位置。\n所以增加选项卡按钮可能导致选项卡按钮调整位置,选项卡按钮的原索引发生变化 create() = !ui_ctrl_plus. delete(__/*tabIndex*/)) = 删除指定索引的选项卡按钮。\n参数用数值指定选项所在位置索引 deleteByTab(__/*tabButton*/)) = 删除指定的选项卡按钮。\n参数指定选项卡按钮对象 deleteByForm(__/*formPage*/) = 删除指定的选项卡按钮。\n参数指定相同索引位置的子窗体对象 prev() = 切换到上一个选项 next() = 切换到下一个选项 initPopup(.(handleCtrl,transparent) = 初始化为弹出菜单样式\n@handleCtrl指定接收输入事件的控件,\n自动修改该控件的checked属性为是否弹出状态,\ntransparent指定菜单是否透明,\n所有参数可选 popup( = 切换到弹出列表模式,\n用于显示简单的弹出列表或菜单,\n如果当前项目列表数组为空,则无论传入什么参数都会切换到隐藏状态 popup(.(true,x,y) = 弹出列表\n可选使用x,y指定列表左上角在屏幕上的坐标 popup(.(true,ctrl,mode) = 弹出列表\nctrl指定控件,弹出列表显示在该控件边上,\n自动修改该控件的checked属性为是否弹出状态,\n可选使用mode参数指定"up","down","left","right"等显示位置 popup(.(false) = 隐藏列表,并将selIndex置为null\n如果当前项目列表数组为空,则无论传入什么参数都会切换到隐藏状态 show(__/*可选输入显示参数*/) = 显示或隐藏所有选项卡按钮,可选输入以 _SW_ 为前缀的显示参数(数值)。\n参数@1也可以传入 true,false 控制是否显示选项卡 skin = @.skin({\n background = { \n hover = "/res/images/button-hover.png";\n focus = "/res/images/button-focus.png";\n active = "/res/images/button-active.png";\n disabled = 0xFFCCCCCC; \n };\n color = {\n hover = 0xF00000FF;__/*用格式为0xAARRGGBB的16进制数值,指定鼠标放到控件上的字体颜色,\nAA为透明度,RR为红色分量,GG为绿色分量,BB为蓝色分量*/ \n };\n border = { \n hover = {left=5;color=0xFFFF0000;padding=15;} \n }; \n}) clear() = 清空所有选项卡按钮、清空所有加载的子窗口 isVisible() = 选项卡是否可见 onPopup(showing) = @.onPopup = function(showing){ __/*弹出状态变更时触发此事件\n弹出状态@showing参数为true,显示为弹出状态@showing参数为false*/ } onVisualStateChanged(showing) = @.onVisualStateChanged = function(showing){ __/*显示或隐藏时触发此事件\n显示 @showing 参数为 true,隐藏 @showing 参数为false*/ } beforeShowCloseButton(tabButton,rcTabItem,rcCloseButton,dpiScaleX,dpiScaleY) = @.beforeShowCloseButton = function(tabButton,rcTab,rcCloseButton){ __/*返回关闭按钮显示的x,y坐标,需要返回2个值\n不返回值取消显示\n\n参数 tabButton 为请求显示关闭按钮的选项卡按钮。\nrcTab 为选项卡按钮所在的位置区块,::RECT对象,\nrcCloseButton为关闭按钮所在的的区块,::RECT对象\ndpiScaleX,dpiScaleY为X,Y轴上的DPI缩放比例,1表示100%*/ } onMouseHover(tabButton,wParam,lParam) = @.onMouseHover = function(tabButton,wParam,lParam){ __/*鼠标正悬浮于选项卡按钮 tabButton 之上,\nwParam,lParam为窗口消息参数*/ } onMouseLeave(tabButton,wParam,lParam) = @.onMouseLeave = function(tabButton,wParam,lParam){ __/*鼠标离开选项卡按钮 tabButton,\nwParam,lParam为窗口消息参数*/ } onMouseLeave(tabButton,wParam,lParam) = @.onMouseLeave = function(tabButton,wParam,lParam){ __/*鼠标离开选项卡按钮 tabButton,\nwParam,lParam为窗口消息参数*/ } onFocusGot(hLostFocus) = @.onFocusGot = function(hLostFocus){ ..win.setFocus(hLostFocus);__/*得到焦点触发此事件,hLostFocus为失去焦点的窗口句柄*/ } onFocusLost(hFocus) = @.onFocusLost = function(hFocus){ __/*失去焦点触发此事件,hFocus 为得到焦点的窗口句柄*/ } onSelChange(tabIndex,tabButton,formPage) = @.onSelChange = function(tabIndex,tabButton,formPage){ __/*切换选项会触发此事件,tabIndex 为当前选中索引\ntabButton 为当前选项卡按钮对象,formPage 为当前子窗口。\n如果在这里禁用选项卡或 tabButton,则不会自动触发 tabButton 的其他事件。*/ } onOk(tabButton) = @.onOk = function(tabButton){ __/*用户在弹出列表中选择并确认选项,且即将关闭弹出列表*/ } onCancel() = @.onCancel = function(){ __/*用户关闭弹出列表并且未确认选项*/ } oncommand(tabButton,id,event) = @.oncommand = function(tabButton,id,event){ __/*点击选项卡按钮触发此函数\ntabButton 为触发事件的选项卡按钮对象(plus 控件)。\nid 为 按钮的控件 id,event目前值总是 0*/ } onMouseDown(tabButton,wParam,lParam) = @.onMouseDown = function(tabButton,wParam,lParam){ __/*在选项卡按钮 tabButton(plus 控件) 上按下鼠标,即将切换当前选项卡。\nwParam,lParam为窗口消息参数*/ } onMouseUp(tabButton,wParam,lParam) = @.onMouseUp = function(tabButton,wParam,lParam){ __/*在选项卡按钮 tabButton(plus 控件) 上放开鼠标,选项卡切换操作已完成,\nwParam,lParam为窗口消息参数*/ } onDrawString(->->->) = @.onDrawString = function(graphics,text,font,rectf,strformat,brush){ graphics.drawString(text,font,rectf,strformat,brush); __/*自绘所有选项卡控钮上的文本。\n注意 owner 参数指向当前选项卡按钮*/ } onDrawForegroundEnd = @.onDrawForegroundEnd = function(graphics,rc,rcContent){ __/*背景前景绘制后,绘制文本前触发此事件,\ngraphics 为 gdip.graphics 对象(GDI+ 画板),\nrc为客户区 RECT 结构体,rcContent 为去掉内边距后的RECT结构体*/ } onDrawEnd = @.onDrawEnd = function(graphics,rc){ __/*所有绘制操作结束触发此事件,\ngraphics 为gdip.graphics对象(GDI+画板),\nrc为客户区RECT结构体*/ } indexOfTab(__) = 获取选项卡按钮所在的索引位置\n参数指定选项卡按钮对象 indexOfForm(__) = 获取子窗口所在的选项索引位置\n参数指定相同索引位置的子窗体对象 closeButton = 选项卡按钮上动态显示的关闭按钮,这是一个 plus 控件。\n可调用 skin 函数自定义外观样式。\n可通过 beforeShowCloseButton 事件自定义显示坐标。\n注意这是一个 orphanWindow 浮动窗口。\n!ui_ctrl_plus. dropButton = 下拉菜单按钮。\n如果存在超出显示范围的选项卡按钮,这个 dropButton 控件会自动显示。\ndropButton 是一个 plus 控件对象。\n!ui_ctrl_plus. each() = @for(tabButton,formPage,tabIndex in ??.each() ){ __/*遍历高级选项卡的所有选项。\ntabButton 为当前选项卡按钮,formPage 为对应的子窗口,tabIndex 为索引位置\n遍历时不应当执行删除、新增选项,更改当前选项等所有可能改变高级选项卡索引的操作。*/ } query(查询属性表) = @.query(\n text = "标题";\n tabsName = "名字";__/*使用选项卡按钮的指定属性查询对应的子窗口(formPage)。\n如果子窗口是延迟加载状态则会立即加载。\n选项卡的任一属性值与查询条件相同即可,不需要匹配所有查询属性。\n自定义属性建议加上 data 前缀以避免与控件属性混淆。\n也可以用一个字符串参数直接查询选项卡按钮的标题。\n返回选项卡按钮对应的子窗口对象,以及所在选项索引(数值).*/\n) query() = !winform. queryTab(查询属性表) = @.queryTab(text = "标题"__/*使用控件的指定属性查询对应的选项卡按钮,\n选项卡按钮的任一属性值与查询条件匹配即可,不需要满足所有查询条件。\n用户自定义属性建议加上 data 前缀以避免以控件已有属性名称冲突。\n也可以用一个字符串参数直接查询选项卡按钮的标题,\n返回选项卡按钮对象,以及所在索引数值*/) queryTab() = !ui_ctrl_plus. set(.(tabIndex,tabProperties) = 设置 @tabIndex 参数指定索引的选项卡按钮属性。\n@tabProperties 参数指定控件属性表。 setTabs(.(属性名,属性值数组) = 批量设置所有选项卡按钮(plus 控件)的指定属性值。\n参数 @2 应传入一个属性值数组,函数会遍历属性值数组,并设置相同索引的选项卡按钮。\n第 1 个选项卡按钮设置第 1 个属性值,第 2 个选项卡按钮设置第 2 个属性值,\n依此类推。 count = 返回高级选项卡包含的选项总数 getText(__/*tabIndex*/) = 返回指定索引选项卡按钮的显示文本。 disabledText = @.disabledText = {'\uF254';'\uF251';'\uF252';'\uF253';'\uF250'}__/*指定文本时,指定为文本或文本数组则禁用当前选项按钮并显示指定文本,\n同时也会禁止所有选项卡按钮响应事件(但其他选项卡按钮不显示禁用样式),禁止切换选项。\n此属性指定为一个文本数组时,当前选项卡按钮将创建动画逐帧显示数组里的文字图标。\n如果当前选项卡按钮配置了图标文本则使用图标文本( iconText )显示数组内的文字图标,\n\n此属性指定为 null 时,启用当前选项,并恢复控禁用之前的 text、iconText 属性。\n同时其他所有选项卡按钮也会切换到允许响应事件(notify 属性恢复为 true )。\n如果尚未指定当前选项,则获取此属性时总是为 null。*/ disabled = 是否禁用选项卡。\n仅当前选项卡按钮会切换禁用样式,其他选项按钮仅切换是否允许响应事件属性(notify)。\n如果尚未指定当前选项,则获取此属性时总是为 false 。 end intellisense**/