MSDN在線原文(英文)
寫窗口過程
DispatchMessage 函數調用消息的目標窗口的窗口過程。窗口過程具有以下特徵:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
窗口過程有四個參數
- hwnd 是窗口的句柄。
- uMsg 是消息代碼,例如WM_SIZE消息表示窗口調整大小。
- wParam和lParam包含屬於該消息的附加數據。確切的含義取決於消息的代碼。
LRESULT 是一個整數值,你的程序將返回Windows。它包含了程序的響應到一個特定的消息,這個值的意義取決於消息的代碼。CALLBACK 是該函數的調用約定。
一個典型的窗口過程是個大型的switch語句,切換到相應的消息代碼,爲每個你要處理的消息添加實例。
switch (uMsg)
{
case WM_SIZE: // Handle window resizing
// etc
}
附加的消息數據包含在lParam和wParam參數,
這兩個參數都是整數值大小的指針寬度(32位或64位),各自的含義取決於該消息的代碼(參數uMsg)。對於每個消息,你需要在MSND上查找消息代碼和轉換爲正確的數據類型參數。通常情況下,數據可以是數值或一個指向結構的指針;某些消息沒有任何數據。
比如:以下是WM-SIZE 的陳述文檔
- wParam是一個標誌,指示窗口是否最大化、最小化、或調整。
- lParam 包含窗口新的寬度和高度的16位值打包爲一個32位或64位的值。你需要執行位移動來獲取這些值,幸運的是頭文件WinDef.h有能夠做到這點的輔助宏。
一個典型的窗口處理幾十條消息,因此它可以增長得很長。使代碼更加模塊化的方法之一是把每個消息的邏輯放在一個單獨的函數中處理。在窗口過程,計算wParam和lParam參數的正確數據類型,並傳遞給函數。例如:處理WM_SIZE消息看起來大概會是這樣:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_SIZE:
{
int width = LOWORD(lParam); //獲取低位字宏
int height = HIWORD(lParam); //獲取高位字宏
//響應消息
OnSize(hwnd, (UINT)wParam, width, height);
}
break;
}
}
void OnSize(HWND hwnd, UINT flag, int width, int height)
{
//處理所需求的尺寸
}
LOWORD和HIWORD宏從lParam參數中獲取16位的寬度和高度值(你可以看一下MSDN文檔中每個消息的細節)。窗口過程提取寬度和高度並把值傳遞給OnSize函數。
缺省消息處理
如果你不在你的窗口過程處理特定消息,通過消息參數直接傳給DefWindowProc函數。這個函數據消息類型而執行消息的默認動作。
return DefWindowProc(hwnd, uMsg, wParam, lParam);
在你的窗口過程內避免阻塞
在你的窗口過程處理時,它會阻止任何其它消息在同一線程創建窗口,因此,在你的窗口過程避免冗長的處理。比如:假設你的程序打開一個TCP連接,並無限期的等待服務器響應。如果你在窗口過程內這樣做,你的用戶界面不會響應,直到請求完成。在這段時間,窗口無法處理鼠標和鍵盤輸入,重繪本身,甚至關閉。
相反,你應該將工作移到另一個線程,使用Windows中內置的多任務處理設施之一:
- 創建一個新線程。
- 使用一個線程池。
- 使用異步I/O調用。
- 使用異步過程調用。