0

I'm trying to send a key down and up message via SendMessage instead of SendKeys -- I need to send the key when another application has focus, so SendKeys won't do. I've read prior questions on this. I can't seem to get any of the solutions offered to work. Here is some code illustrating the problem. I can't figure out why it won't work.

Public Class Form2

Declare Auto Function FindWindowEx Lib "user32" (ByVal hwndParent As IntPtr, ByVal hwndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr

Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Declare Auto Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As UInt32) As Integer


Private Sub SendMessageToNotepad()
    Dim lParamDown1, lParamUp1, lParamDown2, lParamUp2 As UInt32
    Dim repeatCount As UInt32 = 1, scanCode As UInt32 = 0, extended As UInt32 = 0, context As UInt32 = 0,
        previousState As UInt32 = 0, transition As UInt32 = 0
    ' TRYING TO SET THE LPARAM FOR BOTH THE KEYUP AND KEYDOWN COMMANDS

    scanCode = &H53
    lParamDown1 = repeatCount Or (scanCode << 16) Or (extended << 24) Or (context << 29) Or (previousState << 30) Or (transition << 31)
    transition = 1
    previousState = 1
    scanCode = &H53
    lParamUp1 = repeatCount Or (scanCode << 16) Or (extended << 24) Or (context << 29) Or (previousState << 30) Or (transition << 31)

    Dim notepads() As Process = Process.GetProcessesByName("notepad")
    If notepads.Length = 0 Then
        Return
    End If
    Dim child As IntPtr = FindWindowEx(notepads(0).MainWindowHandle, New IntPtr(0), "Edit", Nothing)

    If notepads(0) IsNot Nothing Then
        '  SEND THE KEYDOWN MESSAGE (i.e. &H100) (VK_S = &H53)
        SendMessage(child, &H100, &H53, lParamDown1)
        '  SEND THE KEYUP MESSAGE (i.e. &H100) (VK_S = &H53)
        SendMessage(child, &H101, &H53, lParamUp1)
    End If
End Sub

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    SendMessageToNotepad()
End Sub

End Class

  • Notepad probably translates to `WM_COMMAND` what you're trying to send (~`WM_SETTEXT` + (`CTRL + S`)). Maybe you can use UIAutomation instead (to add text to the Edit Control and activate the `Control + S` command). UIAutomation doesn't need the app to be focused either. – Jimi Sep 21 '21 at 04:48
  • Hi Jimmi, I edited the code above to make it clearer. I think the commented lines of the Code were confusing -- I had actually intended to remove them.. I've added new comments to clarify the Code and removed extraneous lines from it. While a commented-out line of my Code was sending a WM_SETTEXT message, this code snippet is attempting to send a WM_KEYDOWN followed by WM_KEYUP message. It is attempting to send just an "s" keydown and keyup to notepad (not ctrl s at this point). Thanks and best regards.. – user1482264 Sep 21 '21 at 15:37
  • If you just want to send a char, post `WM_CHAR ` or `WM_KEYDOWN`: `PostMessage([Edit Handle], WM_KEYDOWN, VK_S, 1)`; posting `WM_CHAR`, you *print* an upper-case char (`S` instead of `s`): `PostMessage([Edit Handle], WM_CHAR, VK_S, 1)` -- BTW, don't use the ancient VB6 declaration syntax of Win32 functions. – Jimi Sep 21 '21 at 16:52
  • E.g., PostMessage should be declared as ` Private Shared Function PostMessage(hWnd As IntPtr, msg As UInteger, wParam As Integer, lParam As Integer) As Boolean End Function` (in 3 lines). `lParam` and `wParam` can also be declared as `IntPtr`. To post a char, it doesn't matter. `CharSet:=CharSet.Unicode` can be changed in `CharSet:=CharSet.Auto`, to automatically switch to the corresponding `A` or `W` version of the function. – Jimi Sep 21 '21 at 16:55
  • Use the Spy++ utility to discover that the code sends the message to the wrong window. – Hans Passant Sep 21 '21 at 17:31

0 Answers0