0

I'd like to simulate 'real' keystrokes in an inactive window. After some research I found the Windows api. Since Im used to Java, I quickly found JNA, which implements the winapi. I wrote some code, that could simulate keystrokes in a active window with the sendInput() method. The window did not detect virtual keycodes. After some search, windows with directinput need scancodes apparently. And it worked with the following code:

import com.sun.jna.platform.win32.BaseTSD;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;

int KEYEVENT_SCANCODE = 0x0008;
int KEYEVENT_UP = 0x0002;
WinUser.INPUT input = new WinUser.INPUT();

input.type = new WinDef.DWORD(WinUser.INPUT.INPUT_KEYBOARD);
input.input.setType("ki");
input.input.ki.wVk = new WinDef.WORD(0);// 0 cause scancodes are used
input.input.ki.time = new WinDef.DWORD(0);
input.input.ki.dwExtraInfo = new BaseTSD.ULONG_PTR(0);

input.input.ki.wScan = new WinDef.WORD(0x2C); // scancode for 'y'
input.input.ki.dwFlags = new WinDef.DWORD(KEYEVENT_SCANCODE); // keydown

User32.INSTANCE.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size());

input.input.ki.wScan = new WinDef.WORD(0x2C);
input.input.ki.dwFlags = new WinDef.DWORD(KEYEVENT_SCANCODE | KEYEVENT_UP); // keyup

User32.INSTANCE.SendInput(new WinDef.DWORD(1), (WinUser.INPUT[]) input.toArray(1), input.size());

Now I wanted it to be 'smooth', so that the window could be in the background or minimized. I found the SendMessage() and PostMessage() methods and thought I understood its concepts. You pass the handler of a window, the message(wm_keydown and wm_keyup seems good for the task) and and its specific params.

I tried this, but it did not work. (same for postMessage).

User32.INSTANCE.SendMessage(handler, WinUser.WM_KEYDOWN, new   WinDef.WPARAM(0x5A), new WinDef.LPARAM(0x002C0001));
Thread.sleep(100); //tried with and without
User32.INSTANCE.SendMessage(handler, WinUser.WM_KEYUP, new WinDef.WPARAM(0x5A), new WinDef.LPARAM(0xC02C0001)); 

Then I tried WM_CHAR and it worked partially. It worked in the chat of the window, but did not trigger hotkeys. After some research, people say, you have to use directinput hooks(?), since some windows won't recognize messages from the winapi, but mine did apparently from sendInput and sendMessage with WM_CHAR.

Have I passed wrong params? What does it mean, that wm_char is regocnized, but wm_keydown and wm_keyup is not?

I already found lots of examples, stuff on stakeoverflow and the web, but it did not really help. Thanks for reading and answering.

@update I used a tool for detecting messages. The Messages created by real keystrokes and the ones created from the code are equal:

In both cases there is a WM_keydown, then WM_char and WM_keyup. Every param of every message is equal. In addition to that, like I said, if the chat is opened, there are characters written, but actions won't perform, when the chat is closed. I checked, what messages are send with the sendInput() method: they are equal to the both cases above, but action is performed. I'm not able to inprete this behavior.

bob
  • 1
  • 2
  • You usually can't send input to an inactive window as it doesn't want input. And [you can’t simulate keyboard input with (Post|Send)Message](https://blogs.msdn.microsoft.com/oldnewthing/20050530-11/?p=35513). The real question is, what are you trying to accomplish in the first place? There may be better alternatives. Such as UI Automation, etc – Remy Lebeau Jan 22 '19 at 18:08
  • I try to simulate keystrokes in a window, that has not the the focus of the keyboard. The window uses directinput. It detects the keystrokes send with sendInput, but sendInput effects the active window. As far as I understand, sendInput with scancodes will be recognize from directinput. – bob Jan 22 '19 at 18:49
  • AFAIK, DirectInput doesn't use the message queue to get keyboard input, it gets it right from the hardware. So posting messages to windows won't work anyway. You have to use `SendInput()` to simulate keyboard hardware events, it is the only option for that. There is simply no *official, standard* way to send keyboard input to a hidden/inactive window. – Remy Lebeau Jan 22 '19 at 19:25
  • If I use PostMessage with keydown+up or SendMessage with keydown+char+keyup, there are characters written in the chat of the inactive window, but ONLY in there. If the chat is not triggered, nothing happens. That's really confusing. – bob Jan 22 '19 at 20:18
  • 1
    Have you read Remy's comments? Do you want advice or not? – David Heffernan Jan 22 '19 at 21:31
  • Inactive windows do not have the keyboard focus and therefore, cannot receive input. Whatever method you may find today working on what you are trying to achieve (which is not clear), may break tomorrow with the next update. – Michael Chourdakis Jan 23 '19 at 04:31
  • @bob "If the chat is not triggered, nothing happens." Do you mean you can't receive either WM_KEYDOWN or WM_KEYUP when using this code `User32.INSTANCE.SendMessage(handler, WinUser.WM_KEYDOWN, new WinDef.WPARAM(0x5A), new WinDef.LPARAM(0x002C0001)); User32.INSTANCE.SendMessage(handler, WinUser.WM_KEYUP, new WinDef.WPARAM(0x5A), new WinDef.LPARAM(0xC02C0001));` except you send "WM_CHAR" additionally? – Rita Han Jan 23 '19 at 07:28
  • @RitaHan-MSFT Yes thats correct. If the chat is triggert, keystrokes are recognized send with SendMessage wm_keydown, then wm_char, then wm_keyup or with PostMessage wm_keydown, then wm_keyup, since PostMessage translates wm_keydown to wm_char. If the chat is not triggert, keystrokes are not recognized, because nothing happens, but it does, if i press the key by myself. Thats really confusing for me. – bob Jan 23 '19 at 08:51
  • 1
    @DavidHeffernan i have read every comment – bob Jan 23 '19 at 08:51
  • @bob But I can't reproduce this issue with two win32 console apps on my Windows 10 desktop. One is sending the keystroke and the other can receive both WM_KEYDOWN and WM_KEYUP without WM_CHAR. – Rita Han Jan 23 '19 at 09:02
  • Possible duplicate of [How do I send key strokes to a window without having to activate it using Windows API?](https://stackoverflow.com/questions/1220820/how-do-i-send-key-strokes-to-a-window-without-having-to-activate-it-using-window) – technomage Feb 01 '19 at 16:19

0 Answers0