Loading ...
Sorry, an error occurred while loading the content.
 

Sending keystrokes with SendMessage

Expand Messages
  • Dave Miller
    Looking through the archives, I found one thread about this, but it died out before a solution came up, so I m going to try fresh. I m trying to send
    Message 1 of 2 , Feb 6, 2006
      Looking through the archives, I found one thread about this, but it died out
      before a solution came up, so I'm going to try fresh.

      I'm trying to send keystrokes to a window that I can't be certain has focus.
      SendMessage (or, optionally, PostMessage, I've tried both) looks like the
      way to go, but I've had no luck so far. I whipped up some test code using
      the calculator (mostly plagiarized from one of those old posts) and all the
      function returns act like they're working, but nothing seems to happen (I'm
      not even dealing with the "no focus" thing right now, I'm just trying to get
      the message sent and received):

      ###################################
      use strict;
      use Win32::GuiTest qw(FindWindowLike SendMessage SetForegroundWindow ) ;

      use constant WM_KEYDOWN => 0x0100;
      use constant WM_KEYUP => 0x0101;
      use constant WM_CHAR => 0x0102;
      use constant KEY_4 => 0x34;

      my ($hwnd) = FindWindowLike(0, "Calculator");
      print "hwnd = $hwnd\n";
      SetForegroundWindow($hwnd);
      sleep 1;

      my $test = SendMessage( $hwnd, WM_KEYDOWN, KEY_4, 0x00050001 );
      print "test = $test\n";
      my $test2 = SendMessage( $hwnd, WM_CHAR, KEY_4, 0x40050001 );
      print "test2 = $test2\n";
      my $test3 = SendMessage( $hwnd, WM_KEYUP, KEY_4, 0xC0050001 );
      print "test3 = $test3\n";
      ###################################

      If anyone has some ideas that even get me moving in the right direction, it
      would be most appreciated.
    • Piotr Kaluski
      Ok. I think I know the answer to your question. I am not sure that I am right but my experiments and Petzold seem to confirm it. I will give you an elaborate
      Message 2 of 2 , Feb 7, 2006
        Ok.
        I think I know the answer to your question. I am not sure that I am
        right but my experiments and Petzold seem to confirm it. I will give
        you an elaborate answer, to show you how did I figure it out.

        Firstly, of course, I tried your script on my PC. And yes, it did not
        work.

        Then I run Winspector and set message filtering to show only
        WM_KEYDOWN, WM_CHAR and WM_KEYUP. I checked that messages really
        arrive to calculator window. But there was not effect on calculator's
        display.
        Then I checked what messages are send to calculator when I actually
        press '4'. It has occurred that calculator receives 2 messages -
        WM_KEYDOWN and WM_CHAR. No WM_KEYUP.
        I also checked what is the messages' lParam. I have also noticed those
        messages are posted, not sent (PostMessage).
        So I tried PostMessage:

        my $test = PostMessage( $hwnd, WM_KEYDOWN, KEY_4, 0x00050001 );
        print "test = $test\n";
        my $test2 = PostMessage( $hwnd, WM_CHAR, KEY_4, 0x00050001 );

        The result was better, but still not exactly as expected. Calculator
        reacted, but twice.
        Instead of displaying one "4" character it displayed "44". Winspector
        clearly showed that calculator is getting WM_CHAR twice.
        So I started reading Petzold. And I found in chapter 6 "The Keyboard",
        section "Character Messages". It says something like:

        "
        (...)
        while (GetMessage (&msg, NULL, 0, 0))
        {
        TranslateMessage (&msg) ;
        DispatchMessage (&msg) ;
        }

        This is a typical message loop that appears in WinMain. The GetMessage
        function fills in the msg structure fields with the next message from
        the queue. DispatchMessage calls the appropriate window procedure with
        this message.

        Between these two functions is TranslateMessage, which takes on the
        responsibility of translating keystroke messages to character
        messages. If the keystroke message is WM_KEYDOWN or WM_SYSKEYDOWN, and
        if the keystroke in combination with the shift state produces a
        character, TranslateMessage places a character message in the message
        queue. This character message will be the next message that GetMessage
        retrieves from the queue after the keystroke message.
        "
        END OF QUOTE

        So it is enough to post only one WM_KEYDOWN. Calculator will translate
        it to WM_CHAR and will post it to itself.

        Why there is no WM_KEYUP? I am under impression that after getting
        first WM_KEYDOWN, calculator moves focus to an edit box. Edit box seem
        to catch all further keyboard events. Pressing "4" many times causes
        calcultor's main window to receive only one WM_CHAR messages. The
        remaining ones are send to Edit box.

        --Piotr


        --- In perlguitest@yahoogroups.com, Dave Miller <dave@...> wrote:
        >
        > Looking through the archives, I found one thread about this, but it
        died out
        > before a solution came up, so I'm going to try fresh.
        >
        > I'm trying to send keystrokes to a window that I can't be certain
        has focus.
        > SendMessage (or, optionally, PostMessage, I've tried both) looks
        like the
        > way to go, but I've had no luck so far. I whipped up some test code
        using
        > the calculator (mostly plagiarized from one of those old posts) and
        all the
        > function returns act like they're working, but nothing seems to
        happen (I'm
        > not even dealing with the "no focus" thing right now, I'm just
        trying to get
        > the message sent and received):
        >
        > ###################################
        > use strict;
        > use Win32::GuiTest qw(FindWindowLike SendMessage SetForegroundWindow ) ;
        >
        > use constant WM_KEYDOWN => 0x0100;
        > use constant WM_KEYUP => 0x0101;
        > use constant WM_CHAR => 0x0102;
        > use constant KEY_4 => 0x34;
        >
        > my ($hwnd) = FindWindowLike(0, "Calculator");
        > print "hwnd = $hwnd\n";
        > SetForegroundWindow($hwnd);
        > sleep 1;
        >
        > my $test = SendMessage( $hwnd, WM_KEYDOWN, KEY_4, 0x00050001 );
        > print "test = $test\n";
        > my $test2 = SendMessage( $hwnd, WM_CHAR, KEY_4, 0x40050001 );
        > print "test2 = $test2\n";
        > my $test3 = SendMessage( $hwnd, WM_KEYUP, KEY_4, 0xC0050001 );
        > print "test3 = $test3\n";
        > ###################################
        >
        > If anyone has some ideas that even get me moving in the right
        direction, it
        > would be most appreciated.
        >
      Your message has been successfully submitted and would be delivered to recipients shortly.