正如标题所述:是否有一种方法可以使用JNA将模拟按键发送到非活动窗口(因为Java是我最强的语言)?当然,当有另一种语言可以实现此目标时,我会这么做。
除了JNA之外,我还在网上阅读了很多东西,但没有实现这个目标。
现在,我能够使用JNA的sendInput()模拟击键,但是那不是想要的,因为它会影响活动窗口。 您可以在这里阅读有关内容:https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendinput
我的理解是,您可以为该主题使用sendMessage(),但我无法使其正常运行。 https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessage
LRESULT SendMessage( HWND hWnd, UINT讯息, WPARAM wParam, LPARAM lParam );
还有SendMessageA和SendMessageW。有人说SendMessage对于某些操作系统来说太旧了,但我无法验证。
让我们以记事本为例。 窗口标题为“ new 2-Notepad ++”
快捷键:https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown
关键字:https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keyup
import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.win32.W32APIOptions;
public interface User32 extends StdCallLibrary {
User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);
LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
}
public void winAPI() throws InterruptedException {
HWND handler = User32.INSTANCE.FindWindow(null, "new 2 - Notepad++");
// 0x0100 WM_KEYDOWN
User32.INSTANCE.SendMessage(handler, 0x0100, new WinDef.WPARAM(0x31), new WinDef.LPARAM(0)}
// recommended for dedection
Thread.sleep(200);
// 0x0101 WM_KEYUP
User32.INSTANCE.SendMessage(handler, 0x0101, new WinDef.WPARAM(0x31), new WinDef.LPARAM(0)}
}
我对SendMessage(A?)(W?)()的正确实现感到困惑,因为它不是在JNA中实现的。
您还如何创建WPARAM和LPARAM? MSDN说有特定的消息。 因此,当将WM_KEYDOWN或WM_KEYUP作为消息参数传递时:
WPARAM是虚拟的KeyCode:仅仅是一个整数?
LPARAM是字节数组(?)。
我猜这是由于WPARAM和LPARAM的参数数据类型错误而导致的。
答案 0 :(得分:1)
我对JNA不熟悉,但是将从winapi方面提供以下信息。希望这可以帮助您找到解决方案。
还有SendMessageA和SendMessageW。有人说SendMessage是 对于某些操作系统来说太老了,但我无法验证。
SendMessageA和SendMessageW代表SendMessage函数的Ascii和Unicode版本。它们具有相同的功能。请参阅“ Unicode in the Windows API”。
我为SendMessage(A?)(W?)()的正确实现而苦恼 因为它没有在JNA中实现。
因此,请随时在JNA中使用SendMessage。
对于不活动的窗口,由于您没有焦点,因此无法从系统收到诸如WM_KEYUP之类的按键消息。但是您可以模拟系统以将这种消息发送到非活动窗口。您可以参考以下代码。 (Initial thread)
#include <windows.h>
#include <iostream>
#include <string>
int main()
{
LPCWSTR Target_window_Name = TEXT("Untitled - Notepad"); //<- Has to match window name
HWND hWindowHandle = FindWindow(NULL, Target_window_Name);
HWND EditClass = FindWindowEx(hWindowHandle, NULL, L"Edit", NULL);
SendMessage(EditClass, WM_KEYDOWN, 0x5A, 0x002C0001);
SendMessage(EditClass, WM_CHAR, 0x7A, 0x002C0001); //"z"
SendMessage(EditClass, WM_KEYUP, 0x5A, 0xC02C0001);
return(0);
}
您还如何创建WPARAM和LPARAM? MSDN说有消息 具体的。
您需要根据其他消息创建WPARAM和LPARAM。例如对于WM_KEYDOWN消息,wParam是非系统密钥的虚拟密钥代码。参见Virtual-Key Codes。在上面的示例代码中,Z键的虚拟键代码为0x5A。所以wParam是0x5A。与WM_KEYUP消息相同。在WM_CHAR消息中,wParam是密钥的字符代码。您可以在Ascii表中找到小写的“ z”为0x7A。您还需要提供这些消息的扫描代码。您可以搜索“键盘扫描代码规范-Microsoft”。 “ Z”的扫描代码为0x2C。 WM_KEYUP消息的lParam的最后30位和31位始终为1。因此它从0xC0开始。
更多参考文献:“ WM_KEYDOWN message”“ WM_KEYUP message”“ WM_CHAR message”