根據前面的理論, 一個視窗產生的架構應該是這個樣子:
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;