處理鍵盤輸入訊息(轉)
在本課中,我們將要學習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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- VCL中訊息處理初探 (轉)
- windows10家庭版鍵盤無法輸入怎麼修復_win10鍵盤不能輸入處理方法WindowsWin10
- Python-OpenCV 處理視訊(一)(二): 輸入輸出 視訊處理PythonOpenCV
- C#的訊息處理方法 (轉)C#
- 處理鍵盤通知
- JAVA 接收鍵盤輸入Java
- vm安裝win10 鍵盤無法輸入如何處理_vm安裝win10鍵盤無法輸入怎麼解決Win10
- IOS 訊息推送處理iOS
- Python-OpenCV 處理視訊(一): 輸入輸出PythonOpenCV
- C++ BUILDER 訊息處理的深入探索 (轉)C++UI
- java中如何捕獲鍵盤訊息Java
- php ActiveMQ的傳送訊息,與處理訊息PHPMQ
- MPLS RSVP訊息處理——VecloudCloud
- Storm保證訊息處理ORM
- 三、訊息的可靠處理
- 靈活定義和處理SOAP頭訊息 (轉)
- 鍵盤亂鍵怎麼處理 電腦鍵盤按鍵錯亂
- php 之讀取鍵盤輸入PHP
- go 如何監控鍵盤輸入Go
- 限制鍵盤輸入字元/位數字元
- java鍵盤輸入和延時Java
- Java - 4 鍵盤輸入語句Java
- python-input鍵盤輸入Python
- VC++基礎 判斷鍵盤訊息C++
- iOS 防止輸入時鍵盤覆蓋掉輸入框iOS
- .net core 訊息流處理流程
- EPP4加密鍵盤故障處理手冊(轉貼)加密
- MFC動態建立控制元件的訊息處理 (轉)控制元件
- win10鍵盤無法輸入任何東西 win10鍵盤無法輸入的方法Win10
- 如何處理RabbitMQ 訊息堆積和訊息丟失問題MQ
- 關於捕獲VCL沒有處理的Windows訊息 (轉)Windows
- Android高仿微信表情輸入與鍵盤輸入詳解Android
- iOS 文字輸入框隨鍵盤上移iOS
- 同文輸入法更換鍵盤主題
- 傑裡之不執行對箱按鍵同步訊息處理方法【篇】
- win10輸入法新增美式鍵盤怎麼操作_win10輸入法如何新增美式鍵盤Win10
- 處理檔案上傳時的訊息格式轉換問題
- 處理滑鼠離開視窗的訊息 (WM_MOUSELEAVE) (轉)