//layered 分层窗口
import gdip.graphics;
import gdip.solidBrush;
import gdip.bitmap;

namespace win.ui;

class layered{
	ctor( winform,delayTime ){
		if( ::User32.GetSystemMetricsB(0x1000/*_SM_REMOTESESSION*/) ) return;
		
		this._form = winform;
		winform.modifyStyle(0x800000/*_WS_BORDER*/|0xC00000/*_WS_CAPTION*/);
        winform.transparent(true);
        
        winform.background.drawRect	= function(){};
        winform.background.update	= function(){  
        	this.redraw() 
        };
        
        this.background = winform.background.getLayeredBitmap();
        this.backgroundColor = winform.background.getLayeredColor();
    	if( delayTime === null ) delayTime = -1; 
        
        winform._onControlCreated = function(ctrls){
        	for( name,ctrl in ctrls ){ 
        		if(ctrl.directDrawBackgroundOnly){
        			ctrl.directDrawBackgroundOnly();
        			if(ctrl.predraw ) ctrl.predraw();
        		}
        	}	
        }
        
        for( name,ctrl in winform.eachControl() ){
        	if(ctrl.directDrawBackgroundOnly){
        		ctrl.directDrawBackgroundOnly();
        		if(ctrl.predraw ) ctrl.predraw();
        	}
        } 
        
        this.redraw = function(){
			..gdi.layeredBuffer( winform.hwnd,  
				function( hdc,hMemDc,hMemBitmap,width,height,left,top,hwnd,blendFunction ){
				
        			var graphics = ..gdip.graphics(hMemDc);
        			
        			if( this.background || ( this.backgroundColor!== null ) ){ 
        				
        				if( ! ( (width == this.cacheBitmapWidth) 
        					&& (height == this.cacheBitmapHeight ) 
        					&& (this.background==this.cacheBackground) 
        					&& (this.backgroundColor==this.cacheBackgroundColor)) ){
							this.predraw(); 
						}  
							
						if(this.cacheBitmap){
        					graphics.drawCachedBitmap(this.cacheBitmap,0,0);
        				}
        			} 
        			
        			if( this.onDrawBackground ) this.onDrawBackground(graphics,left,top,width,height);
        			   
        			if(! this.updateDrawing ){
						this.updateDrawing = true;
						var rc = ::RECT();
						rc.xywh(left,top,width,height);
						
						this._form.directDrawBackground(hMemDc,graphics,rc);
						this.updateDrawing = false;	
					}
        			
        			graphics.resetClip();
        			graphics.delete();
        			
					..gdi.updateLayeredWindow( hwnd,hMemDc,::SIZE(width,height) ,blendFunction  );  
				}
			) 	
		};
        
        winform.adjust = function(){
        	this.redraw();
        }
        
        winform.beforeShowWindow = function(shown,status){ 
			if(shown){
				for( name,ctrl in winform.eachControl() ){
        			if(ctrl.directDrawBackgroundOnly){
        				ctrl.directDrawBackgroundOnly();
        				if(ctrl.predraw ) ctrl.predraw();
        			}
        		} 
        
				winform.setTimeout(this.redraw);
				if(delayTime>0) && (this.timerId===null) this.timerId = winform.setInterval(this.redraw,delayTime) 
			}
			else {
				if(this.timerId!==null){
					winform.clearInterval(this.timerId);
					this.timerId = null;
				} 
			}
		}
		winform.beforeShowWindow( ..win.isVisible(winform.hwnd) );

        winform._beforeDestroy = function(){
        	if( this.cacheBitmap ) { 
				..gdip.DeleteCachedBitmap(this.cacheBitmap);
				this.cacheBitmap = null; 
			}	
        };
	}; 
	
	predraw = function(){
		if( this.cacheBitmap ) { 
			..gdip.DeleteCachedBitmap(this.cacheBitmap);
			this.cacheBitmap = null; 
		}
						
		if(( this.background ) || ( this.backgroundColor!== null )){
			if( type(this.background) == "string" ){
        		this.background = ..gdip.bitmap(this.background);
        	};
        	
			var rc = this._form.getRect();
			var width,height = rc.right - rc.left,rc.bottom - rc.top;
		
        	var bmpMem = ..gdip.bitmap(width,height);
        	var g = bmpMem.getGraphics();
        	g.smoothingMode = 2/*_SmoothingModeHighQuality*/;
        	
        	if( this.backgroundColor!== null ){
        		var brush = ..gdip.solidBrush(this.backgroundColor);
        		if( this.borderRadius ){
        			var path = ..gdip.path(1/*_FillModeWinding*/)
					path.addRoundRect(::RECT(0,0,width,height),this.borderRadius);
					g.fillPath(brush,path);
					path.delete();
        		}
        		else {
        			g.fillRectangle(brush,0,0,width,height);
        		}
        	} 
        	
        	if(this.background){
        		if(this._form .bkTop!==null){ 
        			g.drawImageExpand(this.background
        				,::RECT(0,0,width,height),this._form .bkTop
        				,this._form .bkRight,this._form .bkBottom,this._form .bkLeft);
        		}
        		else {
        			g.drawImage(this.background);
        		}	
        	}			
        	
        	g.delete();
        	var graphics = ..gdip.graphics(this._form);
        	this.cacheBitmap = graphics.createCachedBitmap(bmpMem); 
        	graphics.delete();
        	
        	this.cacheBackground = this.background;
        	this.cacheBackgroundColor =  this.backgroundColor;
        	this.cacheBitmapWidth = width;
			this.cacheBitmapHeight = height;
        	
        	bmpMem.dispose(); 
        }
	} 
}


/**intellisense()
win.ui.layered( = 创建分层窗口\n支持窗体设计器指定的png透明背景图,背景色，\n支持窗口上的plus,bkplus控件,其他子窗口可通过调用 orphanWindow 函数正常显示
win.ui.layered(.(窗体对象,主动刷新间隔) = 创建分层窗口\n主动刷新间隔为可选参数,以毫秒为单位,过快会降低性能\n刷新间隔设为负数可禁止主动刷新,但plus控件仍然可以自动刷新,\n注意创建分层窗口以后不应再改变窗口大小
win.ui.layered() = !winuilayered.
end intellisense**/

/**intellisense(!winuilayered)
onDrawBackground() = @.onDrawBackground = function(graphics,left,top,width,height){
	__/*可以在这里继续在窗口背景上绘图*/
}
background = 指定背景图像路径或数据
backgroundColor = 指定背景色,ARGB格式
borderRadius = 指定圆角半径，仅在使定背景色时有效
redraw() = 重绘窗口,不要在onDrawBackground里调用此函数
predraw() = 更新窗口绘图缓存但并不立即重绘,不要在onDrawBackground里调用此函数
end intellisense**/