简体   繁体   English

如何将击键发送到非活动窗口?

[英]How do you send keystrokes to an inactive window?

as the title describes: Is there a way to send simulated keystrokes to an inactive window by using JNA ( ,because Java is my strongest language)? 如标题所述:是否有一种方法可以通过使用JNA将模拟击键发送到非活动窗口(因为Java是我最强的语言)? Of course when there is an alternative language, which can achieve this goal, I'd go for that. 当然,当有另一种语言可以实现此目标时,我会这么做。

I read lots of stuff on the web, also besides JNA but with no succes for this goal. 除了JNA之外,我还在网络上阅读了很多东西,但没有达到这个目标。

Right now I am able to simulate keystrokes with sendInput() with JNA but thats not what want, because it effects the active window. 现在,我可以使用JNA的sendInput()模拟击键,但这不是想要的,因为它会影响活动窗口。 You can read about that here: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendinput 您可以在此处阅读有关内容: https : //docs.microsoft.com/zh-cn/windows/desktop/api/winuser/nf-winuser-sendinput

My understanding is that you can use sendMessage() for that topic, but I cant get it working. 我的理解是您可以为该主题使用sendMessage(),但我无法使其正常工作。 https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessage https://docs.microsoft.com/zh-CN/windows/desktop/api/winuser/nf-winuser-sendmessage

LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);

There are also SendMessageA and SendMessageW. 也有SendMessageA和SendMessageW。 Some say SendMessage is too old for some os, but I could not verify that. 有人说SendMessage对于某些操作系统来说太旧了,但是我无法验证这一点。

Lets take Notepad as an example. 让我们以记事本为例。 The window title is 'new 2 - Notepad++' 窗口标题为“新2-记事本++”

Keydown: https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown 键盘输入: https ://docs.microsoft.com/zh-cn/windows/desktop/inputdev/wm-keydown

Keyup: https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keyup 键盘: https ://docs.microsoft.com/zh-cn/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)}
}

I struggle with the right implementation of SendMessage(A?)(W?)() since its not implemented in JNA. 我对SendMessage(A?)(W?)()的正确实现感到困惑,因为它没有在JNA中实现。

Also how do you create WPARAM and LPARAM? 另外,如何创建WPARAM和LPARAM? MSDN says there are message specific. MSDN说有特定的消息。 So when pass WM_KEYDOWN or WM_KEYUP as message parameter: 因此,当传递WM_KEYDOWN或WM_KEYUP作为消息参数时:

WPARAM is the virual KeyCode: just an int? WPARAM是虚拟的KeyCode:仅仅是一个整数?

LPARAM is a bytearray(?). LPARAM是一个字节数组(?)。

I guess it doesnt work because of wrong parameter datatypes of WPARAM and LPARAM. 我想这是行不通的,因为WPARAM和LPARAM的参数数据类型错误。

I am not familiar with JNA but I'll give the following information from winapi aspect. 我不熟悉JNA,但将从winapi方面提供以下信息。 Hope this helps you find the solution. 希望这可以帮助您找到解决方案。

There are also SendMessageA and SendMessageW. 也有SendMessageA和SendMessageW。 Some say SendMessage is too old for some os, but I could not verify that. 有人说SendMessage对于某些操作系统来说太旧了,但是我无法验证这一点。

The SendMessageA and SendMessageW represent Ascii and Unicode version of SendMessage function. SendMessageA和SendMessageW代表SendMessage函数的Ascii和Unicode版本。 They have the same capability. 它们具有相同的功能。 Refer to " Unicode in the Windows API ". 请参阅“ Windows API中的Unicode ”。

I struggle with the right implementation of SendMessage(A?)(W?)() since its not implemented in JNA. 我对SendMessage(A?)(W?)()的正确实现感到困惑,因为它没有在JNA中实现。

So feel free use SendMessage in JNA. 因此,可以在JNA中随意使用SendMessage。

For the inactive window, you can't receive a keystroke message like WM_KEYUP from the system because you have no focus. 对于不活动的窗口,由于您没有焦点,因此无法从系统收到诸如WM_KEYUP之类的按键消息。 But you can simulate the system to send this kind of message to the inactive window. 但是您可以模拟系统以将这种消息发送到非活动窗口。 You can refer to the following code. 您可以参考以下代码。 ( 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);
}

Also how do you create WPARAM and LPARAM? 另外,如何创建WPARAM和LPARAM? MSDN says there are message specific. MSDN说有特定的消息。

You need create WPARAM and LPARAM based on a different message. 您需要根据其他消息创建WPARAM和LPARAM。 For example, WM_KEYDOWN message, wParam is the virtual-key code of the nonsystem key. 例如对于WM_KEYDOWN消息,wParam是非系统密钥的虚拟密钥代码。 See Virtual-Key Codes . 请参阅虚拟键码 In sample code above, the virtual-key code of Z key is 0x5A. 在上面的示例代码中,Z键的虚拟键代码为0x5A。 So wParam is 0x5A. 所以wParam是0x5A。 Same with WM_KEYUP message. 与WM_KEYUP消息相同。 In WM_CHAR message, wParam is the character code of the key. 在WM_CHAR消息中,wParam是密钥的字符代码。 You can find in the Ascii table, the lowercase "z" is 0x7A. 您可以在Ascii表中找到小写的“ z”为0x7A。 You also need to provide the scan code for these messages. 您还需要提供这些消息的扫描代码。 You can search "Keyboard Scan Code Specification - Microsoft". 您可以搜索“键盘扫描代码规范-Microsoft”。 The scan code of "Z" is 0x2C. “ Z”的扫描代码为0x2C。 The last, bit 30 and 31 of lParam of WM_KEYUP message are always 1. So it starts as 0xC0. WM_KEYUP消息的lParam的最后一个比特30和31始终为1。因此它从0xC0开始。

More references: " WM_KEYDOWN message " " WM_KEYUP message " " WM_CHAR message " 更多参考:“ WM_KEYDOWN消息 ”“ WM_KEYUP消息 ”“ WM_CHAR消息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM