The following code works and will print to Label1 when the user presses the a key on the keyboard:
Public Class Form1
Sub New()
InitializeComponent()
End Sub
Public Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal HWND As IntPtr, ByVal WMSG As Integer, ByVal WPARAM As Integer, ByVal LPARAM As IntPtr) As IntPtr
Private WM_KEYDOWN As Integer = &H100
Protected Overrides Sub WndProc(ByRef WindowsMessage As Message)
Select Case WindowsMessage.Msg
Case WM_KEYDOWN
Dim VirtualKeyCode As Integer = CType(WindowsMessage.WParam, Integer)
Select Case (VirtualKeyCode)
Case Keys.A
Label1.Text = "The a key was pressed"
End Select
End Select
MyBase.WndProc(WindowsMessage)
End Sub
End Class
The code stops working after adding (dragging) a button to the form. The WM_KEYDOWN message is no longer sent once the button is on the form. A breakpoint set at Case WM_KEYDOWN never gets hit.
If I remove the button the code starts working again.
Any suggestions?
Thanks.
Keyboard message are posted to the window that has the focus. As long as your Form doesn't have any child controls, the form will get the focus when it is activated. Even though it isn't very good at dealing with getting the focus, it doesn't have any way to indicate that it has the focus for example and doesn't itself have any use for keystrokes.
That changes as soon as you put a control on the form that does like getting the focus. Like a Button. Now that control always gets the focus and you cannot give it back to the form. Accordingly, the form stops receiving WM_KEYDOWN messages, they go to the Button instead.
There is a way to have the form respond to keystrokes, they can be important if they are short-cut keys. Like F1 should display help, regardless of what control has the focus. There's built-in support for that in Winforms, you can override the ProcessCmdKey() method. Like this:
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
If keyData = Keys.Control Or Keys.A Then
MessageBox.Show("yada")
Return True
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
Paste this in your form's code and test it by pressing Ctrl+A.