Ok I did some research and effectively, the key_down event for the Arrow keys is captured before being processed...
Here is the source where it starts :
http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,7765d3efe64d5539
How it works
When a key is pressed, here is the list of what happens inside the control :
The function PreProcessControlMessageInternal
is called.
This function will raise the event PreviewKeyDown on the control.
Then it will call PreProcessMessage
.
The function PreProcessMessage
is called.
This function actually checks if anybody wants to use the key that has been pressed. In our case, (WM_KEYDOWN) :
The Control first calls ProcessCmdKey
: if anyone want to decide this is a command key, return True and use that key. nobody else will see that key has been down
Then the Control calls IsInputKey()
: If anyone decides this is an input key (TextBoxes for example), return True and process your key.
Then it calls ProcessDialogKey()
: [Litterally from ReferenceSource]
is called to check for dialog keys such as TAB, arrow keys, and mnemonics
What to do
In your case, you have three possibilities, the last being the best (and easiest) :
Process the message when ProcessDialogKey()
receives it :
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
Prevent the handling of this key so you can handle it in 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
The Best Way
So actually (and based on the comment of Zohar Peled), the best way is to handle the PreviewKeyDown event, so you don't have to override any other method :
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