在Microsoft Windows 中,鍵盤和鼠標(biāo)是兩個標(biāo)準(zhǔn)的用戶輸入源,在一些交疊的操作中通常相互補充使用。當(dāng)然,鼠標(biāo)在今天的應(yīng)用程序中比10年前使用得更為廣泛。甚至在一些應(yīng)用程序中,我們更習(xí)慣于使用鼠標(biāo),例如在游戲、畫圖程序、音樂程序,以及Web創(chuàng)覽器等程序中就是這樣。然而,我們可以不使用鼠標(biāo),但絕對不能從一般的PC中拆掉鍵盤。 相對于個人計算機(jī)的其他組件,鍵盤有非常久遠(yuǎn)的歷史,它起源于1874年的第一臺Remington打字機(jī)。早期的計算機(jī)程序員用鍵盤在Hollerith卡片上打孔,以后在啞終端上用鍵盤直接與大型主機(jī)通訊。PC上的鍵盤在某些方面進(jìn)行了擴(kuò)展,包括了功能鍵、光標(biāo)定位鍵和(通常都帶有的)單獨的數(shù)字鍵盤,但它們的輸入原理基本相同。
鍵盤基礎(chǔ)
Windows程序獲得鍵盤輸入的方式:鍵盤輸入以消息的形式傳遞給程序的窗口過程。實際上,第一次學(xué)習(xí)消息時,鍵盤就是一個明顯的例子:消息應(yīng)該傳遞給應(yīng)用程序的信息類型。 Windows用8種不同的消息來傳遞不同的鍵盤事件。這好像太多了,但是(就像我們所看到的一樣)程序可以忽略其中至少一半的消息而不會有任何問題。并且,在大多數(shù)情況下,這些消息中包含的鍵盤信息會多于程序所需要的。處理鍵盤的部分工作就是識別出哪些消息是重要的,哪些是不重要的。 一、鍵盤基礎(chǔ)知識 雖然應(yīng)用程序在很多情況下可以通過鼠標(biāo)實現(xiàn)信息的輸入,但到現(xiàn)在為止鍵盤仍然是PC機(jī)中不可替代的重要輸入設(shè)備。 用鍵盤當(dāng)作輸入設(shè)備,每當(dāng)用戶按下或釋放某一個鍵時,會產(chǎn)生一個中斷,該中斷激活鍵盤驅(qū)動程序KEYBOARD.DRV來對鍵盤中斷進(jìn)行處理。KEYBOARD.DRV程序會根據(jù)用戶的不同操作進(jìn)行編碼,然后調(diào)用Windows用戶模塊USER.EXE生成鍵盤消息,并將該消息發(fā)送到消息隊列中等候處理。 1.掃描碼和虛擬碼 掃描碼對應(yīng)著鍵盤上的不同鍵,每一個鍵被按下或釋放時,都會產(chǎn)生一個唯一的掃描碼作為本身的標(biāo)識。掃描碼依賴于具體的硬件設(shè)備,即當(dāng)相同的鍵被按下或釋放時,在不同的機(jī)器上可能產(chǎn)生不同的掃描碼。在程序中通常使用由Windows系統(tǒng)定義的與具體設(shè)備無關(guān)的虛擬碼。在擊鍵產(chǎn)生掃描碼的同時,鍵盤驅(qū)動程序KEYBOARD.DRV截取鍵的掃描碼,然后將其翻譯成對應(yīng)的虛擬碼,再將掃描碼和虛擬碼一齊編碼形成鍵盤消息。所以,最后發(fā)送到消息隊列的鍵盤消息中,既包含了掃描碼又包含了虛擬碼。 經(jīng)常使用的虛擬碼在WINDOWS.H文件中定義,常用虛擬碼的數(shù)值、常量符號和含義如表所示。
取值(16進(jìn)制) 常量符號 含義 01 VK_LBUTTON 鼠標(biāo)左鍵 02 VK_RBUTTON 鼠標(biāo)右鍵 03 VK_CANCEL Break中斷鍵 04 VK_MBUTTON 鼠標(biāo)中鍵 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 -- 漢字系統(tǒng)保留 1A -- 未定義 1B VK_ESCAPE Esc鍵 1C-1F -- 漢字系統(tǒng)保留 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 數(shù)字鍵0-9 3A-40 -- 未定義 41-5A VK_A-VK_Z 字母鍵A-Z 5B-5F -- 未定義 60-69 VK_NUMPAD0-VK_NUMPAD9 小鍵盤數(shù)字鍵0-9 6A VK_MULTIPLY *(乘號)鍵 6B VK_ADD +(加號)鍵 6C VK_SEPAPATOR 分隔符鍵 6E VK_SUBTRACT -(減號)鍵 6F VK_DECIMAL .(小數(shù)點)鍵 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.輸入焦點 同一時刻,Windows中可能有多個不同的程序在運行,也就是說有多個窗口同時存在。這時,鍵盤由多個窗口共享,但只有一個窗口能夠接收到鍵盤消息,這個能夠接收鍵盤消息的窗口被稱為擁有輸入焦點的窗口。 擁有輸入焦點的窗口應(yīng)該是當(dāng)前的活動窗口,或者是活動窗口的子窗口,其標(biāo)題和邊框會以高亮度顯示,以區(qū)別于其他窗口。擁有輸入焦點的也可以是圖標(biāo)而不是窗口,此時,Windows也將消息發(fā)送給圖標(biāo),只是消息的格式略有不同。 窗口過程可以通過發(fā)送WM_SETFOCUS和 WM_KILLFOCUS消息使窗體獲得或失去輸入焦點。程序也可以通過捕獲WM_SETFOCUS和WM_KILLFOCUS消息來判斷窗體何時獲得或失去輸入焦點。其中WM_SETFOCUS消息表示窗口正獲得輸入焦點,WM_ KILLFOCUS消息表示窗口正失去輸入焦點。 3.鍵盤消息 鍵盤消息分為系統(tǒng)鍵消息和非系統(tǒng)鍵消息。系統(tǒng)鍵消息是指由Aft鍵和其他鍵組合而產(chǎn)生的按鍵消息。當(dāng)系統(tǒng)鍵被按下時產(chǎn)生WM_ SYSKEYDOWN消息,當(dāng)系統(tǒng)鍵被釋放時產(chǎn)生WM_SYSKEYUP消息。 Aft鍵與其他鍵形成的組合鍵通常用于對程序菜單和系統(tǒng)菜單進(jìn)行選擇,或用于在不同的程序之間進(jìn)行切換。因此,系統(tǒng)鍵消息應(yīng)該交由Windows進(jìn)行處理,用戶所編制的程序一般不處理系統(tǒng)鍵消息,而是將這些消息交由DefWindowProc函數(shù)進(jìn)行處理。如果用戶想對系統(tǒng)鍵消息進(jìn)行處理,應(yīng)該在處理完這些消息后,再將其發(fā)送給DefWindowProc函數(shù),使得Windows系統(tǒng)能夠正常工作。 某些擊鍵消息可以被轉(zhuǎn)換成字符消息,例如字母鍵、數(shù)字鍵等。而有些鍵只能產(chǎn)生按鍵消息而沒有字符消息,例如 Shift鍵、Insert鍵等。消息循環(huán)中的 TranslateMessage函數(shù)可以實現(xiàn)從擊鍵消息向字符消息的轉(zhuǎn)化。當(dāng)GetMessage函數(shù)捕獲一個WM_SYSKEYDOWN消息或WM_KEYDOWN消息后,TranslateMessage函數(shù)判斷產(chǎn)生該消息的鍵是否能夠被轉(zhuǎn)換成字符消息,如果能,就將該消息轉(zhuǎn)換成字符消息,再通過DispatchMessape函數(shù)將轉(zhuǎn)換后的字符消息發(fā)送到消息隊列中去。字符消息共有以下四種,如表所示。
字符 系統(tǒng)字符 非系統(tǒng)字符 普通字符 WM_SYSCHAR WM_CHAR 死字符 WM_SYSDEADCHAR WM_DEADCHAR
其中死字符是由某些特殊鍵盤上的按鍵所造成的,Windows一般忽略死字符所產(chǎn)生的消息。 Windows的消息一般是通過一個MSG結(jié)構(gòu)體變量傳送給消息處理函數(shù)的。對于鍵盤消息, MSG結(jié)構(gòu)體變量的各個域中較重要的是lParam域和 wParam域。wParam域用于保存按鍵的虛擬鍵代碼或字符的ASCII碼。對于非字符消息,wParam域保存按鍵的虛擬健代碼;對于字符消息,wParam域不保存字符的ASCII碼。lParam域則用于保存擊鍵時產(chǎn)生的附加信息,實際上一個32位的lParam變量被分為六部分,記錄了以下相關(guān)信息:重復(fù)次數(shù)、OEM掃描碼、擴(kuò)展鍵標(biāo)志、關(guān)聯(lián)鍵標(biāo)志、前一擊鍵狀態(tài)和轉(zhuǎn)換狀態(tài)。lParam域各位的含義如表所示。
位數(shù) 含義 0-15 擊鍵重復(fù)次數(shù)累加 16-23 OEM掃描碼 24 是否為擴(kuò)展鍵 25-28 未定義 29 是否便用關(guān)聯(lián)鍵,及Alt鍵是否同時按下。 30 前一次擊鍵狀態(tài),0表示該鍵前一次狀態(tài)為抬起,1表示前一次狀態(tài)為按下 31 轉(zhuǎn)換狀態(tài)
按鍵的次序不同,產(chǎn)生的消息也不相同。例如,按下并釋放1鍵,讀過程依次產(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
|