1

I use PostMessage to simulate keystrokes in a program that is in the background. It work fine except for characters that need shift on the physical keyboard. How do I simulate shift? "

The code I use is roughly:

 VK vk = VkKeyScanEx (c, GetKeyboardLayout (0));

 AttachThreadInput (_attachedThredId, _attachedProcessId, true);
 PostMessage       (_window, WM_KEYDOWN, vk.key, 0x1);
 PostMessage       (_window, WM_KEYUP,   vk.key, 0xC0010001);
 AttachThreadInput (_attachedThredId, _attachedProcessId, false);

How should I handle Extended part of VK?

Edit

I'm trying to create an on-screen keyboard. Each button on the on-screen keyboard simulates a sequence of keystrokes. The receiver is an old program that performs different tasks depending on the keyboard sequence that is performed. Keyboard sequences is as follows

  • {ESC}NN{ESC}NN
  • {ESC}NN
  • ½NN
  • §NN

where {ESC} simulate pressing the Esc key, NN are hex values and §/½ get the program to listen.

Normally we have special physical keyboard to control the program, but they are expensive. So in a test environment where we do not always have the physical keyboards, we have to enter these codes manually

magol
  • 6,135
  • 17
  • 65
  • 120

3 Answers3

5

You must compromise:

If you want to simulate keyboard input, then you must use SendInput, which means being at the mercy of which window currently has focus. SendInput is like hitting the keys on your physical keyboard. The only way you can send your keystrokes to a specific window using your keyboard is to ALT+TAB to the right window.

If you want to send keystrokes to a specific window, then you incur funky behavior:

  1. Applications handle input differently. And simple WM_KEYDOWN / WM_KEYUP messages are not the only way to detect keyboard input. For example there is also the keyboard state (GetKeyboardState()) which you will have a harder time simulating. This is most likely what you're experiencing.
  2. Applications may RELY on the standard behavior of having focus while receiving keyboard input messages. By posting messages to these applications, you invoke strange out-of-order behavior that may crash them.
  3. Now multiple windows on the system can be receiving keyboard input at the same time. This might also cause strange behavior.
  4. (etc...) Hooks won't be called for this input, your keyboard / input drivers won't see it, it won't be recognized by things like DirectInput... basically it's a never-ending patchwork of issues by doing something the bad-bear way.

There is no way around those side-effects; it's the consequence of doing shady stuff.


A solution for your purposes, because you're targeting a single specific application, may be to use PostMessage in conjunction with SetKeyboardState to simulate the keyboard state including shift positions.

tenfour
  • 36,141
  • 15
  • 83
  • 142
2

Okay, I think you're in for a mess here, PostMessage() is notorious for not working well with shift states, and hooks won't get called either. Microsoft recommends SendInput() instead, and so do I. I suggest that you either post a new question, or update this one, where you detail what you are trying to achieve, and maybe we can better recommend a different solution.

As for the extended part, it has nothing to do with this at all, and won't help you.

What you could try, is sending a WM_KEYDOWN message that says the shift key was pressed, and then send another message with your desired key, before sending a WM_KEYUP shift message. I doubt this will work, but you can always try.

  • I have now described a bit more what I try to do. Hope you can help me – magol Feb 10 '11 at 10:58
  • 2
    You still need to use `SendInput`. We already understood what you were trying to do. You didn't need to modify the question, you needed to read the answers! – David Heffernan Feb 10 '11 at 12:33
  • @magol: You could try to activate the window that you want to send input to, set your own window to the foreground as nonactivated using `ShowWindow(SW_NOACTIVATE)`, and then simulate the input with `SendInput()`. When the user presses a new key on your onscreen keyboard, your application should get the focus again, and the process repeats. This should work, AFAIK, but I've never tried it... –  Feb 10 '11 at 13:14
  • I did test ShowWindow(SW_NOACTIVATE), but my window did not get to the front. – magol Feb 10 '11 at 16:51
  • @magol: You might be better of starting a new question "How do I set my window to the foreground without activating it" and post some code with it. There are many things that *could* work. One of them being to temporarily set your window to "topmost", and then immediately undo that. –  Feb 10 '11 at 18:25
  • @Øystein - I gave up SW_NOACTIVATE and has now tried to make my program topmost and then undo it. And that function satisfactorily. Thanks for any help – magol Feb 10 '11 at 19:20
1

Personally i would use SendKey.Send( ) for this purpose.

MSDN page

Simon Smeets
  • 581
  • 6
  • 17
  • 1
    From MSDN: Sends keystrokes to the _active application_. The application that I send the keystrokes to is NOT active, so I can't use it :-( – magol Feb 09 '11 at 12:14
  • 2
    +1, you can't make it work with PostMessage(). Period. Make the window active. – Hans Passant Feb 09 '11 at 13:44
  • I have now described a bit more what I try to do. Hope you can help me – magol Feb 10 '11 at 10:59