一個坑
在WPF應用程序(或者其他Windows應用程序中),為了監聽Alt鍵按下,我們可以嘗試寫出這樣的代碼:
PreviewKeyDown += (s, e) => { if (e.Key == Key.LeftAlt || e.Key == Key.RightAlt) { // A: 做些什么。 } };
然而,運行一看,發現並沒有什么用。A處的代碼根本就沒執行。
打個斷點看下,會發現, e.Key 的值是 Key.System 。這就奇怪了, Key.System 是個什么鬼?
一段源碼
看看KeyEventArgs中的源碼,我們發現微軟寫了這么個注釋:
/// <summary> /// The Key referenced by the event, if the key is not being /// handled specially. /// </summary> public Key Key { get {return _key;} }
如果按鍵沒有被特殊處理, Key 屬性才會返回正確的按鍵。這么說,當我們按下Alt鍵時,其實Windows或者WPF某一層特殊處理了這個按鍵。繼續閱讀源碼,發現這個屬性后面還有這樣一個屬性:
/// <summary> /// The Key referenced by the event, if the key is going to be /// processed by an system. /// </summary> public Key SystemKey { get { return (_key == Key.System) ? _realKey : Key.None;} }
跟剛剛的 Key 屬性相反,這個屬性指進行特殊處理時返回的按鍵。所以,截至這里,問題算是解決了,因為我們可以寫出這樣的代碼:
PreviewKeyDown += (s, e) => { Key key = (e.Key == Key.System ? e.SystemKey : e.Key); if (key == Key.LeftAlt || key == Key.RightAlt) { // A: 做些什么。 } };
一個解釋
然而事情肯定不能這樣就結束了,微軟為什么要設計這樣奇怪的機制?為什么Alt鍵要成為特殊系統按鍵?
經過一系列搜索,我找到了解釋:
在Windows系統中,Alt鍵會被特殊處理。當單獨按下Alt鍵,或者按下一個帶有Alt的組合鍵時,操作系統會將此事件視為“系統按鍵”(System keypress)。系統按鍵與普通按鍵相比,其處理過程是不同的。
首先,無論是系統按鍵還是普通按鍵,Windows都會將這些事件傳遞給應用程序。如果是普通按鍵,則傳遞 WM_KEYDOWN ,但如果是Alt鍵,則傳遞 WM_SYSKEYDOWN ;同理, WM_KEYUP 也會轉變成 WM_SYSKEYUP 。
在Windows中(包括WPF中),Alt鍵如此特殊是為了處理應用程序中那些帶有“特殊標記”文字的菜單項(MenuItems)、按鈕(Buttons)和其它標簽(Labels)的。舉個例子,如果按鈕的文字內容被設置成“Say _Hi”,那么Alt+H快捷鍵就會被轉變成為一次按鈕點擊(Click)事件。
這段解釋可以在這里http://stackoverflow.com/questions/3099472/previewkeydown-is-not-seeing-alt-modifiers得到更詳細的信息。