import gdi;
import win.ui.background;

namespace win.ui{
    
	NMHDR = ::NMHDR;
	
	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;
		} 
	}
}

class win.form {  
 
	ctor( tParam ) begin   
	
		//这句必须放最前面,以保证自定义控件设计时大小不会被修改
		tParam = ..table.mix(tParam,{
	    	left = -1;top = -1;right = 759;bottom = 469;
	    });
	    
	    this.hInstance = _HINSTANSE; 
	    this._mapCommandProc = { freeId = tParam.freeId : 5000 };
        this._ctrlId = { freeId = 3 };//控件ID映射关系
        this._ctrlHwnd = {};//控件句柄映射关系  
        this._ctrlAutoResize = {};//自动调整位置 
        this._onlyDirectDrawBackground = {};
        this._directDrawBackground = {};
	    this._tTimeProc = {};
	    this._tTimeProcEntered = {};
	    this._tTimeTicks = { allocId = 1;freeId={} }; 
	    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 cyborder = ::GetSystemMetrics( 0x6/*_SM_CYBORDER*/ );
		var cxborder = ::GetSystemMetrics( 0x5/*_SM_CXBORDER*/ );
		var cycaption = ::GetSystemMetrics( 0x4/*_SM_CYCAPTION*/  ) ;
        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 //避免去掉标题栏时覆盖了边框设置
        	cycaption = 0; //如果没有标题栏,则要去掉标题栏的高度 
        }	
        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" )   ){
			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;
	    	if(!this._defClientRect){ 
	    		this._defClientRect = ..win.getClientRect(tParam.hwnd) ; 
	    	};
	    	
	    	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;
			if(tParam.parent){
				var mi = ..win.getMonitorInfo(tParam.parent);
				if(mi) rcWk = mi.rcWork;
				else rcWk = ..win.getWorkArea();
			}
			else {
				rcWk = ..win.getWorkArea();
			}
			
			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; 
} 

namespace win.form{ 

	createWindowEx = ::CreateWindowEx;
	
	import ..win.ui.ctrl; 
	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.fromUnicode(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); 
       			
       			if(struct=="JSON"&&..web[["json"]] ){ 
       				var json = topointer(lParam); 
       				
       				json = unicode ? ..string.fromUnicode(json,,-1) : ..raw.str(json);
       				return tonumber( (invoke(f,this,..table.unpack(..web.json.parse(json)) ) ) );
       			}
       			
