Как вы отправляете нажатия клавиш в неактивное окно? - PullRequest
0 голосов
/ 16 января 2019

как следует из заголовка: есть ли способ отправить смоделированные нажатия клавиш в неактивное окно с помощью JNA (потому что Java - мой самый сильный язык)? Конечно, когда есть альтернативный язык, который может достичь этой цели, я бы пошел на это.

Я много читаю в Интернете, кроме JNA, но безуспешно для этой цели.

Прямо сейчас я могу имитировать нажатия клавиш с помощью sendInput () с JNA, но это не то, что нужно, потому что это влияет на активное окно. Вы можете прочитать об этом здесь: 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 Msg, WPARAM wParam, LPARAM lParam );

Есть также SendMessageA и SendMessageW. Некоторые говорят, что SendMessage слишком стар для некоторых ОС, но я не могу это проверить.

Давайте возьмем Блокнот в качестве примера. Название окна «новый 2 - Блокнот ++»

Keydown: https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-keydown

Keyup: 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 - это виртуальный ключевой код: просто int?

LPARAM - это байтовый массив (?).

Полагаю, это не работает из-за неправильных типов данных параметров WPARAM и LPARAM.

1 Ответ

0 голосов
/ 17 января 2019

Я не знаком с JNA, но приведу следующую информацию с точки зрения winapi. Надеюсь, это поможет вам найти решение.

Есть также SendMessageA и SendMessageW. Некоторые говорят, что SendMessage слишком стар для какой-то ос, но я не смог это проверить.

SendMessageA и SendMessageW представляют версию функции SendMessage для Ascii и Unicode. Они имеют одинаковые возможности. См. « Юникод в Windows API ».

Я борюсь с правильной реализацией SendMessage (A?) (W?) () поскольку он не реализован в JNA.

Так что не стесняйтесь использовать SendMessage в JNA.

Для неактивного окна вы не можете получить сообщение о нажатии клавиши, например WM_KEYUP, из системы, потому что у вас нет фокуса. Но вы можете смоделировать систему для отправки такого рода сообщения в неактивное окно. Вы можете обратиться к следующему коду. ( Начальная тема )

#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 - это код виртуального ключа несистемного ключа. См. Коды виртуальных клавиш . В приведенном выше примере кода код виртуальной клавиши Z-ключа равен 0x5A. Таким образом, wParam 0x5A. То же самое с сообщением WM_KEYUP. В сообщении WM_CHAR wParam - это код символа ключа. Вы можете найти в таблице Ascii, строчная буква «z» 0x7A. Вам также необходимо предоставить код сканирования для этих сообщений. Вы можете искать "Спецификация кода сканирования клавиатуры - Microsoft". Код сканирования "Z" - 0x2C. Последний бит 30 и 31 lParam сообщения WM_KEYUP всегда равен 1. Таким образом, он начинается с 0xC0.

Дополнительные ссылки: " Сообщение WM_KEYDOWN " " Сообщение WM_KEYUP " " Сообщение WM_CHAR "

...