在Microsoft Windows 中,鍵盤(pán)和鼠標是兩個(gè)標準的用戶(hù)輸入源,在一些交疊的操作中通常相互補充使用。當然,鼠標在今天的應用程序中比10年前使用得更為廣泛。甚至在一些應用程序中,我們更習慣于使用鼠標,例如在游戲、畫(huà)圖程序、音樂(lè )程序,以及Web創(chuàng )覽器等程序中就是這樣。然而,我們可以不使用鼠標,但絕對不能從一般的PC中拆掉鍵盤(pán)。
相對于個(gè)人計算機的其他組件,鍵盤(pán)有非常久遠的歷史,它起源于1874年的第一臺Remington打字機。早期的計算機程序員用鍵盤(pán)在Hollerith卡片上打孔,以后在啞終端上用鍵盤(pán)直接與大型主機通訊。PC上的鍵盤(pán)在某些方面進(jìn)行了擴展,包括了功能鍵、光標定位鍵和(通常都帶有的)單獨的數字鍵盤(pán),但它們的輸入原理基本相同。
鍵盤(pán)基礎
Windows程序獲得鍵盤(pán)輸入的方式:鍵盤(pán)輸入以消息的形式傳遞給程序的窗口過(guò)程。實(shí)際上,第一次學(xué)習消息時(shí),鍵盤(pán)就是一個(gè)明顯的例子:消息應該傳遞給應用程序的信息類(lèi)型。
Windows用8種不同的消息來(lái)傳遞不同的鍵盤(pán)事件。這好像太多了,但是(就像我們所看到的一樣)程序可以忽略其中至少一半的消息而不會(huì )有任何問(wèn)題。并且,在大多數情況下,這些消息中包含的鍵盤(pán)信息會(huì )多于程序所需要的。處理鍵盤(pán)的部分工作就是識別出哪些消息是重要的,哪些是不重要的。
一、鍵盤(pán)基礎知識
雖然應用程序在很多情況下可以通過(guò)鼠標實(shí)現信息的輸入,但到現在為止鍵盤(pán)仍然是PC機中不可替代的重要輸入設備。
用鍵盤(pán)當作輸入設備,每當用戶(hù)按下或釋放某一個(gè)鍵時(shí),會(huì )產(chǎn)生一個(gè)中斷,該中斷激活鍵盤(pán)驅動(dòng)程序KEYBOARD.DRV來(lái)對鍵盤(pán)中斷進(jìn)行處理。KEYBOARD.DRV程序會(huì )根據用戶(hù)的不同操作進(jìn)行編碼,然后調用Windows用戶(hù)模塊USER.EXE生成鍵盤(pán)消息,并將該消息發(fā)送到消息隊列中等候處理。
1.掃描碼和虛擬碼
掃描碼對應著(zhù)鍵盤(pán)上的不同鍵,每一個(gè)鍵被按下或釋放時(shí),都會(huì )產(chǎn)生一個(gè)唯一的掃描碼作為本身的標識。掃描碼依賴(lài)于具體的硬件設備,即當相同的鍵被按下或釋放時(shí),在不同的機器上可能產(chǎn)生不同的掃描碼。在程序中通常使用由Windows系統定義的與具體設備無(wú)關(guān)的虛擬碼。在擊鍵產(chǎn)生掃描碼的同時(shí),鍵盤(pán)驅動(dòng)程序KEYBOARD.DRV截取鍵的掃描碼,然后將其翻譯成對應的虛擬碼,再將掃描碼和虛擬碼一齊編碼形成鍵盤(pán)消息。所以,最后發(fā)送到消息隊列的鍵盤(pán)消息中,既包含了掃描碼又包含了虛擬碼。
經(jīng)常使用的虛擬碼在WINDOWS.H文件中定義,常用虛擬碼的數值、常量符號和含義如表所示。
取值(16進(jìn)制) 常量符號 含義
01 VK_LBUTTON 鼠標左鍵
02 VK_RBUTTON 鼠標右鍵
03 VK_CANCEL Break中斷鍵
04 VK_MBUTTON 鼠標中鍵
05-07 -- 未定義
08 VK_BACK (BackSpace)鍵
09 VK_TAB Tab鍵
0A-0B -- 未定義
0C VK_CLEAR Clear鍵
0D VK_RETURN Enter鍵
0E-0F -- 未定義
10 VK_SHIFT Shift鍵
11 VK_CONTROL Ctrl鍵
12 VK_MENU Alt鍵
13 VK_PAUSE Pause鍵
14 VK_CAPTIAL CapsLock鍵
15-19 -- 漢字系統保留
1A -- 未定義
1B VK_ESCAPE Esc鍵
1C-1F -- 漢字系統保留
20 VK_SPACE 空格鍵
21 VK_PRIOR PageUp鍵
22 VK_NEXT PageDown鍵
23 VK_END End鍵
24 VK_HOME Home鍵
25 VK_LEFT ←(Left Arrow)鍵
26 VK_UP ↑(Up Arrow)鍵
27 VK_RIGHT →(Right Arrow)鍵
28 VK_DOWN ↓(Down Arrow)鍵
29 VK_SELECT Select鍵
2A -- OEM保留
2B VK_EXECUTE Execute鍵
2C VK_SNAPSHOT Print Screen鍵
2D VK_INSERT Insert鍵
2E VK_DELETE Delete鍵
2F VK_HELP Help鍵
30-39 VK_0-VK_9 數字鍵0-9
3A-40 -- 未定義
41-5A VK_A-VK_Z 字母鍵A-Z
5B-5F -- 未定義
60-69 VK_NUMPAD0-VK_NUMPAD9 小鍵盤(pán)數字鍵0-9
6A VK_MULTIPLY *(乘號)鍵
6B VK_ADD +(加號)鍵
6C VK_SEPAPATOR 分隔符鍵
6E VK_SUBTRACT -(減號)鍵
6F VK_DECIMAL .(小數點(diǎn))鍵
70-87 VK_DIVIDE /(除號)鍵
88-8F VK_F1-VK_F24 F1-F24功能鍵
90 VK_NUMBERLOCK Number lock鍵
91 VK_SCROLL Scroll lock鍵
92-B9 -- 未定義
BA-C0 -- OEM保留
C1-DA -- 未定義
DB_E4 -- OEM保留
E5 -- 未定義
E6 -- OEM保留
E7-E8 -- 未定義
E9-F5 -- OEM保留
F6-FE -- 未定義
2.輸入焦點(diǎn)
同一時(shí)刻,Windows中可能有多個(gè)不同的程序在運行,也就是說(shuō)有多個(gè)窗口同時(shí)存在。這時(shí),鍵盤(pán)由多個(gè)窗口共享,但只有一個(gè)窗口能夠接收到鍵盤(pán)消息,這個(gè)能夠接收鍵盤(pán)消息的窗口被稱(chēng)為擁有輸入焦點(diǎn)的窗口。
擁有輸入焦點(diǎn)的窗口應該是當前的活動(dòng)窗口,或者是活動(dòng)窗口的子窗口,其標題和邊框會(huì )以高亮度顯示,以區別于其他窗口。擁有輸入焦點(diǎn)的也可以是圖標而不是窗口,此時(shí),Windows也將消息發(fā)送給圖標,只是消息的格式略有不同。
窗口過(guò)程可以通過(guò)發(fā)送WM_SETFOCUS和 WM_KILLFOCUS消息使窗體獲得或失去輸入焦點(diǎn)。程序也可以通過(guò)捕獲WM_SETFOCUS和WM_KILLFOCUS消息來(lái)判斷窗體何時(shí)獲得或失去輸入焦點(diǎn)。其中WM_SETFOCUS消息表示窗口正獲得輸入焦點(diǎn),WM_ KILLFOCUS消息表示窗口正失去輸入焦點(diǎn)。
3.鍵盤(pán)消息
鍵盤(pán)消息分為系統鍵消息和非系統鍵消息。系統鍵消息是指由Aft鍵和其他鍵組合而產(chǎn)生的按鍵消息。當系統鍵被按下時(shí)產(chǎn)生WM_ SYSKEYDOWN消息,當系統鍵被釋放時(shí)產(chǎn)生WM_SYSKEYUP消息。 Aft鍵與其他鍵形成的組合鍵通常用于對程序菜單和系統菜單進(jìn)行選擇,或用于在不同的程序之間進(jìn)行切換。因此,系統鍵消息應該交由Windows進(jìn)行處理,用戶(hù)所編制的程序一般不處理系統鍵消息,而是將這些消息交由DefWindowProc函數進(jìn)行處理。如果用戶(hù)想對系統鍵消息進(jìn)行處理,應該在處理完這些消息后,再將其發(fā)送給DefWindowProc函數,使得Windows系統能夠正常工作。
某些擊鍵消息可以被轉換成字符消息,例如字母鍵、數字鍵等。而有些鍵只能產(chǎn)生按鍵消息而沒(méi)有字符消息,例如 Shift鍵、Insert鍵等。消息循環(huán)中的 TranslateMessage函數可以實(shí)現從擊鍵消息向字符消息的轉化。當GetMessage函數捕獲一個(gè)WM_SYSKEYDOWN消息或WM_KEYDOWN消息后,TranslateMessage函數判斷產(chǎn)生該消息的鍵是否能夠被轉換成字符消息,如果能,就將該消息轉換成字符消息,再通過(guò)DispatchMessape函數將轉換后的字符消息發(fā)送到消息隊列中去。字符消息共有以下四種,如表所示。
字符 系統字符 非系統字符
普通字符 WM_SYSCHAR WM_CHAR
死字符 WM_SYSDEADCHAR WM_DEADCHAR
其中死字符是由某些特殊鍵盤(pán)上的按鍵所造成的,Windows一般忽略死字符所產(chǎn)生的消息。
Windows的消息一般是通過(guò)一個(gè)MSG結構體變量傳送給消息處理函數的。對于鍵盤(pán)消息, MSG結構體變量的各個(gè)域中較重要的是lParam域和 wParam域。wParam域用于保存按鍵的虛擬鍵代碼或字符的ASCII碼。對于非字符消息,wParam域保存按鍵的虛擬健代碼;對于字符消息,wParam域不保存字符的ASCII碼。lParam域則用于保存擊鍵時(shí)產(chǎn)生的附加信息,實(shí)際上一個(gè)32位的lParam變量被分為六部分,記錄了以下相關(guān)信息:重復次數、OEM掃描碼、擴展鍵標志、關(guān)聯(lián)鍵標志、前一擊鍵狀態(tài)和轉換狀態(tài)。lParam域各位的含義如表所示。
位數 含義
0-15 擊鍵重復次數累加
16-23 OEM掃描碼
24 是否為擴展鍵
25-28 未定義
29 是否便用關(guān)聯(lián)鍵,及Alt鍵是否同時(shí)按下。
30 前一次擊鍵狀態(tài),0表示該鍵前一次狀態(tài)為抬起,1表示前一次狀態(tài)為按下
31 轉換狀態(tài)
按鍵的次序不同,產(chǎn)生的消息也不相同。例如,按下并釋放1鍵,讀過(guò)程依次產(chǎn)生如表所示三條消息。按下1鍵所產(chǎn)生的消息和wParam的取值
消息 wParam變量取值
WM_KEYDOWN 虛擬碼1
WM_CHAR ASCII碼“1”
WM_KEYUP 虛擬碼1
如果按下Shift鍵后再按下1鍵并釋放,則依次產(chǎn)生如表所示的消息。按下 Shift鍵后按 1健所產(chǎn)生的消息和 wParam的取值
消息 wParam變量取值
WM_KEYDOWN 虛擬碼 VK_SHIFT
WM_KEYDOWN 虛擬碼 VK_1
WM_CHAR ASCII碼 “1”
WM_KEYUP 虛擬碼 VK_1
WM_KEYUP 虛擬碼 VK_SHIFT
聯(lián)系客服