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

Re: Sending keystrokes with SendMessage

Expand Messages
  • 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 1 of 2 , Feb 7, 2006
    • 0 Attachment
      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.