Как вы отправляете нажатия клавиш в неактивное окно?
Как описывает заголовок: есть ли способ отправить смоделированные нажатия клавиш в неактивное окно с помощью 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 ответ
Я не знаком с 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".