2011-01-08 22 views
0

代碼:的KeyEvents只能結合CTRL

Private Sub KeyHandling(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown 
    Select Case e.KeyCode 
     Case Keys.Left 
     btnPrev.PerformClick() 
     Case Keys.Right 
     btnNext.PerformClick() 
     Case Keys.Up 
     btnFirst.PerformClick() 
     Case Keys.Down 
     btnLast.PerformClick() 
    End Select 
End Sub 

我的窗體的KeyPreview屬性已啓用。

問題:

此代碼不會做任何事情,除非我按住Ctrl鍵。任何人都可以解釋嗎? :)

回答

0

這是因爲在KeyDown事件觸發之前,光標鍵被提前截獲。 Winforms使用它來移動焦點,就像Tab一樣。當您按住Ctrl鍵時,它不再是導航鍵,並且您的KeyDown事件可以看到它。

你通常會通過重寫IsInputKey()來解決這個問題,但如果表單有任何控件,那麼這將不起作用。如果將KeyPreview設置爲true,他們可能會這樣做。形式從來沒有得到重點,控制做。您需要放棄KeyPreview,無論如何,這是舊的VB6時代錯誤,您可以通過重寫ProcessCmdKey()來捕獲遊標鍵。像這樣:

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean 
    If keyData = Keys.Left Then 
     Console.WriteLine("left") 
     Return True 
    End If 
    Return MyBase.ProcessCmdKey(msg, keyData) 
End Function 
0

我假設你有你的窗體上的按鈕。當按鈕具有焦點時,用戶可以通過使用表單上的按鈕之間的箭頭按鈕進行導航來更改焦點。這就是當按下箭頭鍵時按鈕沒有收到KeyDown事件的原因。

以下技巧將幫助您避免這種情況。對於每一個按鈕的形式設置PreviewKeyDown事件以下幾點:

Private Sub Button1_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown 
     e.IsInputKey = True 
End Sub 
+0

這可能會起作用,但如果可能的話,您應該在容器控制的更高級別上處理此問題。它使得代碼更加優雅和可維護。 – 2011-01-08 15:02:29

0

發生了什麼事是,箭頭鍵導航控件的形式,很像標籤關鍵。每按一次方向鍵,焦點就從當前激活的控制移動到與箭頭鍵相同的相對方向的下一個控制。

箭頭鍵的這種解釋在比您要處理的表單的KeyDown事件更高的級別上執行。每個按鍵實際上都被ProcessDialogKey function消耗,這防止了該關鍵事件被傳遞到您的KeyHandling方法以用於任何進一步處理。

,當你想到當按Ctrl鍵被按下一切工作的原因是ProcessDialogKey功能不消耗這些事件,允許它們被傳遞到您的事件處理程序方法。方法的documentation告訴我們:

該方法不對包含ALT或CONTROL修飾符的擊鍵進行處理。


如果你不想箭頭鍵你的控件之間只有「點擊」恰如其命名按鈕導航,解決方案應該是顯而易見的:你需要重寫ProcessDialogKey方法,添加自定義密鑰處理邏輯,並返回「True」值以表示您自己處理密鑰。否則,您將繼續前往基類,以免中斷標準處理如標籤輸入。同樣,documentation令人耳目一新這裏清楚:

當重寫在派生類中的ProcessDialogKey方法,控制應返回true,表明它已經處理的關鍵。對於未由控件處理的鍵,應返回調用基類ProcessDialogChar方法的結果。

只需將下面的代碼添加到您的表單,並刪除KeyHandling方法你現在有:

Protected Overrides Function ProcessDialogKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean 
    Select Case keyData 
     Case Keys.Left 
      btnPrev.PerformClick() 
      Return True 
     Case Keys.Right 
      btnNext.PerformClick() 
      Return True 
     Case Keys.Up 
      btnFirst.PerformClick() 
      Return True 
     Case Keys.Down 
      btnLast.PerformClick() 
      Return True 
    End Select 

    Return MyBase.ProcessDialogKey(keyData) 
End Function 
+0

很好的解釋!非常感謝你 – Jeroen 2011-01-08 15:01:22

0

您需要提供更多的信息。

對於初學者來說,您需要處理哪些形式的事件。您顯示具有非標準處理程序名稱的處理程序,但不顯示它與哪個事件關聯。你如何將它與事件聯繫起來?

在窗體設計器中,查看屬性窗口中的事件選項卡。 KeyDown或KeyPress下有什麼?這就是它需要的地方。

其次,它沒有做任何事情,因爲你沒有把它連接起來形成鍵盤事件,或者因爲它運行,但只是沒有做你想做的事情?設置一個斷點。代碼是否被調用?

根據對上述問題的回答,您可能需要在處理KeyDown或KeyPress事件之間切換,具體取決於您嘗試檢測哪些字符。

+0

你必須滾動才能看到它,但方法聲明的最後一行告訴你它處理的是什麼事件:`處理Me.KeyDown`。它已經適用於該方法。你必須檢查標籤 - 這不是C#。 – 2011-01-08 14:59:49