问题
Code:
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
The KeyPreview property of my form is enabled.
Problem:
This code won't do anything, except when I hold the control key. Can anyone explain this? :)
回答1:
This is because the cursor keys get intercepted early, before the KeyDown event fires. Winforms uses it to move the focus, just like Tab. When you hold down the Ctrl key, it is no longer a navigating key and your KeyDown event can see it.
You'd normally fix that by overriding IsInputKey() but that won't work if the form has any controls. They probably do if you set KeyPreview to true. The form never gets the focus, the controls do. You need to give up on KeyPreview, it's an old VB6 anachronism anyway, you catch the cursor keys by overriding ProcessCmdKey(). Like this:
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
回答2:
I assume you have Buttons on your form. When a button has the focus the user can change the focus by navigate with the arrow buttons between the buttons on the form. That is the reason why buttons don't receive the KeyDown event when an arrow key is pressed.
Following trick will help you to avoid this. For every button on your form set the PreviewKeyDown event to the following:
Private Sub Button1_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs) Handles Button1.PreviewKeyDown
e.IsInputKey = True
End Sub
回答3:
What's happening is that the arrow keys are navigating the controls on the form, much like the Tab key. Each press of an arrow key is moving the focus from the currently active control to the next control in the same relative direction as that arrow key.
This interpretation of arrow keys is implemented at a higher level than the form's KeyDown
event that you're handling. Each key press is actually being consumed by the ProcessDialogKey function, which is preventing that key event from ever being passed down to your KeyHandling
method for any further processing.
The reason that everything works as you expect when the Ctrl key is held down is that the ProcessDialogKey
function doesn't consume those events, allowing them to be passed on to your event handler method. The method's documentation tells us:
The method performs no processing on keystrokes that include the ALT or CONTROL modifiers.
If you don't want the arrow keys to navigate between your controls and only to "click" the aptly-named buttons, the solution should be obvious: You need to override the ProcessDialogKey
method, add your custom key handling logic, and return a value of "True" to indicate that you processed the key yourself. Otherwise, you'll go ahead and call through to the base class so as not to disrupt the standard handling of things like Tab and Enter. Again, the documentation is refreshingly clear here:
When overriding the
ProcessDialogKey
method in a derived class, a control should return true to indicate that it has processed the key. For keys that are not processed by the control, the result of calling the base class'sProcessDialogChar
method should be returned.
Simply add the following code to your form, and remove the KeyHandling
method you have now:
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
回答4:
You need to provide a lot more information.
For starters, which form event are you handling. You show a handler with a non-standard handler name, but you don't show which event it is associated with. How are you associating it with an event?
In the form designer, look at the events tab in the Properties window. Do you have anything under KeyDown or KeyPress? That's where it needs to be.
Second, is it not doing anything because you don't have it hooked up to form keyboard events or because it runs but just doesn't do what you want? Set a breakpoint. Does the code ever get called?
Depending on the answer to the questions above, you may need to switch between handling the KeyDown or KeyPress event, depending on which characters you are trying to detect.
来源:https://stackoverflow.com/questions/4634315/keyevents-on-form-only-works-in-combination-with-ctrl