       			var r = invoke(f,this,..raw.convert(topointer(lParam),{ _struct = struct })); 
       			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);
 	   	     			}
 	   	     		} 
 	   	     	) );
 	   		}
 	   }; 
 	   [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);
            	
            	for(hwnd,ctrl in this._ctrlAutoResize ){  
					if( ctrl.cacheOrphanWindowRect__ ){ 
						if(!wParam){
							if( ..win.isVisible(ctrl.hwnd) ){
								ctrl.show(false);
								ctrl.orphanRestorePending = true;
								if( ctrl.onSetOrphanWindowPos ) ctrl.onSetOrphanWindowPos(,,,,0x80/*_SWP_HIDEWINDOW*/)
							}
							continue;
						} 
					
						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();
					}
				}
			}
	   };
 	   [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){
				
				if( wParam == 1/*_SIZE_MINIMIZED*/ ) {
					if( this.onMinimized ) this.onMinimized();
					return;
				}
				
				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 , 0x1C/*_SWP_NOACTIVATE |  _SWP_NOZORDER | _SWP_NOREDRAW*/ );
   						}
   					}
   				}

				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())
   					}
   					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*/ ); 
   							}
   							
   							if( ctrl.preadjust ){
								ctrl.preadjust( size.cx, size.cy,wParam );
							}
							
   							if( ctrl._preadjust ){
								ctrl._preadjust( size.cx, size.cy,wParam );
							}
						} 		
						else {
							ctrl.close();
						}			
   					}
				}
   				
   				if(! ..win.getStyle(this.hwnd,0x40000000/*_WS_CHILD*/) ) this.redraw();//Z Orderd Draw
   				
   				for(hwnd,ctrl in this._ctrlAutoResize ){
   					if( ctrl._adjust ){ 
						ctrl._adjust( ctrlSize[hwnd].cx, ctrlSize[hwnd].cy,wParam );
					} 
					if( ctrl.adjust__ ){ 
						ctrl.adjust__( ctrlSize[hwnd].cx, ctrlSize[hwnd].cy,wParam );
					} 
   				}

   				if( this.toolbar ? this.toolbar.adjust){ 
   					this.toolbar.adjust();
   				}	
   				if( this.statusbar ? this.statusbar.adjust){ 
   					this.statusbar.adjust();
   				}
   				
   				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);
   				} 
   			}
 	   }; 
 	   [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);
 	        	}
 	        }
 	        
 	        this[["(__continueModal)"]] = null;
 	   };
 	   [0x110/*_WM_INITDIALOG*/] = function(this,hwnd, message, wParam, lParam){
 	        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); 
						var nmhdr = ..raw.convert(ptr,::NMHDR() );
						var code = nmhdr.code;
						var ret;
						if( pre ) 
							ret = ctrl._prenotify( 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 ();
					if( ctrl.onDestroy){
						ctrl.onDestroy ();
						ctrl.onDestroy = null;
					}
					
					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 ();
   				if( ctrl.onDestroy){
					ctrl.onDestroy ();
					ctrl.onDestroy = null;
				}
   			}
			
			if( this._onDestroy ){ 
				this._onDestroy ();
			}
			if( this.onDestroy){
				this.onDestroy ();
				this.onDestroy  = null;
			}
			
			if(this._onDestroyInTabs)this._onDestroyInTabs();

			if( this[["_atomId"]] ){ 
				this.atom(false);//释放实例占用原子
			} 
			this[["(__continueModal)"]] = null;//退出模态循环 
			
			_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;
				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;
			
			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();
 	   			..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);
				::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); 
				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){ 
			if(this.onMouseDoubuleClick) return this.onMouseDoubuleClick(wParam,lParam);   
		};
		[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( 
			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;
			};
			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;
			};
			_getFreeCommandId = function(){ 
   				var id = owner._mapCommandProc.freeId;
   				owner._mapCommandProc.freeId++;
   				return id;
   			}; 
   			registCommand = function(proc,oid){
   				if( oid === null ){
   					var free = owner._getFreeCommandId();
   					owner._mapCommandProc[free] = proc;
   					return free;
   				}
   				else {
   					if( oid > owner._mapCommandProc.freeId ) owner._mapCommandProc.freeId = oid + 1;
   					owner._mapCommandProc[oid] = proc;
   					return oid 
   				} 
   			}; 
			redraw = function(){ 
				if(owner[["menu"]])owner[["menu"]].redraw();
				
    			var rc = ::RECT();
    			::GetClientRect(owner[["hwnd"]],rc); 
    			::InvalidateRect(owner[["hwnd"]],rc,1);
    			::UpdateWindow(owner[["hwnd"]]); 
			};
			redrawBackground = function(rect){
				if( !owner.background ) return;
				owner.background.update();
				owner.invalidate(rect);
				owner.update();
			};
			show = function(flag) {    
				if( !owner["(dpiScaleInitialized)"] ){
					if( ! (..win.ui.disableDpiScaling || owner.disableDpiScaling) ){
						owner.enableDpiScaling(true); 
					}
					owner["(dpiScaleInitialized)"] = true;
				}
				
				..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);  
 	   			}
			};
			doModal = function(hwndOwner){ 
			
				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(); 
				
				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 = function( alpha,clr ){
				if( alpha === false ){
					owner.modifyStyleEx(0x80000/*_WS_EX_LAYERED*/);
					if( owner._shadowWindow ) owner._shadowWindow.transprent(1); 
					return;
				}
	    		owner.modifyStyleEx(0,0x80000/*_WS_EX_LAYERED*/);
	    		if( alpha === true )
	    			return;
	    			
	    		if( clr!==null || alpha !==null ){
	    			if(clr ===null){  
	    				if( owner._shadowWindow ) {
	    					 owner._shadowWindow.transprent(alpha/255); 
	    				}
	    			}
					::User32.SetLayeredWindowAttributes( owner[["hwnd"]],clr:0, alpha:0,clr!==null?1:2)
				}
			}
			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 freeId = ..table.pop( owner._tTimeTicks.freeId,1) ;
				if(!freeId){ 
					freeId = owner._tTimeTicks.allocId;
					owner._tTimeTicks.allocId++;
				}
		 		
				owner[["_tTimeProc"]][freeId] = func; 
				owner[["_tTimeTicks"]][freeId] = elapse;
				
				if( ::User32.SetTimer(owner.hwnd,freeId,elapse,null) )
	    			return freeId;
			};
			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.freeId,id);
	    			return true;
	    		}
			};
			setTimeout = function(code,elapse=0,...){
				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) ) 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();
				}; 
			};
			valid = {
      			_get = function(){
      				return( ..win.isWindow( owner.hwnd ) )
      			} 
      		};
      		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;
      				}
      			}
      			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 = owner[name];
      			if( ctrl ? ctrl.hwnd ? ctrl.close ){
      				ctrl.close();
      			}
      			owner[name] = null;
      		};
			add = function( tParam,parentCtrl ) {
				var zorder,zorderBk = {},{};
				var cls;
        		for name,opt in tParam{
        			cls = opt.cls;
        			..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 parent = parentCtrl : owner;
 				var dpiScaleX,dpiScaleY = (parent.dpiScaleX : 1) ,(parent.dpiScaleY : 1);
 	 			var defParent = parent._defClientRect : parent._defRect;
 	 			var result = {};
				for(i=1;#zorder ){  
		    		var name = zorder[i][1];
		    		var opt = zorder[i][2];    
		    		
		    		//计算位置参数
		    		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 = owner._ctrlId.freeId;
						owner._ctrlId.freeId = owner._ctrlId.freeId + 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.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._onControlCreated ) owner._onControlCreated(result);
				if( owner.onControlCreated ) owner.onControlCreated(result);
				
				if(owner["(dpiScaleInitialized)"]){
					owner.resize();
				}
				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;
}

win._form = win.form;
win.ui.isForm = function(v){
	return v@===..win.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
win._form = 指向原始的 win.form\n注意 win.loadForm 函数会暂时修改 win.form函数并注入代码修改默认行为,例如修改父窗口,\n如果在库里面希望创建原生窗口而不需要接受注入代码,\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);
}
end intellisense**/