示範在 Win32 視窗程序中處理 WM_CHAR 訊息,接收鍵盤輸入字元並即時顯示於用戶區左上角。涵蓋訊息類型區別、TranslateMessage 角色、InvalidateRect 觸發重繪、繪圖集中於 WM_PAINT 的最佳實踐。
| 訊息 | 觸發時機 | wParam 內容 | 典型用途 |
|---|---|---|---|
WM_KEYDOWN | 按鍵按下 | 虛擬鍵碼 (VK_*) | 遊戲控制、快捷鍵、非字元按鍵 |
WM_KEYUP | 按鍵釋放 | 虛擬鍵碼 | 按鍵釋放偵測 |
WM_CHAR | TranslateMessage 轉換 | 字元碼 (ANSI/Unicode) | 文字輸入、編輯框 |
關鍵點:GetMessage → TranslateMessage → DispatchMessage 迴路中,TranslateMessage 將 WM_KEYDOWN 轉為 WM_CHAR(含鍵盤佈局、Shift 狀態、死鍵處理)。若不呼叫 TranslateMessage,將不會產生 WM_CHAR。
.data
Char WPARAM 20h ; 初始為空格 (無輸入時不顯示)
.code
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_CHAR
PUSH wParam
POP Char ; 儲存接收到的字元
INVOKE InvalidateRect, hWnd, NULL, TRUE ; 整個用戶區無效化 + 擦除背景
.ELSEIF uMsg==WM_PAINT
INVOKE BeginPaint, hWnd, ADDR ps
MOV hdc, EAX
INVOKE TextOut, hdc, 0, 0, ADDR Char, 1 ; 繪製單一字元
INVOKE EndPaint, hWnd, ADDR ps
.ENDIF
...
WndProc endp
WM_KEYDOWN (wParam=41h)TranslateMessage 依當前鍵盤佈局轉為 WM_CHAR (wParam='A'=41h)DispatchMessage 傳遞給 WndProcWM_CHAR 分支:將字元存入 Char,呼叫 InvalidateRect(hWnd, NULL, TRUE)WM_PAINTWM_PAINT 分支:BeginPaint → TextOut(0,0,Char,1) → EndPaintWM_CHAR 呼叫 GetDC/TextOut/ReleaseDC:視窗最小化還原、被遮蔽後顯示時,字元會消失,因為 Windows 不會自動重繪非 WM_PAINT 產生的內容。WM_PAINT 內繪製,狀態資料儲存在全域/靜態變數,InvalidateRect 通知 Windows 「需重繪」。InvalidateRect(hWnd, NULL, TRUE):NULL=整個用戶區,TRUE=擦除背景(呼叫 BeginPaint 時自動填充類別背景筆刷)。WM_KEYDOWN 攔截 Backspace (VK_BACK) 刪除字元GetTextExtentPoint32 計算文字寬度,實現自動換行WM_CHAR (ANSI) 與 WM_UNICHAR (Unicode) 在 Unicode 版本程式中的差異