问题
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.
来源:https://stackoverflow.com/questions/54313354/simulate-keystrokes-in-inactive-windows