0

I'm simulating a pressed Ctrl button by:

[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);

keybd_event(VK_CONTROL, 0, 0, 0); //key down
/* Stuff which needs ctrl to be pressed is done here */
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); //key up

This code is located in a .dll file. The dll is used in an WPF application. Now i have the strange behaviour, that the pressed Ctrl key is recognized only if the WPF window is NOT active. Meaning when I click on another window to deactivate the WPF window and force to run the code without activating the WPF window again it works. After clicking on the WPF window it doesn't work anymore.

Any ideas whats the problem here?

Edit: I moved the code from the dll to the wpf application which did not change anything. In the WPF app I tested:

keybd_event(VK_CONTROL, 0, 0, 0);
child.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
udondan
  • 57,263
  • 20
  • 190
  • 175
andineupert
  • 341
  • 2
  • 6
  • 19
  • Why are you using a dll import for this? – ThaMe90 Jan 30 '14 at 12:10
  • Because I'm using it anyways for some other stuff. But I tried different solutions to raise the key down/up events also. All solutions led to the same behaviour. – andineupert Jan 30 '14 at 12:19
  • `keybd_event` is asynchronous. Use `SetKeyboardState`. set all the 256 bytes to 0, except the one at indice VL_CONTROL (set to -128, or 0x80). Use again with all to 0 after the synchronous RaiseEvent – manuell Jan 30 '14 at 13:17
  • I'm guessing that you've seen the [C# Simulate Key Press](http://stackoverflow.com/questions/7307868/c-sharp-simulate-key-press) post... have you? If that doesn't help, please take a look at the [Windows Input Simulator (C# SendInput Wrapper - Simulate Keyboard and Mouse)](http://inputsimulator.codeplex.com/) project on CodePlex. My final offering is the [How to: Simulate Mouse and Keyboard Events in Code](http://msdn.microsoft.com/en-us/library/vstudio/ms171548(v=vs.100).aspx) page from MSDN, which uses the `SendKeys` class to do what you want. – Sheridan Jan 30 '14 at 13:57
  • manuell makes a good point about `keybd_event` being asynchronous -- and you follow it with a call to `RaiseEvent`, which I believe is synchronous. So you're calling your event before your app has had a chance to process the "CTRL was pressed" message. Try wrapping the `RaiseEvent` call inside a `Dispatcher.BeginInvoke` (i.e., register a callback to run after the "CTRL was pressed" message has been processed) and see if that fixes your problem. – Joe White Jan 30 '14 at 13:58
  • Thanks! The asynchronous/synchronous problem is the right point. Succesfully using SetKeyboardState now. Thank you! – andineupert Jan 30 '14 at 14:10
  • The answer to practically every question asking to *simulate input* is: Use the documented interface. It goes by the name [UI Automation](http://msdn.microsoft.com/en-us/library/ms747327.aspx). – IInspectable Jan 30 '14 at 16:41

1 Answers1

0

manuell mentioned a solution and explained the problem in the third comment on my question:

keybd_event is asynchronous. Use SetKeyboardState. set all the 256 bytes to 0, except the one at indice VL_CONTROL (set to -128, or 0x80). Use again with all to 0 after the synchronous RaiseEvent – manuell

Joe Whites explains a bit further and proposes a potentially good solution also:

manuell makes a good point about keybd_event being asynchronous -- and you follow it with a call to RaiseEvent, which I believe is synchronous. So you're calling your event before your app has had a chance to process the "CTRL was pressed" message. Try wrapping the RaiseEvent call inside a Dispatcher.BeginInvoke (i.e., register a callback to run after the "CTRL was pressed" message has been processed) and see if that fixes your problem. – Joe White

Thanks!

Community
  • 1
  • 1
andineupert
  • 341
  • 2
  • 6
  • 19