2010-07-03 49 views
44

我在Windows窗體項目上工作了一段時間,然後決定嘗試使用鍵盤快捷鍵。一點閱讀後,我算了一下,只寫一個事件處理程序,並將其綁定到窗體的KeyDown事件:對KeyDown事件沒有響應的表單

private void Form1_KeyDown(object sender, KeyEventArgs e) 
{ 
    if (e.Control && e.Alt && e.KeyCode == Keys.O) 
    { 
     MessageBox.Show("Ctrl+Alt+O: magic!"); 
    } 
} 

我這樣做,打開Visual Studio設計的屬性面板的好醇」的方式,然後雙擊我的表單的KeyDown事件來生成Form1_KeyDown事件處理程序。但是在測試我的應用程序時,表單完全沒有響應。Ctrl + Alt + O鍵盤快捷鍵。 Visual Studio設計確實生成的代碼雖然到事件處理程序的窗體綁定:

private void InitializeComponent() 
{ 
    // ... 

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown); 

    // ... 
} 

於是,我就加入了Console.WriteLine()調用處理程序,以檢查它被稱爲可言,但沒有運氣無論是。另外,我嘗試在事件綁定調用(如上所示)上設置一個斷點,並發現程序到達該斷點就好了。但是我在方法定義本身中設置的任何斷點永遠都不會到達。

爲了確保我在做正確的前幾個步驟,我試着重複他們:

  • 在同解的新形式。
    同一個問題:當我按下Ctrl鍵+ Alt鍵+Ø鍵盤快捷鍵和調試器甚至沒有步入事件處理程序的形式不響應。試了一遍,它的工作原理。

  • 一個全新的WinForms解決方案。
    它完美地工作:消息對話框出現(Console.WriteLine()調用也可以)。

所以我很迷茫。什麼阻止了這個項目中的所有表單接收KeyDown事件?

回答

107

您的窗體是否將KeyPreview屬性設置爲true?

Form.KeyPreview物業

獲取或設置指示該事件被傳遞給具有焦點的控制之前,窗體是否將接收鍵 事件的值。

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx

+0

不,所以我改變了它,解決了它!感謝您的回答和文檔鏈接。 – BoltClock 2010-07-03 20:28:50

+17

這是一個黑客攻擊,可以讓VB6程序員快樂。它具有執行順序問題,而是重寫ProcessCmdKey()。 – 2010-07-03 21:31:52

+0

@HansPassant,我找不到任何解釋執行順序問題的東西。 KeyDown + KeyPreview不會看到所有的鍵,這足以解決問題,但執行順序問題又是什麼? – kdbanman 2015-12-08 23:11:28

17

試試你的窗體上的KeyPreview屬性設置爲true。這對我註冊按鍵很有幫助。

+0

是的,就是這樣!非常感謝。 – BoltClock 2010-07-03 20:28:14

23

建議對StackOverflow上和MSDN 12(包括在這裏接受的答案)這個問題最常見的部分是快速和容易:

KeyDown事件被觸發,只要一個FormKeyPreview屬性設置爲true

這足以滿足大多數的目的,但它是有風險的,原因有二:

  1. KeyDown處理程序do not see all keys。具體來說,「你不能看到用於導航的按鍵類型,就像光標鍵和Tab,Escape和Enter對話框一樣。」

  2. 攔截關鍵事件有幾種不同的方式,它們都按順序發生。 KeyDown處理最後。因此,KeyPreview不是一個預覽,事件可能會在途中的幾個停止沉默。

(感謝@HansPassant這些點。)

相反,在你的Form覆蓋ProcessCmdKey

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { 
    if (keyData == Keys.Up) 
    { 
     // Handle key at form level. 
     // Do not send event to focused control by returning true. 
     return true; 
    } 
    return base.ProcessCmdKey(ref msg, keyData); 
} 

這樣一來,所有的按鍵對於方法可見,和該方法首先可以查看事件。

請注意,您仍然可以控制聚焦控件是否參見KeyDown事件。只需返回true以阻止後續的KeyDown事件,而不是像在KeyDown事件處理程序中那樣將KeyPressEventArgs.Handled設置爲trueHere是一篇有更多細節的文章。

+1

這是正確的答案,特別是如果您發現PreviewKeyDown根本不會在KeyPreview設置爲true時觸發。 – Tim 2016-01-27 23:16:59

+0

真的,真的很有幫助。如果可以的話,我會加倍努力!謝謝 – 2017-02-09 15:41:58