import win; import win.ui.background; import win.ui.ctrl; import gdi; class win.form { ctor( tParam ) begin //实现延迟加载的伪窗口对象 if(tParam[["fake"]]){ if(tParam.thisObject){ //创建真实窗口 this = tParam.thisObject; tParam.thisObject = null; } else{ //返回伪窗口,访问伪窗口的任何属性或方法时创建真实窗口 return { fake = true; loadForm = tParam.loadForm; tParam = tParam; @_fakeMeta; }; } } //这句必须放最前面,以保证自定义控件设计时大小不会被修改 tParam = ..table.mix(tParam,{ left = -1;top = -1;right = 759;bottom = 469; }); this.hInstance = _HINSTANSE; this._mapCommandProc = { lastFreeId = tParam.lastFreeId : 5000;freeIds={} }; this._ctrlId = { lastFreeId = 3;freeIds={} };//控件ID映射关系 this._ctrlHwnd = {}; this._ctrlAutoResize = {}; this._uncontrolledHwnd = {}; this._onlyDirectDrawBackground = {}; this._directDrawBackground = {}; this._tTimeProc = {}; this._tTimeProcEntered = {}; this._tTimeTicks = { lastFreeId = 1;freeIds={} }; this.isDialogMessage = ..win.isDialogMessage; //不允许自定义控件重写的属性,请写在这段代码前面 if( tParam.tParam ){ for(k,v in tParam.tParam){ if(tParam[k]===null){ tParam[k] = v; } } if( tParam.id === null )tParam.id = 0; } else { tParam.id = 0; } tParam.exstyle := 0; tParam.style := 0; var x = tParam.left; var y = tParam.top; var cx = tParam.right - x; var cy = tParam.bottom - y; this._defClientRect = ::RECT( 0, 0, cx, cy); select( tParam.exmode ) { case "toolwindow" { tParam.exstyle |= 0x80/*_WS_EX_TOOLWINDOW*/; } case "none" { tParam.exstyle |= 0; } else { tParam.exstyle |= 0x40000/*_WS_EX_APPWINDOW*/; }; } if(tParam.composited) tParam.exstyle |= 0x2000000/*_WS_EX_COMPOSITED*/ if(tParam.acceptfiles) tParam.exstyle |= 0x10/*_WS_EX_ACCEPTFILES*/ if(tParam.frame) tParam.exstyle |= 0x1/*_WS_EX_DLGMODALFRAME*/ if(tParam.cp) tParam.exstyle |= 0x10000/*_WS_EX_CONTROLPARENT*/ if(tParam.topmost) tParam.exstyle |= 0x8/*_WS_EX_TOPMOST*/ select( tParam.mode ) { case "child" { tParam.style |= 0x40000000/*_WS_CHILD*/ } case "popup" { if(!(tParam.style&0x40000000/*_WS_CHILD*/)) tParam.style |= 0x80000000/*_WS_POPUP*/ ; else { tParam.border = "none"; } } else { tParam.style |= 0x0/*_WS_OVERLAPPED*/; } } if(! (#(tParam.text)) ){ tParam.title = false; } if(tParam.title === false ) tParam.style := 0x80000000/*_WS_POPUP*/ var delTitle = ~0xC00000/*_WS_CAPTION*/; select( tParam.border ) { case "dialog frame"{ tParam.style |= 0x400000/*_WS_DLGFRAME*/; delTitle = ~0x800000/*_WS_BORDER*/; } case "thin" { tParam.style |= 0x800000/*_WS_BORDER*/; delTitle = ~0x400000/*_WS_DLGFRAME*/; } case "none" { //无边框窗口 //取消默认的 0x0/*_WS_OVERLAPPED* 样式 tParam.style := 0x80000000/*_WS_POPUP*/ tParam.style &= ~ 0x800000/*_WS_BORDER*/; tParam.title = false; } else { tParam.style |= 0x40000/*_WS_SIZEBOX*/; } } if(tParam.title===false) { tParam.style &= delTitle //避免去掉标题栏时覆盖了边框设置 } else{ tParam.style |= 0xC00000/*_WS_CAPTION*/ } if(tParam.max!==false) tParam.style |= 0x10000/*_WS_MAXIMIZEBOX*/ else tParam.style &= ~0x10000/*_WS_MAXIMIZEBOX*/ if(tParam.min!==false) tParam.style |= 0x20000/*_WS_MINIMIZEBOX*/ else tParam.style &= ~0x20000/*_WS_MINIMIZEBOX*/ if(tParam.sysmenu!==false) { tParam.style |= 0x80000/*_WS_SYSMENU*/ } else { tParam.style &= ~0x80000/*_WS_SYSMENU*/ } if( tParam.maximize ){ tParam.style |= 0x1000000/*_WS_MAXIMIZE*/; } if( tParam.minimize ){ tParam.style |= 0x20000000/*_WS_MINIMIZE*/ } if( tParam.clipch ){ tParam.style |= 0x2000000/*_WS_CLIPCHILDREN*/; } this@ = _metaProperty; if( ( type( tParam.parent) == "table" ) ){ if(tParam.parent[["_defClientRect"]]) this.parent = tParam.parent; tParam.parent = tParam.parent.hwnd; } if( type( tParam.parent ) != "number" ) tParam.parent = 0; if( tParam[["hwnd"]] || tParam[["createWindowEx"]] ){ this.hwnd = tParam[["hwnd"]] if( !this.hwnd ){ this.hwnd = tParam[["createWindowEx"]](tParam.exstyle,tParam.className,tParam.text,tParam.style , x,y,cx,cy,tParam.parent,tParam.id/*menu*/, _HINSTANSE ); } if( !this.hwnd ) return; this._defWindowProc = function(hwnd, message, wParam , lParam){ return ::CallWindowProc(this._wndproc_c_prev, hwnd, message, wParam , lParam); } } else{ if( ! tParam.className ){ tParam.cls := "AARDIO_FORM" tParam.className = ..win.registerFormClass( tParam.cls ); if( ! tParam.className ){ error("注册窗口类失败1",2); }; this._defWindowProc = ::DefWindowProc; } else { tParam.className = ..win.registerFormClass( tParam.cls,,tParam.className ); if( !tParam.className ) error("注册窗口类失败2",2); this._defWindowProc = function(hwnd, message, wParam , lParam){ return ::CallWindowProc(this._wndproc_c_prev, hwnd, message, wParam , lParam); } } if( tParam.bkLeft != null ){ this.bkLeft = tParam.bkLeft; this.bkRight = tParam.bkRight; this.bkTop = tParam.bkTop; this.bkBottom= tParam.bkBottom; } var rcWnd = ::RECT(x, y, x+cx , y+cy ); ::User32.AdjustWindowRectEx(rcWnd, tParam.style, 0, tParam.exstyle); //client to window cx = rcWnd.right - rcWnd.left; cy = rcWnd.bottom - rcWnd.top; var rcWk = ..win.getWorkArea(tParam.parent); if(x<0){ var sx = rcWk.width(); if(sx>cx){ if(x==-1) x = rcWk.left + (sx-cx)/2; else x = rcWk.left + (sx-cx)+x+2 } else x = rcWk.left; } else { x = rcWk.left + x; } if(y<0){ var sy = rcWk.height(); if(sy>cy){ if(y==-1) y = rcWk.top + (sy-cy)/2; else y = rcWk.top + (sy-cy) + y+2 } else y = rcWk.top; } else { y = rcWk.top + y; } this.hwnd = createWindowEx(tParam.exstyle,tParam.className,tParam.text,tParam.style , x,y,cx,cy,tParam.parent,tParam.id/*menu*/, _HINSTANSE ); if(!this.hwnd) return null,"CreateWindowEx failed!"; if(!..win.title ) ..win.title = tParam.text; } this[["scroll"]] = tParam.scroll; var wndproc = function( hwnd, message, wParam , lParam) { if( this[["wndproc__"]] ) { var result = this.wndproc__( hwnd, message, wParam , lParam ); if( (result !== null) && ( message!=0x2/*_WM_DESTROY*/) )//用非恒等式来排除0,false等逻辑假的值 return result; } var proc = _defaultProc[message] if( proc ){ var result = proc(this,hwnd,message,wParam,lParam) if( result !== null ) return result; } return this._defWindowProc(hwnd,message,wParam,lParam); }; this._wndproc_c = ..raw.tostdcall( wndproc,"addr(addr,INT,ADDR,addr)",this/*设为owner对象*/) this._wndproc_c_prev = ::SetWindowPointer(this.hwnd,0xFFFFFFFC/*_GWL_WNDPROC*/, this._wndproc_c); _forms[this.hwnd] = this; this.background = ..win.ui.background(this); if( tParam.bgcolor !== null ) this.background.setColor( tParam.bgcolor ); if( tParam.image ) this.background.loadImage( tParam.image ); ..win.resetMessage();//移除_WM_QUIT消息,重置消息循环 end; //考虑伪窗口,所有函数应放入 _metaProperty } namespace win.form{ createWindowEx = ::CreateWindowEx; var ctrl_factory = ..win.ui.ctrl.factory _forms = {} //记录所有win.form对象,创建则添加此表,销毁则从表中移除 getForm = function(hwnd){ var winform = _forms[hwnd]; while(!winform){ hwnd = ..win.getParentOwner(hwnd); if(!hwnd) return null; winform = _forms[hwnd]; } return winform; }; getParentForm = function(hwnd){ var winform = _forms[hwnd]; while(!winform){ hwnd = ..win.getParent(hwnd); if(!hwnd) return null; winform = _forms[hwnd]; } return winform; }; /*默认消息处理函数defaultProc{{*/ _defaultProc = { [ 0x113/*_WM_TIMER*/ ] = function(this,hwnd, message, wParam, lParam){ var proc = this._tTimeProc[wParam]; if( proc ){ if( this._tTimeProcEntered[wParam] ) return; this._tTimeProcEntered[wParam] = true; var ret = proc(hwnd,message,wParam,this._tTimeTicks[wParam] ) this._tTimeProcEntered[wParam] = null; if( (ret !== null) && ( ret!== true ) ){ var tick = tonumber(ret) if( !tick ){ this.killtimer(wParam)//移除此定时器 } else { this.settimer(wParam,tick)//重新设定时间间隔 } } } } [ 0x4A/*_WM_COPYDATA*/ ] = function( this,hwnd,message,wParam,lParam ){ if(lParam && this.onCopyData ){ var s,n = ..win.getCopyData(lParam); if( s ){ if( n == 0xffffffff && s[1] == '{'# )s = eval( s ); } return this.onCopyData( s,n ); } } [0xACCC/*_WM_THREAD_COMMAND*/] = function( this,hwnd,message,wParam,lParam ){ if( this.__onThreadCommand ) return this.__onThreadCommand(wParam); } [0xACCE/*_WM_THREAD_CALLBACK*/] = function( this,hwnd,message,wParam,lParam ){ if(!(wParam && lParam) ) return 0; var p = topointer(wParam); var proto = ..raw.str(p);//::User32.SendMessageA var name,struct = ..string.match(proto,"\s*(.+?)\s*(%\(\))"); var unicode; if(!(name&&struct)){ proto = ..string.fromUtf16(p,,true); //::User32.SendMessageW name,struct = ..string.match(proto,"\s*(.+?)\s*(%\(\))"); unicode = true; } if(!(name&&struct)) return 0; struct = ..string.match(struct,"\(\s*\{\s*(.+?)\s*\}\s*\)") : ""; var f = this[name]; if(f){ if(!#struct) return invoke(f,this); var r; var a = topointer(lParam); if(struct=="JSON"){ if(!..JSON) error('未导入 JSON 库!\n\t_WM_THREAD_CALLBACK 接收到 wParam 参数:\n\t '+proto); var json = unicode ? ..string.fromUtf16(a,,-1) : ..raw.str(a); r = invoke(f,this,..table.unpack(..JSON.parse(json)) ); if( this.onThreadCallBackReturn ){ r = this.onThreadCallBackReturn(r) }; } else{ r = invoke(f,this,..raw.convert(a,{ _struct = struct })); if( this.onThreadCallBackReturn ){ r = this.onThreadCallBackReturn(r) }; if(r[["_struct"]]){ ..raw.copy(topointer(lParam),r); return 0; } } return tonumber(r); } } [0xACCD/*_WM_THREAD_CALLWND*/] = function( this,hwnd,message,wParam,lParam ){ return ..thread.applyCallWnd(this,wParam,lParam) } [0x14/*_WM_ERASEBKGND*/] = function(this,hwnd, message, wParam, lParam){ if( this.onEraseBkgnd !== null ){ var ret = this.onEraseBkgnd(hwnd, message, wParam, lParam); if( ret !== null ) return ret; }; if( this.hasBackground ){ this.background.draw( topointer(wParam) ); return 1; } }; [0xA1/*_WM_NCLBUTTONDOWN*/] = function(this,hwnd, message, wParam, lParam){ if( ( wParam >= 0xA/*_HTLEFT*/ && wParam <= 0x11/*_HTBOTTOMRIGHT*/ ) ){ return this.applyDisableDragFullWindow( function(disabled){ if( this.onResizeBorder ){ ret = this.onResizeBorder(wParam, lParam); if( ret!== null ) return ret; } if(disabled){ return this._defWindowProc(hwnd,message,wParam,lParam); } } ) ); } }; [0x47/*_WM_WINDOWPOSCHANGED*/] = function(this,hwnd, message, wParam, lParam){ var pos = ..raw.convert(topointer(lParam), { addr hwnd; addr hwndInsertAfter; int x; int y; int cx; int cy; INT flags; }) var flags = pos.flags; if(flags & 0x40/*_SWP_SHOWWINDOW*/){ if( !this["(dpiScalingInitialized)"] )this.enableDpiScaling("init"); for(hwnd,ctrl in this._ctrlAutoResize ){ if( ctrl.cacheOrphanWindowRect__ ){ var rc = ctrl.cacheOrphanWindowRect__; var l,t = ..win.toScreen(this.hwnd,rc.left,rc.top); var swp = 0x1C/*_SWP_NOACTIVATE | _SWP_NOZORDER | _SWP_NOREDRAW*/; if( ctrl.orphanRestorePending) { swp = 0x40/*_SWP_SHOWWINDOW*/ | swp; ctrl.orphanRestorePending = null; } ..win.setPos( hwnd,l,t,rc.width() ,rc.height() ,,swp); if( ctrl.onSetOrphanWindowPos ) ctrl.onSetOrphanWindowPos(l,t,rc.width() ,rc.height(),swp) ctrl.redraw(); } } } elseif(flags & 0x80/*_SWP_HIDEWINDOW*/){ for(hwnd,ctrl in this._ctrlAutoResize ){ if( ctrl.cacheOrphanWindowRect__ ){ if( ..win.isVisible(ctrl.hwnd) ){ ctrl.show(false); ctrl.orphanRestorePending = true; if( ctrl.onSetOrphanWindowPos ) ctrl.onSetOrphanWindowPos(,,,,0x80/*_SWP_HIDEWINDOW*/) } } } } if(this._onPosChangedWithShadow) return this._onPosChangedWithShadow(flags,pos.hwndInsertAfter,pos.x,pos.y,pos.cx,pos.cy); if(this.onPosChanged) return this.onPosChanged(flags,pos.hwndInsertAfter,pos.x,pos.y,pos.cx,pos.cy); }; [0x18/*_WM_SHOWWINDOW*/] = function(this,hwnd, message, wParam, lParam){ if( hwnd == this.hwnd){ if( this.beforeShowWindow ) this.beforeShowWindow( !!wParam,lParam); if( this._beforeShowWindowInCustom ) this._beforeShowWindowInCustom( !!wParam,lParam); } }; [0x3/*_WM_MOVE*/] = function(this,hwnd, message, wParam, lParam){ if( hwnd == this.hwnd){ if( ..win.isIconic(hwnd) ) return; this.onMoveForm(); } }; [0x02E0/*_WM_DPICHANGED]*/] = function(this,hwnd, message, wParam, lParam){ if( this.onDpiChanged ){ var dpiX,dpiY = ::HIWORD(wParam),::LOWORD(wParam); var rect = ..raw.convert( topointer(lParam),::RECT()); return this.onDpiChanged(dpiX,dpiY,rect); } } [0x5/*_WM_SIZE*/] = function(this,hwnd, message, wParam, lParam){ if( hwnd == this.hwnd){ var dwpFlags = 0x1C;/*_SWP_NOACTIVATE | _SWP_NOZORDER | _SWP_NOREDRAW | _SWP_FRAMECHANGED*/; if(!wParam){ /*_SIZE_RESTORED*/ var st = this["[prevSizeStatus]"]; if(st){ this["[prevSizeStatus]"] = null; if( this.onRestored ) this.onRestored(wParam); if(!this["(dpiScalingInitialized)"] && (st==="minimized")){ this.enableDpiScaling("init"); } } } elseif( wParam == 1/*_SIZE_MINIMIZED*/ ) { this["[prevSizeStatus]"] = "minimized"; if( this.onMinimized ) this.onMinimized(); return; } elseif( wParam == 2/*_SIZE_MAXIMIZED*/ ) { this["[prevSizeStatus]"] = "maximized" dwpFlags = 0x3C;//dwpFlags | _SWP_FRAMECHANGED } var defDlg = this._defClientRect; if(!defDlg) return; var dlg = this.getClientRect(); if( dlg.width() == 0 ){ return;} var scaleX = (dlg.right-dlg.left)/(defDlg.right-defDlg.left); var scaleY = (dlg.bottom-dlg.top)/(defDlg.bottom-defDlg.top); var dpiScaleX,dpiScaleY = (this.dpiScaleX : 1) ,(this.dpiScaleY : 1); var defCtrl; var l,t,r,b,w,h; var ctrlSize = {}; var numCtrls = 0; for(hwnd,ctrl in this._ctrlAutoResize ){ numCtrls++; } var hPosInfo = ::BeginDeferWindowPos(numCtrls); var adjustCtrl = function(ctrl,backOnly){ if( !backOnly && !this._ctrlAutoResize[ctrl.hwnd] ) return; var parent = dlg; var defParent = defDlg; if( ctrl.parent != this ){ var size = ctrlSize[ctrl.parent.hwnd] ; if(size){ parent = ::RECT(0,0,size.cx,size.cy); } else { parent = ctrl.parent.getClientRect(); } defParent = ctrl.parent._defClientRect; }; defCtrl = ctrl._defRect; w = defCtrl.right-defCtrl.left; h = defCtrl.bottom -defCtrl.top; if( ctrl[["dl"]] ){ if( ctrl[["dl"]] < 1 ){ l = parent.left + parent.width() *ctrl[["dl"]]; } else{ l = defCtrl.left * dpiScaleX; } } else l = defCtrl.left * scaleX ; if( ctrl[["dt"]] ){ if( ctrl[["dt"]] < 1 ){ t = parent.top + parent.height()*ctrl[["dt"]]; } else{ t = defCtrl.top * dpiScaleY ; } } else t = defCtrl.top * scaleY ; if( ctrl[["dr"]] ) { if( ctrl[["dr"]] < 1 ){ r = parent.right - parent.width() *ctrl[["dr"]]; } else{ r = parent.right - ( defParent.right - defCtrl.right)* dpiScaleX ; } if( ctrl[["aw"]] == false ) && ( ctrl[["dl"]] == false ) l = r - (w* dpiScaleX); } else { if( ctrl[["aw"]] ) r = defCtrl.right * scaleX ; else r = l+w* dpiScaleX; } if( ctrl[["db"]] ) { if( ctrl[["db"]] < 1 ){ b = parent.bottom - parent.height() *ctrl[["db"]]; } else{ b = parent.bottom - ( defParent.bottom - defCtrl.bottom )* dpiScaleY ; } if( ( ctrl[["ah"]] == false ) && ( ctrl[["dt"]] == false ) ) t = b - (h* dpiScaleY) ; } else{ if( ctrl[["ah"]] ) b = defCtrl.bottom * scaleY; else b = t + h* dpiScaleY; } if(backOnly){ ctrl.setPos(l,t,r-l,b-t); return; } ctrlSize[ctrl.hwnd] = { l;t;r;b; cx = r - l;cy = b - t }; if( !..win.getStyle(ctrl.hwnd,0x40000000/*_WS_CHILD*/) ){ ctrl.cacheOrphanWindowRect__ = ::RECT(l,t,r,b); } else{ if( ctrl.parent == this ){ hPosInfo = ::DeferWindowPos(hPosInfo,ctrl.hwnd,0,..math.floor(l),t, r - l, b - t ,dwpFlags); } } } var hasBackground = this.hasBackground; if(#this._onlyDirectDrawBackground){ hasBackground = true; for(k,ctrl in this._onlyDirectDrawBackground){ adjustCtrl( ctrl,true ); } } if(#this._directDrawBackground){ hasBackground = true; for(k,ctrl in this._directDrawBackground){ adjustCtrl( ctrl,true ); } } if( hasBackground ){ this.background.update(); } this.enumControl( adjustCtrl ); ::EndDeferWindowPos(hPosInfo); for(hwnd,ctrl in this._ctrlAutoResize){ if( ctrl.cacheOrphanWindowRect__ ){ var rc = ctrl.cacheOrphanWindowRect__; var l,t = ..win.toScreen(this.hwnd,rc.left,rc.top); ..win.setPos( ctrl.hwnd,l,t,rc.width() ,rc.height(),,0x14/*_SWP_NOACTIVATE | _SWP_NOZORDER*/); if( ctrl.onSetOrphanWindowPos ) ctrl.onSetOrphanWindowPos(l,t,rc.width() ,rc.height()) if( ctrl.preadjust ) ctrl.preadjust( rc.width(), rc.height(),wParam ); if( ctrl._preadjust ) ctrl._preadjust( rc.width(), rc.height(),wParam ); } else { var size = ctrlSize[hwnd]; if(size){ if( ctrl.parent != this ){ var l,t,r,b = ..table.unpack(size); ..win.setPos( hwnd,..math.floor(l),t, r - l, b - t ,,0x1C/*_SWP_NOACTIVATE | _SWP_NOZORDER | _SWP_NOREDRAW*/ ); } else { ::User32.InvalidateRect(hwnd,null,true); } if( ctrl.preadjust ) ctrl.preadjust( size.cx, size.cy,wParam ); if( ctrl._preadjust ) ctrl._preadjust( size.cx, size.cy,wParam ); } else { ctrl.close(); } } } if( this.preadjust ) this.preadjust( dlg.right-dlg.left,dlg.bottom-dlg.top,wParam); if( this._preadjust ) this._preadjust( dlg.right-dlg.left,dlg.bottom-dlg.top,wParam); for(hwnd,ctrl in this._uncontrolledHwnd){ if( ctrl._preadjust ) ctrl._preadjust(); } if(! ..win.getStyle(this.hwnd,0x40000000/*_WS_CHILD*/) ) this.redraw();//Z Orderd Draw for(hwnd,ctrl in this._ctrlAutoResize ){ var size = ctrlSize[hwnd]; if( ctrl._adjust ) ctrl._adjust( size.cx, size.cy,wParam ); if( ctrl.adjust__ ) ctrl.adjust__( size.cx, size.cy,wParam ); } if( this._adjust ){ this._adjust( dlg.right-dlg.left,dlg.bottom-dlg.top,wParam); } if( this.adjust__ ){ this.adjust__( dlg.right-dlg.left,dlg.bottom-dlg.top,wParam); } if(this._adjustWithShadow){ this._adjustWithShadow( dlg.right-dlg.left,dlg.bottom-dlg.top,wParam); } } }; [0x112/*_WM_SYSCOMMAND*/] = function(this,hwnd, message, wParam, lParam){ if( wParam >= 0xF000 ) { if(wParam==0xF020 && this.onMinimize) return this.onMinimize(lParam); return; } var proc = this._mapCommandProc[wParam] if( proc ) proc(wParam,..win.getMessagePos(lParam)); }; [0x111/*_WM_COMMAND*/] = function(this,hwnd, message, wParam, lParam){ var id = ::LOWORD(wParam); var wmEvent = ::HIWORD(wParam); var proc; if( lParam && lParam!=1 ){ var ctrl = this._ctrlId[id] || this._ctrlHwnd[lParam]; if(ctrl){ if( ctrl[["_precommand"]] ) { ctrl._precommand(id,wmEvent); } var funcname = ctrl[["_commandFuncnames"]][[wmEvent]]; if(#funcname && ctrl[[funcname]]){invoke(ctrl[funcname],ctrl);} if( ctrl[["oncommand"]] ) { ctrl.oncommand(id,wmEvent); return; } } } elseif(id<3){ if( id == 2 ){ if( this.onCancel ) return this.onCancel() if( this.restoreFullScreen && ( !..win.getStyleEx(this.hwnd,0x80000/*_WS_EX_LAYERED*/) ) ) this.fullscreen( false ); } elseif( id == 1 ) if( this.onOk ) return this.onOk() } proc = this._mapCommandProc[id] if(type(proc)==type.function) proc(id,wmEvent); }; [0x10/*_WM_CLOSE*/] = function(this,hwnd, message, wParam, lParam){ if( type(this.onClose) == type.function ){ var ret = this.onClose(hwnd, message, wParam, lParam); if( ret !== null ) return ret; } if(this[["(__continueModal)"]]){ var hwndOwner = ..win.getOwner(this.hwnd); if(hwndOwner){ ..win.enable(hwndOwner,1/*_TRUE*/); ..win.setActive(hwndOwner); } } }; [0x110/*_WM_INITDIALOG*/] = function(this,hwnd, message, wParam, lParam){ this.enableDpiScaling("init") if( type(this.onInitDialog) == type.function ) return this.onInitDialog(hwnd, message, wParam, lParam) }; [0x004E /*_WM_NOTIFY*/] = function(this,hwnd, message, wParam, lParam){ if(lParam){ var nmhdr; var id = wParam; var ctrl = this._ctrlId[id] : this._ctrlHwnd[id]; if(!ctrl){ nmhdr = ..raw.convert(topointer(lParam),::NMHDR() ); ctrl = this._ctrlHwnd[nmhdr.hwndFrom]; } if(ctrl){ var pre,notify = ctrl._prenotify,ctrl.onnotify; if( notify || pre ){ var ptr = topointer(lParam); if(!nmhdr) nmhdr = ..raw.convert(ptr,::NMHDR() ); var code = nmhdr.code; var ret; if( pre ) { /* 属性元表中使用名称 _prenotify,创建对象后使用名称 prenotify, 值只能为 null 或 table,不可指定为函数。 */ if( type(pre)==="table" ) pre = pre[code]; if( pre ) ret = invoke(pre,ctrl,id,code,ptr,nmhdr); } if( notify && ( ret === null) ) ret = ctrl.onnotify(id,code,ptr,nmhdr ) if(ret!==null) return ret; } } } }; [0x115/*_WM_VSCROLL*/] = function(this,hwnd, message, wParam, lParam){ if( lParam ){ var ctrl = this._ctrlHwnd[lParam]; if( ctrl[["oncommand"]] ){ ctrl.oncommand( ctrl.id,::LOWORD (wParam),::HIWORD(wParam) ) } } } [0x312/*_WM_HOTKEY*/] = function(this,hwnd, message, wParam, lParam){ var id = wParam; //这个是注册的时候设定的ID if( this[["_hotkeys"]] && ( type( this[["_hotkeys"]][id] ) == type.function ) ){ this[["_hotkeys"]][id] (id,::LOWORD(lParam),::HIWORD(lParam) ) } } [0x2/*_WM_DESTROY*/] = function(this,hwnd, message, wParam, lParam){ if(this._hasBeenDestroyed){ return; }; this._hasBeenDestroyed = true; this.hasBackground = false; if( this.saveConfigBeforeDestroy ){ this.saveConfigBeforeDestroy (); }; if( this._beforeDestroy ){ this._beforeDestroy (); }; if( this.beforeDestroy){ this.beforeDestroy(); }; if( this._acceleratorTable ){ this._acceleratorTable.destroy(); } var tm = this[["_tTimeProc"]] for(id,v in tm){ ::User32.KillTimer(this.hwnd,id); this[["_tTimeProc"]][id] = null; this[["_tTimeTicks"]][id] = null; } for(hwnd,ctrl in this._ctrlHwnd){ if( ! ctrl.isForm ){ if( ctrl.onDestroy){ ctrl.onDestroy (); ctrl.onDestroy = null; } if( ctrl._onDestroy ) ctrl._onDestroy(); if( ctrl._onDestroy_stdReserved__ ) ctrl._onDestroy_stdReserved__(); if( ctrl[["(bgbrush)"]] ){ ::DeleteObject( ctrl[["(bgbrush)"]] ); ctrl[["(bgbrush)"]] = null; } if( ctrl[["(ownFontHandle)"]] ){ ::DeleteObject( ctrl[["(ownFontHandle)"]] ); ctrl[["(ownFontHandle)"]] = null; } ctrl._closed = true; } } if( this[["(ownFontHandle)"]] ){ ::DeleteObject( this[["(ownFontHandle)"]] ); this[["(ownFontHandle)"]] = null; } for(k,ctrl in this._onlyDirectDrawBackground){ if( ctrl.onDestroy){ ctrl.onDestroy (); ctrl.onDestroy = null; } if( ctrl._onDestroy ) ctrl._onDestroy(); if( ctrl._onDestroy_stdReserved__ ) ctrl._onDestroy_stdReserved__(); } if( this.onDestroy){ this.onDestroy (); this.onDestroy = null; } if( this._onDestroy ) this._onDestroy (); if( this._onDestroy_stdReserved__ ) this._onDestroy_stdReserved__(); if(this._onDestroyInTabs)this._onDestroyInTabs(); if( this[["_atomId"]] ){ this.atom(false);//释放实例占用原子 } if(this[["(__continueModal)"]]){ var hwndOwner = ..win.getOwner(this.hwnd); if(hwndOwner){ ..win.enable(hwndOwner,1/*_TRUE*/); ..win.setActive(hwndOwner); } //退出模态循环,必须发送 _WM_NULL 退出 win.pumpMessage this[["(__continueModal)"]] = null; ::User32.PostMessage(0,0/*_WM_NULL*/,0,0); } _forms[hwnd] = null; this.background.delete(); this.background = null; var parent = this[["_parentForm"]]; if( parent ){ parent._ctrlHwnd[this.hwnd]=null; parent._ctrlId[this.id]=null; ..table.push(parent._ctrlId.freeIds,this.id); parent._ctrlAutoResize[this.hwnd]=null; } if( ..win.getStyle(hwnd,0x80/*_DS_MODALFRAME*/) ) return; if( ..win.getStyle(hwnd,0x40000000/*_WS_CHILD*/) ) { if(this!==..mainForm)return; } if(this._messageOnly) return; if( (..win.autoQuitMessage===false) || (this.autoQuitMessage===false) ) return; for(k,f in _forms){ if( ! f._messageOnly ){ if( f == ..mainForm ) return; if( !..win.getStyle(f.hwnd,0x40000000/*_WS_CHILD*/) && !f._parentForm ) { return; } if( ..ide && ..win.getClass( ..win.getParent(f.hwnd) : 0 ) == "AfxFrameOrView100su") { return; } } } for(k,f in _forms){ ::SendMessage(f.hwnd,0x2/*_WM_DESTROY*/); } ..win.quitMessage(); } [0x138/*_WM_CTLCOLORSTATIC*/ ] = function(this,hwnd, message, wParam, lParam){ var ctrl = this._ctrlHwnd[ lParam ]; var hdc = topointer(wParam) if( ctrl ){ if( type(ctrl.color)==type.number ) ::SetTextColor(hdc,ctrl.color ) ; if(ctrl.transparent) { ::SetBkMode(hdc,1); return tonumber( ::GetStockObject(5) );//NULL_BRUSH } else if( ctrl[["(bgbrush)"]] ){ ::SetBkColor(hdc,ctrl[["(bgcolor)"]] ) ; return ctrl[["(bgbrush)"]]; } } } [0x24/*_WM_GETMINMAXINFO*/] = function(this,hwnd, message, wParam, lParam){ if( this.onGetMinMaxInfo ){ return this.onGetMinMaxInfo(hwnd, message, wParam, topointer( lParam ) ); } } [0x7E/*_WM_DISPLAYCHANGE*/] = function(this,hwnd, message, wParam, lParam){ if( this.getMinMaxInfo && ..win.isZoomed(hwnd) ){ var minMaxInfo = this.getMinMaxInfo(); if(minMaxInfo)..win.setPos(hwnd,,,minMaxInfo.maxSize.x,minMaxInfo.maxSize.y); } } [0x231/*_WM_ENTERSIZEMOVE*/] = function(this,hwnd, message, wParam, lParam){ if( this.onEnterSizeMove ){ return this.onEnterSizeMove(); } this.enterSizeMoveRect = this.getRect(); } [0x232/*_WM_EXITSIZEMOVE*/] = function(this,hwnd, message, wParam, lParam){ if( this.onExitSizeMove ){ return this.onExitSizeMove(); } if ..win.isZoomed(this.hwnd) return; var x,y,cx,cy = this.getPos(); var rc = this.enterSizeMoveRect; if( ( y <= 0 ) && ( cy < rc.height() ) ){ this.setPos(,,rc.width(),rc.height()) }; } [ 0x2C/*_WM_MEASUREITEM*/ ] = function(this,hwnd, message, wParam, lParam){ lParam = topointer(lParam) var item = ::MEASUREITEMSTRUCT(); ..raw.convert(lParam,item); var ctrl; if( item.CtlID ){ ctrl = this._ctrlId[ item.CtlID ]; } elseif( item.CtlType == 0x1/*_ODT_MENU*/ && ..win.ui.menu) { ctrl = ..win.ui.menu; } if( ctrl ? ctrl.onMeasureItem ) { var ret = ctrl.onMeasureItem(item,ctrl.dpiScaleX:1,ctrl.dpiScaleY:1); ::CopyMemoryByStruct(lParam,item,24/* raw.sizeof(item)*/); if( ret !== null ){ return ret; }; } } [ 0x2B/*_WM_DRAWITEM*/ ] = function(this,hwnd, message, wParam, lParam){ var item = ::DRAWITEMSTRUCT(); ..raw.convert(topointer(lParam), item); var ctrl; if( item.CtlID ){ ctrl = this._ctrlId[ item.CtlID ]; } elseif( item.CtlType == 0x1/*_ODT_MENU*/ && ..win.ui.menu) { ctrl = ..win.ui.menu; } if( ctrl ? ctrl.onDrawItem ) { var ret = ctrl.onDrawItem(item,ctrl.dpiScaleX:1,ctrl.dpiScaleY:1); if( ret !== null ){ return ret; }; } } [0x233/*_WM_DROPFILES*/] = function(this,hwnd, message, wParam, lParam){ if( this[["onDropFiles"]] ) this.onDropFiles( ..win.getDropFile(wParam) ); } [0x1C/*_WM_ACTIVATEAPP*/] = function(this,hwnd, message, wParam, lParam){ if( this.onActivateApp ) { return this.onActivateApp(!!wParam,lParam) } if( (!wParam) && this.restoreFullScreen && ( !..win.getStyleEx(this.hwnd,0x80000/*_WS_EX_LAYERED*/) ) ) this.fullscreen( false ); } [0x6/*_WM_ACTIVATE*/] = function(this,hwnd, message, wParam, lParam){ if( this.onActivate ) { return this.onActivate(::LOWORD(wParam),lParam,::HIWORD(wParam)) } } [0x21/*_WM_MOUSEACTIVATE*/] = function(this,hwnd, message, wParam, lParam){ if( this.onMouseActivate ) { return this.onMouseActivate(wParam,::LOWORD(lParam),::HIWORD(lParam)) } } [0x201/*_WM_LBUTTONDOWN*/] = function(this,hwnd, message, wParam, lParam){ if(this.onMouseDown) return this.onMouseDown(wParam,lParam); }; [0x202/*_WM_LBUTTONUP*/] = function(this,hwnd, message, wParam, lParam){ if(this.onMouseClick) return this.onMouseClick(wParam,lParam); }; [0x203/*_WM_LBUTTONDBLCLK*/] = function(this,hwnd, message, wParam, lParam){ var cb = this.onMouseDoubleClick || this.onMouseDoubuleClick; if(cb) return invoke(cb,this,wParam,lParam); }; [0xACCF/*_WM_TRAYMESSAGE*/] = function(this,hwnd, message, wParam, lParam){ var cb = this.onTrayMessage[[lParam]]; if(cb) return invoke(cb,this.onTrayMessage,wParam); }; [0x11/*_WM_QUERYENDSESSION*/] = function(this,hwnd,message,wParam,lParam){ if( this.beforeSystemEndSesssion ){this.beforeSystemEndSesssion ();}; if( this.saveConfigBeforeDestroy ){this.saveConfigBeforeDestroy ();}; this.close() ..win.quitMessage(); ..publish("beforeSystemEndSesssion",wParam,lParam) } } var defaultProc = _defaultProc; var onCtlColor = defaultProc[0x138/*_WM_CTLCOLORSTATIC*/ ]; defaultProc[0x133/*_WM_CTLCOLOREDIT*/] = onCtlColor; defaultProc[0x135/*_WM_CTLCOLORBTN*/] = onCtlColor; defaultProc[0x134/*_WM_CTLCOLORLISTBOX*/] = onCtlColor; defaultProc[0x114/*_WM_HSCROLL*/] = defaultProc[0x115/*_WM_VSCROLL*/] /*}}*/ _metaProperty = ..win.ui.ctrl.metaProperty( _eq = lambda(form) owner.hwnd == form.hwnd; isForm = { _get = function(){ return true } }; text = { _get = function(){ return ..win.getText( owner[["hwnd"]] ); } _set = function(v){ ..win.setText( owner[["hwnd"]],tostring(v) ); } }; getForm = function(){ return owner; }; preloadForm = function(...){ if( (...)[["hwnd"]] || (...===null) ) return owner.loadForm(...); //custom 控件 var this = owner; var args = {...}; return ..win._form({ fake = true; loadForm = function(){ return this.loadForm(..table.unpackArgs(args)); } } ) }; loadForm = function(path,...){ return ..win.loadForm(path,,owner,... ); }; loadcode = function(path,...){ return ..win.loadForm(path,,owner,... ); }; getCtrlById = function(id){ return owner._ctrlId[id] }; getCtrl = function(hwnd){ var cs = owner._ctrlHwnd; var c = cs[hwnd] while(!c){ hwnd = ..win.getParentOwner(hwnd); if(!hwnd) return null; c = cs[hwnd]; } return c; }; _freeCommandId = function(id){ owner._mapCommandProc[id] = null; ..table.push(owner._mapCommandProc.freeIds,id); }; _getFreeCommandId = function(){ var lastFreeId = ..table.pop(owner._mapCommandProc.freeIds,1); if(!lastFreeId){ lastFreeId = owner._mapCommandProc.lastFreeId; owner._mapCommandProc.lastFreeId++; } return lastFreeId; }; registCommand = function(proc,oid){ if( oid === null ){ var free = owner._getFreeCommandId(); owner._mapCommandProc[free] = proc; return free; } else { if( oid > owner._mapCommandProc.lastFreeId ) owner._mapCommandProc.lastFreeId = oid + 1; owner._mapCommandProc[oid] = proc; return oid } }; redraw = function(){ if(owner[["menu"]])owner[["menu"]].redraw(); ::User32.InvalidateRect(owner[["hwnd"]],null,true); return ::UpdateWindow(owner[["hwnd"]]); }; redrawBackground = function(rect){ if( !owner.background ) return; owner.background.update(); owner.invalidate(rect); return owner.update(); }; show = function(flag) { //必须在 win.show 前面避免自定义控件不刷新 if( (flag!=6/*_SW_MINIMIZE*/) && (!owner["(dpiScalingInitialized)"] )){ owner.enableDpiScaling("init"); } ..win.show(owner[["hwnd"]],flag); if( owner[["(__continueModal)"]] ){ hwndOwner = ..win.getOwner( owner.hwnd) if(hwndOwner && (hwndOwner!=owner[["hwnd"]]) ){ ..win.enable(hwndOwner,!( flag === null || flag) ); if( !flag && flag !== null ) ..win.setActive(hwndOwner); } ..win.setActive(owner.hwnd); } if( owner.getMinMaxInfo && ..win.isZoomed(owner[["hwnd"]]) ){ var minMaxInfo = owner.getMinMaxInfo(); if(minMaxInfo) ..win.setPos(owner[["hwnd"]],,,minMaxInfo.maxSize.x,minMaxInfo.maxSize.y); } if(owner.hasDirectDrawBackground()){ owner.redrawBackground(); } }; doModal = function(hwndOwner,swFlags){ if(!hwndOwner){ hwndOwner = ..win.getOwner( owner.hwnd) } else if(type(hwndOwner)==type.table){ hwndOwner = hwndOwner.hwnd;//winform.hwnd } if(hwndOwner){ ..win.setOwner(owner.hwnd,hwndOwner); } owner.modifyStyle(0,0x80/*_DS_MODALFRAME*/) owner[["(__continueModal)"]] = true; ::SendMessageInt(owner[["hwnd"]],0x110/*_WM_INITDIALOG*/,0,0); owner.show(swFlags); if(!owner.onCancel) owner.onCancel = function(){ owner.endModal(); } if(!owner.onOk) owner.onOk = function(){ for(name,ctrl in owner.eachControl() ){ if(ctrl.default && ctrl.oncommand) return ctrl.oncommand(); } } while(owner[["(__continueModal)"]]){ ..win.pumpMessage(); } if( hwndOwner ) { ..win.enable(hwndOwner,1/*_TRUE*/); ..win.setActive(hwndOwner); ..win.setPos(owner.hwnd,,,,,,0x10/*_SWP_NOACTIVATE*/|0x80/*_SWP_HIDEWINDOW*/); } owner.close(); return owner[["dialogResult"]]; }; endModal = function(result){ if(!..win.isWindow(owner.hwnd)){ return; } owner[["dialogResult"]] = result; owner.close(); }; continueModal = { _get = function(){ return owner[["(__continueModal)"]]; } }; transparent = { _set = function(v){ if(!v){ owner.modifyStyleEx(0x80000/*_WS_EX_LAYERED*/); } else{ owner.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/); } } _get = function(ownerCall){ if(ownerCall) return owner.setLayered;//@Deprecated return !!..win.getStyleEx(owner[["hwnd"]],0x80000/*_WS_EX_LAYERED*/) } }; transparentColor = { _set = function(v){ if(v===null){ owner.modifyStyleEx(0x80000/*_WS_EX_LAYERED*/); } else{ owner.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/); ::User32.SetLayeredWindowAttributes( owner[["hwnd"]],v,0,1); } } _get = function(){ var c = {INT v}; var f = {INT v}; if(::User32.GetLayeredWindowAttributes(owner[["hwnd"]],c,,f)){ if(f.v===1) return c.v; } } }; opacity = { _set = function(v){ if(owner[["setOpacity"]]) return owner.setOpacity(v); if(v===null){ owner.modifyStyleEx(0x80000/*_WS_EX_LAYERED*/); if( owner._shadowWindow ) owner._shadowWindow.setOpacity(null); } else{ owner.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/); if( owner._shadowWindow ) owner._shadowWindow.setOpacity(v); ::User32.SetLayeredWindowAttributes( owner[["hwnd"]],0,v,2); } } _get = function(){ if(owner[["getOpacity"]]) return owner.getOpacity(); var a = {BYTE v}; var f = {INT v}; if(::User32.GetLayeredWindowAttributes(owner[["hwnd"]],,a,f)){ if(f.v===2) return a.v; } } }; setLayered = function(alpha,clr){//@Deprecated if(alpha === true ){ owner.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/); } elseif( alpha === false ){ owner.modifyStyleEx(0x80000/*_WS_EX_LAYERED*/); } elseif( alpha !== null ){ owner.opacity = alpha; } elseif( clr !== null ){ owner.transparentColor = clr; } }; bgcolor = { _get = function(){ return owner.background.getColor(); } _set = function( v ){ owner.background.setColor( v ) } }; onDrawBackground = { _get = function(){ return null;} _set = function( v ){ owner[["onDrawBackground"]] = v; owner.hasBackground = true; } }; image = { _get = function(){ return owner.background.getBitmap(); } _set = function( v ){ if(type(v) == type.string ){ owner.background.loadImage( v ) return; } owner.background.setBitmap( v,true ) } }; getBitmap = function(h,delPrev=true){ return owner.background.getBitmap(); }; setBitmap = function(h,delPrev=true){ return owner.background.setBitmap(h,delPrev); }; setImage = function(h,delPrev=true){ return owner.background.setBitmap(h,delPrev);// 请使用 setBitmap替代 }; setInterval = function(func,elapse,...){ if( type(elapse) != "number" ) { func,elapse = elapse,func; if( type(elapse) != "number" ) error("参数@2指定了错误的延时值",2); } if( !func ) error("参数@1未指定回调函数",2); var args = {...} if(..table.count(args)){ var f = func; func = function(){ return f( ..table.unpackArgs(args) ); } } var lastFreeId = ..table.pop( owner._tTimeTicks.freeIds,1) ; if(!lastFreeId){ lastFreeId = owner._tTimeTicks.lastFreeId; owner._tTimeTicks.lastFreeId++; } owner[["_tTimeProc"]][lastFreeId] = func; owner[["_tTimeTicks"]][lastFreeId] = elapse; if( ::User32.SetTimer(owner.hwnd,lastFreeId,elapse,null) ) return lastFreeId; }; changeInterval = function(id,elapse,func){ if( owner[["_tTimeProc"]][id] ){ ::User32.SetTimer(owner.hwnd,id,elapse,null ) owner[["_tTimeTicks"]][id] = elapse; if( func ){ owner[["_tTimeProc"]][id] =func; } return true; } }; clearInterval = function(id){ if( id === null ) return; if( owner[["_tTimeProc"]][id] ){ ::User32.KillTimer(owner.hwnd,id); owner[["_tTimeProc"]][id] = null; owner[["_tTimeTicks"]][id] = null; owner[["_tTimeProcEntered"]][id] = null; ..table.push(owner._tTimeTicks.freeIds,id); return true; } }; setTimeout = function(code,elapse=0,...){ if( type(elapse) != "number" ) { code,elapse = elapse,code; if( type(elapse) != "number" ) error("参数@2指定了错误的延时值",2); } if( !code ) error("参数@1未指定回调函数",2); if( type(code)=="string" ) { code,err = loadcode(code) if(!code)error(err,2) } var args = {...} var this = owner; return owner.setInterval ( function(hwnd,msg,id){ this.killtimer(id) code( ..table.unpackArgs(args) ); },elapse ) }; reghotkey = function( func , mod,vk ){ if(! owner[["_hotkeys"]] ) owner[["_hotkeys"]] = {}; if( type(vk) != type.number ) error("请使用参数@3指定虚拟键码",2); var id = ..table.push( owner[["_hotkeys"]] ,func); //保存回调函数 if( ::User32.RegisterHotKey(owner.hwnd,id,mod,vk) ) return id; owner[["_hotkeys"]][id] = null; }; unreghotkey = function(idEvent){ if( idEvent ? owner[["_hotkeys"]][idEvent] ){ ::User32.UnregisterHotKey(owner.hwnd,idEvent); owner[["_hotkeys"]][idEvent] = null; } }; hit = function(method){ if(method)invoke(owner["hit" + ..string.replace(method,"^\w",..string.upper)],owner) }; hitCaption = function () { var hwnd = ..win.getRoot(owner.hwnd); //优先考虑双击取消最大化,最大化拖动意义不大 if( ..win.isZoomed(hwnd) || owner.restoreFullScreen ) return; owner.setTimeout( function(){ ..win.releaseCapture(); ::SendMessageInt( hwnd, 0xA1/*_WM_NCLBUTTONDOWN*/ , 0x2/*_HTCAPTION*/, 0/*不指定坐标,避免HTMLayout重入事件*/ ); } ) }; hitClose = function () { var hwnd = ..win.getRoot(owner.hwnd); ::PostMessage(hwnd,0x10/*_WM_CLOSE*/,0,0); }; hitMin = function () { var hwnd = ..win.getRoot(owner.hwnd); ::PostMessage(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF020/*_SC_MINIMIZE*/, 0); }; hitMax = function(){ var hwnd = ..win.getRoot(owner.hwnd); var zoomed = ..win.isZoomed(hwnd); if(zoomed) ::PostMessage(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF120/*_SC_RESTORE*/, 0); else ::PostMessage(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF030/*_SC_MAXIMIZE*/,0); return !zoomed; }; hitTopleft = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/, 0xF004/*_SC_SIZE | _WMSZ_TOPLEFT*/,0xD/*_HTTOPLEFT*/) ) }; hitTop = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF003 ,0xC/*_HTTOP*/ ) ) }; hitTopright = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF005,0xE/*_HTTOPRIGHT*/ ) ) }; hitLeft = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF001,0xA/*_HTLEFT*/ ) ) }; hitRight = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF002,0xB/*_HTRIGHT*/ ) ) }; hitBottomleft = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF007,0x10/*_HTBOTTOMLEFT*/ ) ) }; hitBottom = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF006,0xF/*_HTBOTTOM*/ ) ) }; hitBottomright = function () { var hwnd = owner.hwnd; if( ..win.isZoomed(hwnd) ) return; owner.applyDisableDragFullWindow( lambda() ::SendMessageInt(hwnd, 0x112/*_WM_SYSCOMMAND*/,0xF008,0x11/*_HTBOTTOMRIGHT*/ ) ) }; cmdTranslate = function(hwnd,message,wParam,lParam){ if( message == 0x111/*_WM_COMMAND*/ ){ defaultProc[0x111/*_WM_COMMAND*/](owner,hwnd,message,wParam,lParam); } }; nextControl = function(k){ var k,v = ..table.next(owner,k); while(k){ if(v[["hwnd"]] && v.className && owner._ctrlHwnd[v[["hwnd"]]] )return k,v; k,v = ..table.next(owner,k); } }; eachControl = function(cls,pattern){ var next; var this = owner; next = function(name){ var k,v = this.nextControl(name); if(!k) return; if(( v[["hwnd"]] && (v.className) && (!cls || cls == v.cls) && (!pattern || ..string.find(k,pattern)) ) ){ return k,v; } return next(k); } return next; }; enumControl = function(proc,cls){ var this = owner; var enumControl; enumControl = function(hParent){ for hwnd in ..win.eachChild(hParent) { var ctrl = this._ctrlHwnd[hwnd] if( (ctrl) && (!cls || cls == ctrl.cls) ){ proc(ctrl); } if( ..win.getChild(hwnd) ) enumControl(hwnd); } } enumControl(this.hwnd); for(hwnd,ctrl in this._ctrlHwnd){ if( !..win.getStyle(hwnd,0x40000000/*_WS_CHILD*/) ) { if(!..win.isWindow(hwnd)) { ctrl.close(); continue; } if(!cls || cls == ctrl.cls) proc(ctrl); enumControl(hwnd); } }; }; eachControlEx = function(cls){ var ctrlHwnd = owner._ctrlHwnd; var hwnd,ctrl; var next; next = function(){ hwnd,ctrl = ..table.next(ctrlHwnd,hwnd); if( (hwnd===null) || (!cls || cls == ctrl.cls) ){ return hwnd,ctrl; } if(hwnd) return next(); } return next; }; bindConfig = function(cfg,fields){ if( type(cfg.save) != "function" ) error("无效配置文件",2); var winform = owner; if(fields){ cfg.afterLoad = function(){ for(name,ctrl in winform.eachControl() ){ var v = fields[name] : fields[ctrl.cls] if( v ) { if(type(v) == "table"){ for(n,v2 in v){ if( ..string.find(name,n) ) { fields[name] = v2; v = v2; if(cfg[name]!==null){ ctrl[v] = cfg[name];} else {cfg[name]= ctrl[v]}; continue 2; } } continue; } if(cfg[name]!==null){ ctrl[v] = cfg[name];} else {cfg[name]= ctrl[v]}; } }; } cfg.afterLoad(); cfg.save(); } if(winform.afterConfigLoad) winform.afterConfigLoad(cfg); cfg.beforeSave = function(){ if(!..win.isWindow(winform.hwnd))return; if(fields){ for(name,ctrl in winform.eachControl() ){ var v = fields[name] : fields[ctrl.cls] if( v ) cfg[name] = ctrl[v]; } } if(winform.beforeConfigSave) winform.beforeConfigSave(cfg); }; winform.saveConfigBeforeDestroy = function(){ cfg.beforeSave(); }; }; setIcon = function(small,big){ if( type.isString(small) ) small = ..com.picture.loadBitmap(small); if( type.isString(big) ) big = ..com.picture.loadBitmap(big); small = ::User32.SendMessageP( owner.hwnd,0x80/*_WM_SETICON*/,0,small:big); big = ::User32.SendMessageP( owner.hwnd,0x80/*_WM_SETICON*/,1,big:small); return small,big; }; fullscreen = function(fs){ var hwnd = owner.hwnd; if( fs === null ) fs = !owner.restoreFullScreen; if( fs ){ if( owner.restoreFullScreen ) return owner.restoreFullScreen; var restoreFullScreen = { style = ..win.getStyle(hwnd, 0x40C40000/*_WS_CAPTION | _WS_BORDER | _WS_DLGFRAME | _WS_CHILD | _WS_SIZEBOX*/ ); parent = ..win.getParent(hwnd); own = ..win.getOwner(hwnd); top = ..win.getStyleEx(hwnd,0x8/*_WS_EX_TOPMOST*/); placement = ..win.getPlacement(hwnd); hwnd = hwnd; } if(restoreFullScreen.placement.showCmd == 0x2/*_SW_SHOWMINIMIZED*/){ return; } var hOwner = ..win.getParent(hwnd); ..win.setParent( hwnd,..win.getDesktop() ) owner.modifyStyle( restoreFullScreen.style ) ..win.setRect(hwnd,..win.getMonitorInfo( hOwner : hwnd ).rcMonitor); ..win.setForeground( hwnd ); ..win.setActive( hwnd ); ..win.setTopmost( hwnd ); owner.restoreFullScreen = restoreFullScreen; } else { if( owner.restoreFullScreen ){ with( owner.restoreFullScreen ){ if(parent)..win.setParent( hwnd, parent ); if(own)..win.setOwner(hwnd,own); owner.modifyStyle(,style); placement.update(); if( !top ){ ..win.setTopmost( hwnd,false ) } } owner.restoreFullScreen = null; } } if(owner.onSetOrphanWindowPos){ var x,y,cx,cy = ..win.getPos(hwnd); owner.onSetOrphanWindowPos(x,y,cx,cy,0x14); } return owner.restoreFullScreen;; }; getScale = function(){ var dpiScaleX,dpiScaleY = (owner.dpiScaleX : 1) ,(owner.dpiScaleY : 1); var defDlg = owner._defClientRect; if(!defDlg) return; var dlg = owner.getClientRect(); return ((dlg.right-dlg.left)/(defDlg.right-defDlg.left)),((dlg.bottom-dlg.top)/(defDlg.bottom-defDlg.top)),dpiScaleX,dpiScaleY; }; applyDisableDragFullWindow = function(callback){ if( ( owner.disableDragFullWindow === null && owner.hasBackground && ! ..win.getStyle(owner.hwnd,0x2000000/*_WS_CLIPCHILDREN*/) ) || owner.disableDragFullWindow ){ var status = { bool fullwindow}; ::SystemParametersInfo(0x26/*_SPI_GETDRAGFULLWINDOWS*/,0,status,0); if( status.fullwindow ){ ::SystemParametersInfo( 0x25/*_SPI_SETDRAGFULLWINDOWS*/,0,{},0); var r = callback(true); ::SystemParametersInfo( 0x25/*_SPI_SETDRAGFULLWINDOWS*/,1,{},0); return r; } } return callback(); }; hasDirectDrawBackground = function(){ return owner.onDrawBackground || #owner._onlyDirectDrawBackground || #owner._directDrawBackground; }; directDrawBackground = function(hMemDc,graphics,rc){ if( owner.onDrawBackground ){ owner.onDrawBackground(hMemDc,rc); } var ctrlBkOnly = owner._onlyDirectDrawBackground; var ctrlBk = owner._directDrawBackground; var ctrl; for(i=1;#ctrlBkOnly;1){ ctrl = ctrlBkOnly[i]; ctrl.onDirectDrawBackground(hMemDc,graphics) } var isVisible = ..win.isVisible; for(i=1;#ctrlBk;1){ ctrl = ctrlBk[i]; if( isVisible(ctrl.hwnd) ) ctrl.onDirectDrawBackground(hMemDc,graphics) } if( owner.onDrawBackgroundEnd){ owner.onDrawBackgroundEnd(hMemDc,rc); } }; onMoveForm = function(){ for(hwnd,ctrl in owner._ctrlAutoResize ){ if( ctrl.cacheOrphanWindowRect__ ){ var rc = ctrl.cacheOrphanWindowRect__; var l,t = ..win.toScreen(owner.hwnd,rc.left,rc.top); ..win.setPos( hwnd,l,t,rc.width() ,rc.height() ,,0x14/*_SWP_NOACTIVATE | _SWP_NOZORDER*/ ); if( ctrl.onSetOrphanWindowPos ) ctrl.onSetOrphanWindowPos(l,t,rc.width() ,rc.height()) } if(ctrl.isForm){ ctrl.onMoveForm(); } } }; remove = function(name){ var ctrl = name; if type(name)==="string" { ctrl = owner[name]; owner[name] = null; } if(ctrl){ if( ctrl[["hwnd"]] ? ctrl.close ){ ctrl.close(); } elseif(ctrl[["onlyDirectDrawBackground"]]){ var i = ..table.removeByValue(owner._onlyDirectDrawBackground,ctrl); } } }; this = lambda() owner; clear = function(){ for(h,c in owner.eachControlEx() ) c.close();}; add = function( tParam,parentCtrl ) { var parent = parentCtrl : owner; var dpiScaleX,dpiScaleY = (parent.dpiScaleX : 1) ,(parent.dpiScaleY : 1); if(tParam[["hwnd"]]){ owner._ctrlHwnd[tParam.hwnd] = tParam; owner._uncontrolledHwnd[tParam.hwnd] = tParam; tParam[["parent"]] = owner; tParam[["_parentForm"]] = owner; tParam[["dpiScaleX"]] = dpiScaleX; tParam[["dpiScaleY"]] = dpiScaleY return; } var cls = tParam[["cls"]];//注意后面的 cls = opt.cls; if( cls && ..win.ui.ctrl[ cls ]){ //容错写法不入文档,创建单个控件直接返回控件对象 var k = (parent[[ cls ]] === null ) ? cls : 1; var r = parent.add({ [k] = tParam}); return r[k]; } var zorder,zorderBk = {},{}; for name,opt in tParam{ cls = opt.cls; if(opt.z===null) opt.z = #zorder + 1; ..table.push( (cls=="bk")||(cls=="bkplus") ? zorderBk :zorder,{name;opt}); } ..table.sort(zorder,lambda(b) owner[2].z < b[2].z); if(#zorderBk){ ..table.sort(zorderBk,lambda(b) owner[2].z < b[2].z); zorder = ..table.append(zorderBk,zorder) } var ctrl; var defParent = parent._defClientRect : parent._defRect; var result = {}; for(i=1;#zorder ){ var name = zorder[i][1]; var opt = zorder[i][2]; if(opt.anchors) opt.dl,opt.dt,opt.dr,opt.db = opt.left,opt.top,opt.right,opt.bottom; //计算位置参数 var width = opt.width; if( width!==null ){ if( opt.left!==null ) opt.right = opt.left + width; elseif( opt.right!==null ) opt.left = opt.right - width; } else{ if( opt.right === null && opt.marginRight === null) opt.marginRight = 0; if( opt.left === null && opt.marginLeft === null) opt.marginLeft = 0; } if( opt.marginRight !== null ){ if( opt.marginRight < 1 ){ opt.right = defParent.right - defParent.width() * opt.marginRight; opt.dr = opt.marginRight ? opt.marginRight : 1; } else { opt.right = defParent.right - opt.marginRight; opt.dr = 1; } } if( opt.marginLeft !== null ){ if( opt.marginLeft < 1 ){ opt.left = defParent.left + defParent.width() * opt.marginLeft; opt.dl = opt.marginLeft ? opt.marginLeft : 1 } else { opt.left = defParent.left + opt.marginLeft; opt.dl = 1; } } if( opt.left===null ){ if( opt.right !== null ) opt.left = opt.right - (width:0); else opt.left = 0; } if( opt.right===null ){ opt.right = ( opt.left : 0) + (width:0); } opt.width = null; opt.marginLeft = null; opt.marginRight = null; //计算位置参数 var height = opt.height; if( height!==null ){ if( opt.top!==null ) opt.bottom = opt.top + height; elseif( opt.bottom!==null ) opt.top = opt.bottom - height; } else{ if( opt.bottom === null && opt.marginBottom === null) opt.marginBottom = 0; if( opt.top === null && opt.marginTop === null) opt.marginTop = 0; } if( opt.marginBottom !== null ){ if( opt.marginBottom < 1 ){ opt.bottom = defParent.bottom - defParent.height() * opt.marginBottom; opt.db = opt.marginBottom ? opt.marginBottom : 1 } else { opt.bottom = defParent.bottom - opt.marginBottom; opt.db = 1; } } if( opt.marginTop !== null ){ if( opt.marginTop < 1 ){ opt.top = defParent.top + defParent.height() * opt.marginTop; opt.dt = opt.marginTop ? opt.marginTop : 1 } else { opt.top = defParent.top + opt.marginTop; opt.dt = 1; } } if( opt.top===null ){ if( opt.bottom!== null ){ opt.top = opt.bottom - (height:0); } else { opt.top = 0; } } if( opt.bottom===null ){ opt.bottom = ( opt.top : 0) + (height:0); } opt.height = null; opt.marginTop = null; opt.marginBottom = null; if(!opt.id) { opt.id = ..table.pop(owner._ctrlId.freeIds,1); if(!opt.id){ opt.id = owner._ctrlId.lastFreeId; owner._ctrlId.lastFreeId = owner._ctrlId.lastFreeId + 1; } } opt[["parent"]] = parent; opt.hInstance = owner.hInstance; ctrl = ctrl_factory.create(opt); if(!ctrl)continue ; if( type(name) == type.string ){ var conflict = parent[name]; if( conflict[["hwnd"]] && conflict.close ){ conflict.close(); } parent[name] = ctrl; } result[name] = ctrl; owner._ctrlId[opt.id] = ctrl; ctrl[["id"]] = opt.id; ctrl[["parent"]] = parent; ctrl[["_parentForm"]] = owner; if( !ctrl.hwnd ){ if(ctrl.onlyDirectDrawBackground){ if(!(ctrl.setFont)) ctrl.setFont = function(){}; ..table.push( owner._onlyDirectDrawBackground,ctrl ); ctrl.setPos(opt.left,opt.top,opt.right-opt.left,opt.bottom-opt.top); ctrl_factory.onCreateComplete(ctrl,dpiScaleX,dpiScaleY); owner.hasBackground = true; continue; } ctrl.hwnd = createWindowEx (opt.exstyle, opt.cls , opt.text , opt.style ,opt.left,opt.top,opt.right - opt.left , opt.bottom - opt.top, parent.hwnd , opt.id , opt.hInstance ) } else { ..win.modifyStyle(ctrl.hwnd,,opt.style | 0x40000000/*_WS_CHILD*/); ..win.setParent(ctrl.hwnd,parent.hwnd); ..win.setPos(ctrl.hwnd,opt.left,opt.top,opt.right - opt.left , opt.bottom - opt.top,0x1/*_HWND_BOTTOM*/); } owner._ctrlHwnd[ctrl.hwnd] = ctrl if( (opt.autoResize === null) || (opt.autoResize) ) owner._ctrlAutoResize[ctrl.hwnd] = ctrl; ctrl_factory.onCreateComplete(ctrl,dpiScaleX,dpiScaleY); if(owner["(dpiScalingInitialized)"]) ctrl.reloadScale(); } if( owner._onControlCreated ) owner._onControlCreated(result); if( owner.onControlCreated ) owner.onControlCreated(result); return result; }; ) _metaProperty.addtimer = _metaProperty.setInterval; _metaProperty.settimer = _metaProperty.changeInterval; _metaProperty.killtimer = _metaProperty.clearInterval; _metaProperty.clearTimeout = _metaProperty.clearInterval; _metaProperty.hitmin = _metaProperty.hitMin; _metaProperty.hitmax = _metaProperty.hitMax; _fakeMeta = { _float = true; _get = function(k){ var tParam = owner.tParam; owner.tParam = null; owner@ = null; var form; if(owner.loadForm){ form = owner.loadForm(); ..table.assign(owner,form); owner@ = form@; } else{ form = ..win._form({ fake = true; thisObject = owner; tParam = tParam; }) } if(owner.onCreated) owner.onCreated(form); return owner[k] } _set = function(k,v){ if(k === "onCreated" ) owner[[k]] = v; else{ var hwnd = owner.hwnd;//触发上面的 _get 元方法 owner[k] = v; } } } } win._form = win.form; namespace win.ui{ waitCursor = function(wait,hCur){ if( wait ){ if(hCur===null) hCur = ::User32.LoadCursor(null,0x7F02/*_IDC_WAIT*/); ::User32.SetCursor( hCur ); ..win._form._defaultProc[0x20/*_WM_SETCURSOR*/] = function(this,hwnd, message, wParam, lParam){ ::User32.SetCursor( hCur ); return true; } if( type(wait) = type.function ){ wait(); ..win._form._defaultProc[0x20/*_WM_SETCURSOR*/] = null; } } else { ..win._form._defaultProc[0x20/*_WM_SETCURSOR*/] = null; ::User32.SetCursor( ::User32.LoadCursor(null,0x7F00/*_IDC_ARROW*/) ); } } form = ..win.form; isForm = lambda(v) v@===form._metaProperty; } /**intellisense() win.ui.waitCursor(__) = 参数为true显示等待光标,false取消,\n参数也可以仅传入一个函数,执行该函数并在执行期间显示等待光标\n可选使用参数@2指定其他光标句柄 win.ui.isForm(__) = 检测输入参数是否win.form窗体对象 win.form = 在标准库 win.ui 中定义的创建窗体的类,\n窗体对象以及窗体创建的控件对象可作为参数传入其他线程,\n跨线程调用窗体对象的成员函数时将转发到创建窗口的线程执行。 win._form = 指向原始的 win.form。\n win.loadForm 函数会暂时修改 win.form函数 并注入代码修改默认行为,例如修改父窗口,\n非必要尽量不要替换 win.form,如果必须替换时请注意:\n替换 win.form 的类必须继承 win._form 对象的所有属性、方法、命名空间的静态成员。 win.form.getForm(__/*控件或窗口句柄*/) = 在上级父窗口或所有者窗口中查找最接近的form对象 win.form.getParentForm(__/*控件或窗口句柄*/) = 在上级父窗口中查找最接近的form对象 win.form._defaultProc = @._defaultProc[__/*消息ID*/] = function(this,hwnd, message, wParam, lParam){\n \n} win.form.createWindowEx = @.createWindowEx = function(exStyle,className,windowName,style,x,y,width,height,hwndParent,hMenu,hlnstance,lpParam){ return ::CreateWindowEx(exStyle,className,windowName,style,x,y,width,height,hwndParent,hMenu,hlnstance,lpParam); } win.ui.form() = !winform. win.form.loadForm() = !winform. ?.loadForm = !winform. ?.getForm = !winform. win.form(propertiesTable) = 创建的窗体对象,\n可选用参数 @propertiesTable 指定一个表对象以指定窗口设置和属性。\n请使用窗体设计器自动生成参数表。\n\n窗体对象以及窗体创建的控件对象可作为参数传入其他线程,\n跨线程调用窗体对象的成员函数时将转发到创建窗口的线程执行。\n!winform. win._form() = !winform. !winform._parentForm = 创建该控件的父窗口(win.form对象),\n设计时窗体容器是所有拖放在窗体上的控件的 _parentForm,\n\n即使窗口移除子窗口样式、更改父子关系,或以 orphanWindow显示,\n控件的 _parentForm 始终都不会改变\n!winform. end intellisense**/