處理鍵盤輸入訊息(轉)

heying1229發表於2007-07-28
處理鍵盤輸入訊息:

  在本課中,我們將要學習WINDOWS程式是如何處理鍵盤訊息的。

理論:

因為大多數的PC只有一個鍵盤,所以所有執行中的WINDOWS程式必須共用它。WINDOWS 將負責把擊鍵訊息送到具有輸入焦點的那個應用程式中去。儘管螢幕上可能同時有幾個應用程式視窗,但一個時刻僅有一個視窗有輸入焦點。有輸入焦點的那個應用程式的標題條總是高亮度顯示的。 實際上您可以從兩個角度來看鍵盤訊息:一是您可以把它看成是一大堆的按鍵訊息的集合,在這種情況下,當您按下一個鍵時,WINDOWS就會傳送一個WM_KEYDOWN給有輸入焦點的那個應用程式,提醒它有一個鍵被按下。當您釋放鍵時,WINDOWS又會傳送一個WM_KYEUP訊息,告訴有一個鍵被釋放。您把每一個鍵當成是一個按鈕;另一種情況是:您可以把鍵盤看成是字元輸入裝置。當您按下“a”鍵時,WINDOWS傳送一個WM_CHAR訊息給有輸入焦點的應用程式,告訴它“a”鍵被按下。實際上WINDOWS 內部傳送WM_KEYDOWN和WWM_KEYUP訊息給有輸入焦點的應用程式,而這些訊息將透過呼叫TranslateMessage翻譯成WM_CHAR訊息。WINDOWS視窗過程函式將決定是否處理所收到的訊息,一般說來您不大會去處理WM_KEYDOWN、WM_KEYUP訊息,在訊息迴圈中TranslateMessage函式會把上述訊息轉換成WM_CHAR訊息。在我們的課程中將只處理WM_CHAR。

例子:

.386
.model flat,stdcall
option casemap:none
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD

include masm32includewindows.inc
include masm32includeuser32.inc
include masm32includekernel32.inc
include masm32includegdi32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.lib
includelib masm32libgdi32.lib

.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
char WPARAM 20h ; the character the program receives from keyboard

.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?

.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
mov CommandLine,eax
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT

.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF 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
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start

分析:


char WPARAM 20h ; the character the program receives from keyboard

這個變數將儲存從鍵盤接收到的字元。因為它是在視窗過程中透過WPARAM型變數傳送的,所以我們簡單地把它定義為WPARAM型。由於我們的視窗在初次重新整理時(也即剛被建立的那一次)是沒有鍵盤輸入的所以我們把他設成空格符(20h),這樣顯示時您就什麼都看不見。

.ELSEIF uMsg==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
這一段是用來處理WM_CHAR訊息的。它把接收到的字元放入變數char中,接著呼叫InvalidateRect,而InvalidateRect使得視窗的客戶區無效,這樣它會發出WM_PAINT訊息,而WM_PAINT訊息迫使WINDOWS重新繪製它的客戶區。該函式的語法如下:

InvalidateRect proto hWnd:HWND,
lpRect:DWORD,
bErase:DWORD

lpRect是指向客戶區我們想要其無效的一個正方形結構體的指標。如果該值等於NULL,則整個客戶區都無效;布林值bErase告訴WINDOWS是否擦除背景,如果是TRUE,則WINDOWS在呼叫BeginPaint函式時把背景擦掉。 所以我們此處的做法是:我們將儲存所有有關重繪客戶區的資料,然後傳送WM_PAINT訊息,處理該訊息的程式段然後根據相關資料重新繪製客戶區。儘管這麼做事有點像走了弓背,但WINDOWS要處理那麼龐大的訊息群,沒有一定的規矩可不行。實際上我們完全可以透過呼叫GetDC 獲得裝置上下文控制程式碼,然後繪製字元,然後再呼叫ReleaseDC釋放裝置上下文控制程式碼,毫無疑問這樣也能在客戶區繪製出正確的字元。但是如果這之後接收到WM_PAINT訊息要處理時,客戶區會重新重新整理,而我們這稍前所繪製的字元就會消失掉。所以為了讓字元一直正確地顯示,就必須把它們放到WM_PAINT的處理過程中處理。而在本訊息處理中傳送WM_PAINT訊息即可。

invoke TextOut,hdc,0,0,ADDR char,1

在呼叫InvalidateRect時,WM_PAINT訊息被髮送到了WINDOWS視窗處理過程,程式流程轉移到處理WM_PAINT訊息的程式段,然後呼叫BeginPaint得到裝置上下文的控制程式碼,再呼叫TextOut在客戶區的(0,0)處輸出儲存的按鍵字元。這樣無論您按什麼鍵都能在客戶區的左上角顯示,不僅如此,無論您怎麼縮放視窗(迫使WINDOWS重新繪製它的客戶區),字元都會在正確的地方顯示,所以必須把所有重要的繪製動作都放到處理WM_PAINT訊息的程式段中去。

[@more@]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928720/,如需轉載,請註明出處,否則將追究法律責任。

相關文章