根据前面的理论, 一个窗口生成的框架应该是这个样子:
要显示一个窗口, 需要先建立一个窗口;
要建立一个窗口, 需要先注册一个窗口类型;
注册前需要给窗口类型指定种种特性, 这些特性里面, 最重要的就是指定"窗口的回调函数"!
此回调函数必须要按照 Windows 指定的格式(只有函数名和参数名可变):
但消息非常非常多, 不可能都做处理, 不需要的消息都要通过 DefWindowProc 函数做默认处理.
DefWindowProc 函数的参数和回调函数的参数一直, 并返回回调函数需要的返回值.
譬如我们只处理 WM_DESTROY 消息:
program Project1; uses Windows; {前面提到的函数都来自 Windows 单元} var hWnd : THandle; {声明窗口句柄} MyWndClass: TWndClass; {声明一个窗口类型} begin //在这里设置 MyWndClass 的参数(譬如窗口图标、光标和画刷等等), 包括指定 "类名" {然后注册} RegisterClass(MyWndClass); {建立并返回句柄} hWnd := CreateWindow(类名, 标题, 样式, X,Y, 宽,高, 0, 0, HInstance, nil); {显示} ShowWindow(hWnd, SW_SHOWNORMAL); end.这个窗口类型 TWndClass 其实是一个结构, 是 tagWNDCLASSA 结构的重命名.
{tagWNDCLASSA 结构:} tagWNDCLASSA = packed record style: UINT; {窗口风格, 见下表} lpfnWndProc: TFNWndProc; {窗口回调函数的指针, 后面要详细分析} cbClsExtra: Integer; {为窗口类分配的额外空间, 一般为 0} cbWndExtra: Integer; {为窗口实例分配的额外空间, 一般为 0} hInstance: HINST; {窗口所在程序实例的句柄, 就是 HInstance} hIcon: HICON; {指定窗口图标, 一般用 LoadIcon 加载; 不指定可设为 0} hCursor: HCURSOR; {指定窗口光标, 一般用 LoadCursor 加载; 不指定可设为 0} hbrBackground: HBRUSH; {指定窗口背景画刷, 这需要用 GetStockObject 函数检索; 也可以直接指定系统颜色} lpszMenuName: PAnsiChar; {菜单资源名称; 一般置为 nil, 表示窗口没有默认菜单} lpszClassName: PAnsiChar; {给该窗口类命名; CreateWindow 函数将使用这个名称} end; //窗口风格参数 style 可选值: CS_VREDRAW = DWORD(1); {窗口高度变化时将被重绘} CS_HREDRAW = DWORD(2); {窗口宽度变化时将被重绘} CS_KEYCVTWINDOW = 4; {} CS_DBLCLKS = 8; {不忽略鼠标双击的消息} CS_OWNDC = $20; {给用该类建立的每一个窗口分配独立的设备 DC} CS_CLASSDC = $40; {让属于该类的所有窗口共享一个设备 DC} CS_PARENTDC = $80; {允许窗口的子窗口继承一些共同特性} CS_NOKEYCVT = $100; {} CS_NOCLOSE = $200; {禁用系统菜单的 Close命令,同时窗口没有关闭按钮} CS_SAVEBITS = $800; {当窗口被覆盖时, 用位图缓存被覆盖区, 从而避免 WM_PAINT 消息, 一般用于菜单或对话框} CS_BYTEALIGNCLIENT = $1000; {通过字节对齐, 增强客户区的绘制性能} CS_BYTEALIGNWINDOW = $2000; {通过字节对齐, 增强窗口的绘制性能} CS_GLOBALCLASS = $4000; {全局窗口类, 一般用于 DLL; 没有此选项, 窗口类和窗口建立函数中指定的实例句柄须相同} //关于窗口背景画刷: {系统预定义了一些画刷, 需要用 GetStockObject 根据指定的常数检索;} {但 GetStockObject 返回的句柄有可能是画刷、画笔、调色板或系统字体的句柄,} {所以还需要把 GetStockObject 返回的句柄进行类型转换, 譬如: HBRUSH(GetStockObject(常数))} //下面是 GetStockObject 函数参数的可选值: WHITE_BRUSH = 0; LTGRAY_BRUSH = 1; GRAY_BRUSH = 2; DKGRAY_BRUSH = 3; BLACK_BRUSH = 4; NULL_BRUSH = 5; HOLLOW_BRUSH = NULL_BRUSH; WHITE_PEN = 6; BLACK_PEN = 7; NULL_PEN = 8; OEM_FIXED_FONT = 10; ANSI_FIXED_FONT = 11; ANSI_VAR_FONT = 12; SYSTEM_FONT = 13; DEVICE_DEFAULT_FONT = 14; DEFAULT_PALETTE = 15; SYSTEM_FIXED_FONT = $10; DEFAULT_GUI_FONT = 17; DC_BRUSH = 18; DC_PEN = 19; STOCK_LAST = 19; {另外背景画刷还可以使用 Windows 定义系统颜色常量, 譬如: HBRUSH(COLOR_WINDOW + 1) } COLOR_SCROLLBAR = 0; COLOR_BACKGROUND = 1; COLOR_ACTIVECAPTION = 2; COLOR_INACTIVECAPTION = 3; COLOR_MENU = 4; COLOR_WINDOW = 5; COLOR_WINDOWFRAME = 6; COLOR_MENUTEXT = 7; COLOR_WINDOWTEXT = 8; COLOR_CAPTIONTEXT = 9; COLOR_ACTIVEBORDER = 10; COLOR_INACTIVEBORDER = 11; COLOR_APPWORKSPACE = 12; COLOR_HIGHLIGHT = 13; COLOR_HIGHLIGHTTEXT = 14; COLOR_BTNFACE = 15; COLOR_BTNSHADOW = $10; COLOR_GRAYTEXT = 17; COLOR_BTNTEXT = 18; COLOR_INACTIVECAPTIONTEXT = 19; COLOR_BTNHIGHLIGHT = 20; COLOR_3DDKSHADOW = 21; COLOR_3DLIGHT = 22; COLOR_INFOTEXT = 23; COLOR_INFOBK = 24; COLOR_HOTLIGHT = 26; COLOR_GRADIENTACTIVECAPTION = 27; COLOR_GRADIENTINACTIVECAPTION = 28; COLOR_MENUHILIGHT = 29; COLOR_MENUBAR = 30; COLOR_ENDCOLORS = COLOR_MENUBAR; COLOR_DESKTOP = COLOR_BACKGROUND; COLOR_3DFACE = COLOR_BTNFACE; COLOR_3DSHADOW = COLOR_BTNSHADOW; COLOR_3DHIGHLIGHT = COLOR_BTNHIGHLIGHT; COLOR_3DHILIGHT = COLOR_BTNHIGHLIGHT; COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT;整理一下思路:
要显示一个窗口, 需要先建立一个窗口;
要建立一个窗口, 需要先注册一个窗口类型;
注册前需要给窗口类型指定种种特性, 这些特性里面, 最重要的就是指定"窗口的回调函数"!
此回调函数必须要按照 Windows 指定的格式(只有函数名和参数名可变):
function WndProc(wnd: HWND; msg: UINT; wParam: Integer; lParam: Integer): Integer; stdcall; begin ... end;在该回调函数中, 要处理发送到窗口的所有消息;
但消息非常非常多, 不可能都做处理, 不需要的消息都要通过 DefWindowProc 函数做默认处理.
DefWindowProc 函数的参数和回调函数的参数一直, 并返回回调函数需要的返回值.
譬如我们只处理 WM_DESTROY 消息:
function WndProc(wnd: HWND; msg: UINT; wParam: Integer; lParam: Integer): Integer; stdcall; begin if msg = WM_DESTROY then ... else Result := DefWindowProc(wnd, msg, wParam, lParam); end;