2016-03-30 107 views
1

我需要調整程序流程,具體取決於按鈕是否處於活動控制時按下箭頭。像這樣:.NET Winforms按鈕箭頭鍵KeyDown

Private Sub btn_OK_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles btn_OK.KeyDown 

    If e.KeyCode = Keys.Up Then 
     If mode = mymodes.first Then 
      firstcontrol.Focus() 
     Else 
      secondcontrol.Focus() 
     End If 
    End If 
End Sub 

正如我所看到的,按下任何箭頭鍵都不會觸發KeyDown事件。程序,而不是做一些他的內部功能,並通過使用窗體的選項卡順序移動焦點(如它似乎)。 KeyPreview在實際表單上設置爲true。

是否有任何方式獲得想要的功能與箭頭鍵和沒有子類化按鈕和使用ProcessCmdKey?

+0

請使用唯一的相關標籤。我已經刪除了C#標記,因爲您的代碼是vb.net。 –

+0

我會接受C#中的答案代碼。 – user1697111

+0

那麼在這種情況下,你應該在你的問題的文本中指定。否則就好像你在添加不相關的標籤。 –

回答

3

好吧,我做了一些研究,有效,對方向鍵key_down的事件被處理之前被捕獲...

這裏是它啓動源: http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,7765d3efe64d5539

它是如何工作

當按下一個鍵,這裏是控制內部發生了什麼列表:

功能PreProcessControlMessageInternal被調用。

此函數將引發控件上的事件PreviewKeyDown。 然後它會打電話PreProcessMessage

函數PreProcessMessage被調用。

該函數實際上檢查是否有人想使用已按下的鍵。在我們的例子中,(WM_KEYDOWN):

  • 控制首先調用ProcessCmdKey:如果有人想決定,這是一個命令鍵,返回True並使用該密鑰。沒有其他人會看到該鍵已關閉

  • 然後控制調用IsInputKey():如果有人決定這是一個輸入鍵(例如TextBoxes),則返回True並處理您的鍵。

  • 然後調用ProcessDialogKey():Litterally從ReferenceSource]

被稱爲檢查對話框鍵,如TAB,箭頭鍵和助記

怎麼辦

就你而言,你有三種可能性,最後是最好的(a第二最容易):

過程時ProcessDialogKey()接收它的信息:

Protected Overrides Function ProcessDialogKey(keyData As Keys) As Boolean 
    If keyData = Keys.Up Or keyData = Keys.Down Or keyData = Keys.Left Or keyData = Keys.Right Then 
     'Do whatever you want with the key 
     Return True 'So the processing will stop 
    End If 
    Return MyBase.ProcessDialogKey(keyData) 
End Function 

防止該鍵可以在Button_keyDown()

Protected Overrides Function ProcessDialogKey(keyData As Keys) As Boolean 
    If keyData = Keys.Up Or keyData = Keys.Down Or keyData = Keys.Left Or keyData = Keys.Right Then 
     Return False 
    End If 
    Return MyBase.ProcessDialogKey(keyData) 
End Function 


Private Sub btn_OK_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles btn_OK.KeyDown 

    If e.KeyCode = Keys.Up Then 
     If mode = mymodes.first Then 
      firstcontrol.Focus() 
     Else 
      secondcontrol.Focus() 
     End If 
    End If 
End Sub 

最佳處理它的處理方式

所以實際上(基於瑣佩萊德的評論),最好的辦法是處理PreviewKeyDown事件,所以你不必重寫任何其他方法:

Private Sub Form1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles MyBase.PreviewKeyDown 
    'Do whatever here, all the keydown events will fall into this sub. 
End Sub 
+0

Thanx Martin。我知道如何在子類中解決這個問題。我只是想知道是否可以從最高級別獲得這些信息,因爲所有這些事件和密鑰都是從IDE提供的,但顯然它們不起作用。 – user1697111

+0

@ user1697111您的表單已經是system.winfows.forms.form的派生類,因此您不需要任何其他派生類。 –

+0

很好的解釋。 +1進行研究。但是,只需處理'PreviewKeyDown'事件而不是'KeyDown'事件,就可以實現相同的行爲,因此不需要重寫'ProcessDialogKey'方法。 –

0

我注意到KeyUp與按鈕上的箭頭鍵一起使用,而KeyDown則沒有。這會有助於解決您的問題嗎?

+0

你會不會相信,在我的系統上,當按鈕獲得焦點時,會觸發KeyUp?把它放在處理函數下面,看看:Debug.Print(「KeyUp」&Me.ActiveControl.Name)Debug.Print(「KeyUp」&e.KeyCode.ToString)。 – user1697111

+0

如果按鈕獲得焦點,則「如果e.KeyCode = Keys.Up」應防止誤報。所以...基本上我的答案是工作,不是嗎?如果您有多個按鈕,您可以將它們指向相同的事件處理程序(如果需要的話)... – Brandtware

+0

不,KeyUp在按鈕關注時也無法按預期工作。 – user1697111

0

此代碼僅在焦點位於按鈕上時纔有效。

將此代碼在形式層面,所以有重點將錯過該事件的所有控件...

Private Sub myForm_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown 

    If e.KeyCode = Keys.Up Then 
     If mode = mymodes.first Then 
      firstcontrol.Focus() 
     Else 
      secondcontrol.Focus() 
     End If 
    End If 
End Sub 
+0

您是否嘗試過?因爲我最初的想法是這樣的,但事實證明,箭頭鍵根本不會引發key_down事件。 –

+0

(當然)不管用Me.KeyPreview設置都不起作用。請記住,我們談論Button控件。 – user1697111

+0

@ZoharPeled你是對的我只是試過它箭頭鍵只會引發KeyUp事件......我正在檢查裏面referencesource ... –

0

基於答案this question我想出了這個(測試和我的工作計算機)

Private Sub Form1_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles MyBase.PreviewKeyDown 
    If Me.Button1.Focused Then 
     If e.KeyCode = Keys.Up Then 
      If mode = mymodes.first Then 
       firstcontrol.Focus() 
      Else 
       secondcontrol.Focus() 
      End If 
     End If 
    End If 
End Sub 

原來,箭頭鍵沒有被key_down的事件默認處理,但它們是由PreviewKeyDown事件處理。

+0

這也不會工作(事件不會被解僱)。爲什麼不嘗試設置一個小表單,只有少量控件,並在發佈答案之前嘗試其工作?此外'這個問題'使用子類。 – user1697111

+0

注意:'(測試並在我的電腦上工作)'。另外請注意我正在處理'PreviewKeyDown'事件而不是'KeyDown'事件。此外,「這個問題」有更多的答案。 [這個答案](http://stackoverflow.com/a/14500362/3094533)不使用任何子類。 –