Windows鍵盤訊息處理

2021-09-07 01:15:57 字數 4617 閱讀 8858

本文大部分來自msdn和網友的部落格,我在實踐的基礎上再作了一些總結。

1,虛擬鍵(vk_*)

鍵盤上每乙個鍵對應乙個掃瞄碼,掃瞄碼是oem廠商制定的,不同的廠商生產的鍵盤同樣乙個按鍵的掃瞄碼都有可能出現不一致的情況,為了擺脫由於系統裝置不一致的情況,通過鍵盤驅動程式將掃瞄碼對映為統一的虛擬鍵碼表示,從而達到所有的裝置都有乙個統一的虛擬鍵,比如回車鍵的虛擬鍵是vk_return。

windows定義的虛擬鍵都定義在winuser.h這個標頭檔案裡面,都是以vk_作為字首。

2,啟用/關閉視窗對鍵盤的訊息

啟用/關閉訊息:wm_setfocus/wm_killfocus

建立游標:createcaret(...)

設定游標位置:setcaretpos(…)

在視窗中顯示游標:showcaret(…)

銷毀游標:destroycaret()

3,鍵盤訊息

1)字元訊息

系統字元訊息

wm_syschar:系統字元

wm_sysdeadchar:系統死字元

非系統按鍵訊息

wm_char:非系統字元

wm_deadchar:非系統死字元

2)按鍵訊息

系統按鍵訊息:與alt鍵相組合的組合鍵(無論使用者處理否,都需要最後呼叫defwindowproc(hwnd,imessage,wparam,lparam))

wm_syskeydown

wm_syskeyup

非系統按鍵訊息:

wm_keydown

wm_keyup

注意:a)除print鍵之外都有「按下」訊息。

b) 所有鍵都存在「彈起」訊息。

c)根據msdn說明,只有下面這些鍵才會產生字元訊息:

我們是怎麼收到wm_char的呢?就是因為我們在訊息迴圈時呼叫了translatemessage對鍵盤訊息進行翻譯,

如果訊息為wm_keydown或者wm_syskeydown,並且按鍵與位移狀態相組合產生乙個字元,則translatemessage把字元訊息放入訊息佇列中。此字元訊息將是getmessage從訊息佇列中得到的按鍵訊息之後的下乙個訊息。

在我們處理這個訊息時,對應的wparam不是虛擬鍵,而是ansi或unicode字元**,一般情況下我們可以這樣用:(tchar)wparam;

4,訊息順序

因為translatemessage函式從wm_keydown和wm_syskeydown訊息產生了字元訊息,所以字元訊息是夾在按鍵訊息之間傳遞給視窗訊息處理程式的。例如,如果caps lock未開啟,而使用者按下再釋放a鍵,則視窗訊息處理程式將接收到如表6-10所示的三個訊息:

表6-10

訊息按鍵或者**

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x61)

wm_keyup

「a」的虛擬鍵碼(0x41)

如果您按下shift鍵,再按下a鍵,然後釋放a鍵,再釋放shift鍵,就會輸入大寫的a,而視窗訊息處理程式會接收到五個訊息,如表6-11所示:

表6-11

訊息按鍵或者**

wm_keydown

虛擬鍵碼vk_shift (0x10)

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x41)

wm_keyup

「a」的虛擬鍵碼(0x41)

wm_keyup

虛擬鍵碼vk_shift(0x10)

shift鍵本身不產生字元訊息。

如果使用者按住a鍵,以使自動重複產生一系列的按鍵,那麼對每條wm_keydown訊息,都會得到一條字元訊息,如表6-12所示:

表6-12

訊息按鍵或者**

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x61)

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x61)

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x61)

wm_keydown

「a」的虛擬鍵碼(0x41)

wm_char

「a」的字元**(0x61)

wm_keyup

「a」的虛擬鍵碼(0x41)

如果某些wm_keydown訊息的重複計數大於1,那麼相應的wm_char訊息將具有同樣的重複計數。

組合使用ctrl鍵與字母鍵會產生從0x01(ctrl-a)到0x1a(ctrl-z)的ascii控制**,其中的某些控制**也可以由表6-13列出的鍵產生:

表6-13

按鍵字元**

產生方法

ansi c控制字元

backspace

0x08

ctrl-h \b

tab0x09

ctrl-i \t

ctrl-enter

0x0a

ctrl-j \n

enter

0x0d

ctrl-m \r

esc0x1b

ctrl-[

最右列給出了在ansi c中定義的控制字元,它們用於描述這些鍵的字元**。

我們一般可以這樣處理wm_carh訊息:

case wm_char:

} 我們可以在wm_char裡面判斷當前是否有指定的鍵被按下:

bool bisctrl = (::getasynckeystate(vk_control) & 0x8000); (mfc原始碼 afxcolordialog.cpp 460行)或

