Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top