/*
AAuto 窗口非客户区的绘制（8月15日更新）
作者: lujjjh http://www.ecranesoft.com/bbs/showtopic-8600.aspx
$Id: main.aau 997 2010-11-09 14:05:43Z crane.he $
*/ 

import win.ui;
import com.picture;  
/*DSG{{*/
var winform = win.form(parent=...; bottom=249;right=349;border="resizable";text="AAuto Form" )
winform.add(  )
/*}}*/

::GetDCEx := ::User32.api( "GetDCEx", "pointer( int hWnd, int hrgnClip, int flags )" ); 
::GetClassLong := ::User32.api( "GetClassLong", "int( int hWnd, int nIndex )" ); 

var hSkin;
try {
	var picture = com.picture.load( string.load( "/res/skin.gif" ) ); 
	hSkin =  picture.CopyHandle() ;
	
} catch () {
	hSkin = 0;
} 

if( !hSkin ) {
	win.msgbox( '无法读取皮肤文件！\r\n请检查皮肤图片路径是否有误。', "错误：" );
	return null;
}

var hSkinDC = ::CreateCompatibleDC();
::SelectObject( hSkinDC, hSkin );  

paintNC = function ( hDC ) {
	// 创建一个内存设备上下文（双缓冲绘图）
	var hMem     = ::CreateCompatibleDC( );
	var rcWindow = winform.getRect()
	var re;
	// 偏移区域，方便操作
	re, rcWindow = ::OffsetRect( rcWindow, -rcWindow.left, -rcWindow.top );
	// 创建一个内存位图对象
	var hBitmap  = ::CreateCompatibleBitmap( hDC, rcWindow.right, rcWindow.bottom);
	// 将位图选入内存设备上下文，即可开始绘制
	::SelectObject( hMem, hBitmap );
	// 创建一个透明色画刷
	var hBrush   = ::CreateSolidBrush( 0xff00ff );
	// 先填充透明色
	::FillRect( hMem, rcWindow, hBrush );
	::DeleteObject( hBrush );
	
	// 标题栏
	::BitBlt( hMem, 0, 0, 3, 31, hSkinDC, 0, 0, 0xCC0020/*_SRCCOPY*/ );
	::StretchBlt( hMem, 3, 0, rcWindow.right - 6, 31, hSkinDC, 3, 0, 1, 31, 0xCC0020/*_SRCCOPY*/ );
	::BitBlt( hMem, rcWindow.right - 3, 0, 3, 31, hSkinDC, 4, 0, 0xCC0020/*_SRCCOPY*/ );
	
	// 外边框
	::StretchBlt( hMem, 0, 31, 2, rcWindow.bottom - 33, hSkinDC, 0, 31, 2, 1, 0xCC0020/*_SRCCOPY*/ );
	::StretchBlt( hMem, rcWindow.right - 2, 31, 2, rcWindow.bottom - 33, hSkinDC, 5, 31, 2, 1, 0xCC0020/*_SRCCOPY*/);
	::BitBlt( hMem, 0, rcWindow.bottom - 2, 2, 2, hSkinDC, 0, 32, 0xCC0020/*_SRCCOPY*/);
	::StretchBlt( hMem, 2, rcWindow.bottom - 2, rcWindow.right - 4, 2, hSkinDC, 2, 32, 3, 2, 0xCC0020/*_SRCCOPY*/ );
	::BitBlt( hMem, rcWindow.right - 2, rcWindow.bottom - 2, 2, 2, hSkinDC, 5, 32, 0xCC0020/*_SRCCOPY*/ );
	
	// 画图标
	var hIcon = ::GetClassLong( winform.hwnd, 0xFFFFFFF2/*_GCL_HICON*/ );
	::DrawIconEx( hMem, 8, 8, hIcon, 16, 16, 0, 0, 0x0003/*_DI_NORMAL*/ );
	
	// 写标题
	var sTitle = winform.text;
	::SetBkMode( hMem, 0x1/*_TRANSPARENT*/ );
	var hFont = ::CreateFont( 12, 0, 0, 0, 0x2BC/*_FW_BOLD*/, 0, 0, 0, 0, 0, 0, 0, 0, "宋体" );
	::SelectObject( hMem, hFont );
	::SetTextColor( hMem, 0xffffff );
	::DrawText( hMem, sTitle, #sTitle, ::RECT( 28, 2, rcWindow.right - 100, 29 ), 0x0/*_DT_LEFT*/ | 0x4/*_DT_VCENTER*/ | 0x20/*_DT_SINGLELINE*/ | 0x40000/*_DT_WORD_ELLIPSIS*/ );
	::DeleteObject( hFont );
	
	// 画非客户区按钮
	paintNCBtn( hMem );
	
	// 透明拷贝内存设备上下文到设备上下文
	::TransparentBlt( hDC, 0, 0, rcWindow.right, rcWindow.bottom, hMem, 0, 0, rcWindow.right, rcWindow.bottom, 0xff00ff );
	::DeleteObject( hBitmap );
	::DeleteDC( hMem );
}

paintNCBtn = function ( hDC, minState = 0, maxState = 0, closeState = 0 ) {
	/**
	xxxstate:
	0	默认
	1	鼠标移入
	2	鼠标按下
	**/
	var rcWindow = winform.getRect()
	var re;
	re, rcWindow = ::OffsetRect( rcWindow, -rcWindow.left, -rcWindow.top );
	::TransparentBlt( hDC, rcWindow.right - 100, 1, 26, 17, hSkinDC, 7,  minState   * 17, 26, 17, 0xff00ff );
	::TransparentBlt( hDC, rcWindow.right - 74,  1, 26, 17, hSkinDC, 33, maxState   * 17, 26, 17, 0xff00ff );
	::TransparentBlt( hDC, rcWindow.right - 48,  1, 41, 17, hSkinDC, 59, closeState * 17, 41, 17, 0xff00ff );
}

winform.wndproc = function ( hwnd, message, wParam, lParam ) {
	select(message) {
		case 0x14/*_WM_ERASEBKGND*/ {								// 当窗口背景需要重画时，系统会发送这个消息给窗口
		
			var hDC = topointer(wParam);							// WM_ERASEBKGND 的 wParam 就是窗口的设备上下文句柄
			var lpRect = winform.getClientRect()
			var hBrush = ::GetStockObject( 0x0/*_WHITE_BRUSH*/ );	// 获取白色画刷作为背景刷子
			::FillRect( hDC, lpRect, hBrush  );			// 用白色画刷填充整个窗口客户区
			return 1;												// 告诉 AAuto 我们已经处理了这个消息，不用交给系统处理了
		}
		case 0x83/*_WM_NCCALCSIZE*/	{								// 当窗口需要计算非客户区大小时，系统会发送这个消息给窗口
		
			var lpRect = ::RECT();
			raw.convert( topointer( lParam ), lpRect );				// lParam 是一个 RECT
			lpRect.left   += 2;										// 左、右、下各留 2 个像素
			lpRect.top    += 31;									// 标题栏留出 31 个像素
			lpRect.right  -= 2;
			lpRect.bottom -= 2;
			::CopyMemoryByStruct( topointer(lParam), lpRect, 16 );					// 将修改完毕的区域拷贝给 lParam
			return 0;
		}
		case 0x85/*_WM_NCPAINT*/ {									// 当窗口非客户区需要重画时，系统会发送这个消息给窗口
			var hDC = ::GetDCEx( hwnd, wParam, 0x1/*_DCX_WINDOW*/ | 0x80/*_DCX_INTERSECTRGN*/ );
			// 以上为 MSDN 推荐写法，但是可能会无法获取
			if( !hDC ){ 
				hDC = ::GetWindowDC( hwnd );
			} 
			
			paintNC( hDC );
			::ReleaseDC( hwnd, hDC );
			return 1;
		}
		case 0xAF/*_WM_NCUAHDRAWFRAME*/, 0xAE/*_WM_NCUAHDRAWCAPTION*/
			return 0x85/*_WM_NCPAINT*/;
		case 0x86/*_WM_NCACTIVATE*/	{								// 当窗口非客户区被激活或失去焦点时，系统会发送这个消息给窗口
			if ( wParam == 1 ) {
				return 0;
			} else { 
				winform.capture = false;
				return 1;
			}
		}
		case 0x6/*_WM_ACTIVATE*/ {									// 当窗口被激活或失去焦点时，系统会发送这个消息给窗口
		
			::SendMessageInt( hwnd, 0x86/*_WM_NCACTIVATE*/, ::LOWORD( wParam ), 0 );
			return 0;
		}
		case 0x84/*_WM_NCHITTEST*/ {
			var hDC = ::GetWindowDC( hwnd );
			var rcWindow = winform.getRect()
			var x = ::LOWORD( lParam );								// lParam 记录的是鼠标的位置
			var y = ::HIWORD( lParam );								// 低位是横坐标，高位是纵坐标
			if( ::PtInRect( ::RECT( rcWindow.right - 100, rcWindow.top + 1, rcWindow.right - 74, rcWindow.top + 18 ), x, y ) ) {
				paintNCBtn( hDC, 1 );
				::ReleaseDC( hwnd, hDC );
				return 0x8/*_HTMINBUTTON*/;
			} elseif( ::PtInRect( ::RECT( rcWindow.right - 74, rcWindow.top + 1, rcWindow.right - 48, rcWindow.top + 18 ), x, y ) ) {
				paintNCBtn( hDC, 0, 1 );
				::ReleaseDC( hwnd, hDC );
				return 0x9/*_HTMAXBUTTON*/;
			} elseif( ::PtInRect( ::RECT( rcWindow.right - 48, rcWindow.top + 1, rcWindow.right - 7, rcWindow.top + 18 ), x, y ) ) {
				paintNCBtn( hDC, 0, 0, 1 );
				::ReleaseDC( hwnd, hDC );
				return 0x14/*_HTCLOSE*/;
			}
			paintNCBtn( hDC );
			::ReleaseDC( hwnd, hDC );
			if( ::PtInRect( ::RECT( rcWindow.left, rcWindow.top, rcWindow.left + 4, rcWindow.top + 31 ), x, y ) )
				return 0xD/*_HTTOPLEFT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.left + 4, rcWindow.top, rcWindow.right - 4, rcWindow.top + 4 ), x, y ) )
				return 0xC/*_HTTOP*/;
			elseif( ::PtInRect( ::RECT( rcWindow.right - 4, rcWindow.top, rcWindow.right, rcWindow.top + 31 ), x, y ) )
				return 0xE/*_HTTOPRIGHT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.left, rcWindow.top + 31, rcWindow.left + 4, rcWindow.bottom - 4 ), x, y ) )
				return 0xA/*_HTLEFT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.right - 4, rcWindow.top + 31, rcWindow.right, rcWindow.bottom - 4 ), x, y ) )
				return 0xB/*_HTRIGHT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.left, rcWindow.bottom - 4, rcWindow.left + 4, rcWindow.bottom ), x, y ) )
				return 0x10/*_HTBOTTOMLEFT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.left + 4, rcWindow.bottom - 4, rcWindow.right - 4, rcWindow.bottom ), x, y ) )
				return 0xF/*_HTBOTTOM*/;
			elseif( ::PtInRect( ::RECT( rcWindow.right - 4, rcWindow.bottom - 4, rcWindow.right, rcWindow.bottom ), x, y ) )
				return 0x11/*_HTBOTTOMRIGHT*/;
			elseif( ::PtInRect( ::RECT( rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.top + 31 ), x, y ) )
				return 0x2/*_HTCAPTION*/;
			return 0x1/*_HTCLIENT*/;
		}
		case 0xA1/*_WM_NCLBUTTONDOWN*/ {
			var hDC = ::GetWindowDC( hwnd );
			select( wParam ) {
				case 0x8/*_HTMINBUTTON*/ {
					paintNCBtn( hDC, 2 );
					return 1;
				}
				case 0x9/*_HTMAXBUTTON*/ {
					paintNCBtn( hDC, 0, 2 );
					return 1;
				}
				case 0x14/*_HTCLOSE*/ {
					paintNCBtn( hDC, 0, 0, 2 );
					return 1;
				}
			}
			::ReleaseDC( hwnd, hDC );
		}
		case 0xA2/*_WM_NCLBUTTONUP*/ {
			select( wParam ) {
				case 0x8/*_HTMINBUTTON*/
					::PostMessage( hwnd, 0x112/*_WM_SYSCOMMAND*/, 0xF020/*_SC_MINIMIZE*/, 0 );
				case 0x9/*_HTMAXBUTTON*/
					::PostMessage( hwnd, 0x112/*_WM_SYSCOMMAND*/, ..win.isZoomed( hwnd ) ? 0xF120/*_SC_RESTORE*/ : 0xF030/*_SC_MAXIMIZE*/, 0 );
				case 0x14/*_HTCLOSE*/
					::PostMessage( hwnd, 0x10/*_WM_CLOSE*/, 0, 0 );
			}
		}
	}
}

winform.top++;
winform.top--;

winform.show( true ); 
win.loopMessage();
return winform;