bool bisctrl = (::getkeystate(vk_control) & 0x8000);

下面我解釋一下鍵盤訊息的lparam引數,這個引數在msdn上面都可以查到,只是英文,我這裡作一些簡單的說明:(以wm_keydown為例)

wparam:虛擬鍵值,vt_*等值。

lparam:根據其不同的位數表示的含義不同可以分以下幾部分:

(1) 重複計數字(0 - 15 位):表示訊息按鍵資料。一般情況下為1,當鍵一直按下,視窗過程就會連續收到w_keydown訊息,但有可能視窗過程來不及處理這些按鍵訊息,那麼windows就會把幾個按鍵訊息組合成乙個,並增加重複計數。比如你處理wm_keydown時sleep(200),那麼得到的這個數字就可能大於1,一般可以這樣來得到這個計數:

dword count = (((dword)lparam) & 0x0000ffff);

(3) 擴充套件鍵標誌(24位):擴充套件鍵標誌在有alt鍵(或ctrl鍵)按下時為1,否則為0。

(4) 保留位(25~28位):保留位是系統預設保留的,一般不用。

(5) 關聯碼(29位):關聯碼用來記錄某鍵與alt鍵的組合狀態,若按下alt,當wm_syskeydown訊息送到某個啟用的視窗時,其值為1,否則為0。

(6) 鍵的先前狀態(位30):鍵的先前狀態用於記錄先前某鍵的狀態,對於wm_syskeyup訊息,其值始終為1。

(7) 轉換狀態(31位):轉換狀態的訊息是始終按著某鍵所產生的訊息,若某鍵原來是按下的,則其先前狀態為0。轉換狀態指示鍵被按下還是被鬆開。當鍵被按下時,對應於者wm_syskeydown訊息,其值始終為0,當鍵被鬆開時,其轉換狀態為1,對應於wm_syskeyup訊息,其值始終為1。

5,死字元訊息

windows程式經常忽略wm_deadchar和wm_sysdeadchar訊息,但您應該明確地知道死字元是什麼,以及它們工作的方式。

在某些非u.s.英語鍵盤上,有些鍵用於給字母加上音調。因為它們本身不產生字元,所以稱之為「死鍵」。例如,使用德語鍵盤時,對於u.s.鍵盤上的+/=鍵,德語鍵盤的對應位置就是乙個死鍵,未按下shift鍵時它用於標識銳音,按下shift鍵時則用於標識抑音。

當使用者按下這個死鍵時,視窗訊息處理程式接收到乙個wparam等於音調本身的ascii或者unicode**的wm_deadchar訊息。當使用者再按下可以帶有此音調的字母鍵(例如a鍵)時,視窗訊息處理程式會接收到wm_char訊息,其中wparam等於帶有音調的字母「a」的ansi**。

因此,使用者程式不需要處理wm_deadchar訊息,原因是wm_char訊息已含有程式所需要的所有資訊。windows的做法甚至還設計了內部錯誤處理。如果在死鍵之後跟有不能帶此音調符號的字母(例如「s」),那麼視窗訊息處理程式將在一行接收到兩條wm_char訊息-前乙個訊息的wparam等於音調符號本身的ascii**(與傳遞到wm_deadchar訊息的wparam值相同),第二個訊息的wparam等於字母s的ascii**。

當然,要感受這種做法的運作方式,最好的方法就是實際操作。您必須載入使用死鍵的外語鍵盤,例如前面講過的德語鍵盤。您可以這樣設定:在「控制台」中選擇「鍵盤」,然後選擇「語系」頁面標籤。然後您需要乙個應用程式,該程式可以顯示它接收的每乙個鍵盤訊息的詳細資訊。下面的keyview1就是這樣的程式。

windows鍵盤訊息

鍵盤訊息分為擊鍵訊息和字元訊息 擊鍵訊息,如 wm keydown wm keyup wm syskeydown wm syskeyup 字元訊息,如 wm char wm deadchar wm syschar wm sysdeadchar 帶有sys表示一般交給defwindowproc處理,如...

Windows訊息處理

這裡簡述一下關於window訊息處理,主要在實際應用中 在乙個windows程式中,乙個程式的的訊息是通過乙個大迴圈來實現接收處理的 這個可以檢視win32程式的編寫,具體可以詳細查詢相關資料 在windows程式設計中,尤其是mfc程式中,關於視窗訊息是非常重要的 視窗過程函式 接收處理視窗訊息的...

WPF處理Windows訊息

wpf中處理訊息首先要獲取視窗控制代碼,建立hwndsource物件 通過hwndsource物件新增訊息處理 函式.hwndsource類 hwndsource class implements its own window procedure.實現其自己的視窗過程。建立視窗之後使用 addhoo...