Как отправить нажатия клавиш в окно, не активируя его с помощью Windows API?

Я уже сделал приложение, которое отправляет команды в активированное окно. Я хочу использовать компьютер во время работы моего процесса, потому что как только я переключаю фокус на другое окно, нажатия клавиш, отправляемые с помощью клавиш отправки, переходят в окно, на которое я только что переключился.

В настоящее время я использую FindWindow, IsIconic и ShowWindow из Windows API. Я должен проверить, есть ли окно с FindWindow и установить мой объект в конкретное окно, которое возвращается с этим вызовом, затем я проверяю, свернуто ли оно с помощью IsIconic, и вызвать ShowWindow, если оно есть, и, наконец, мне нужно вызвать Interaction.AppActivate, чтобы установить фокус на это окно. Все это делается еще до того, как я отправляю нажатия клавиш. Похоже, должен быть способ отправлять нажатия клавиш без необходимости показывать окно и активировать его. Самое главное, что пока мое приложение выполняет нажатия клавиш, я ничего не могу сделать на своем компьютере.

4 ответа

Решение

Хорошо, это несколько разочаровывает, я уверен, но вы принципиально не можете сделать это со 100% надежностью.

Windows предполагает, что активное окно является тем, которое получает ввод с клавиатуры. Правильный способ подделки ввода с клавиатуры - с SendInput, и вы заметите, что он отправляет сообщения только в активное окно.

При этом вы можете отправлять сообщения SendMessage WM_KEYUP, WM_CHAR и WM_KEYDOWN и (в зависимости от того, как их получает WndProc) могут сойти с рук. Но помните, что он сломается при некоторых обстоятельствах, точка.

Похоже, вы используете keybd_event() или SendInput(), которые оба посылают нажатия клавиш в текущее активное окно. Чтобы направить нажатия клавиш в конкретное окно, независимо от того, нацелена ли эта вдова или нет, сначала нужно найти ее дескриптор HWND, а затем публиковать в нее сообщения надлежащим образом отформатированного WM_KEYUP/DOWN и WM_CHAR.

Как только у вас есть окна HWND, вы можете напрямую отправить Message() сообщения WM_KEYDOWN и WM_KEYUP в его очередь сообщений. Окно не обязательно должно быть активным.

Однако следует понимать, что это зависит от того, как целевое приложение обрабатывает ввод с клавиатуры. Есть несколько разных способов справиться с этим.

WM_KEYUP / WM_KEYDOWN является наиболее распространенным, и некоторые приложения обрабатывают только одно или другое (обычно WM_KEYDOWN).

WM_CHAR также довольно часто

Некоторые программы используют GetAsyncKeyState, GetKeyState или GetKeyboardState. Это чрезвычайно необычно, но эффективно предотвращает инъекцию клавиш с помощью SendMessage(). Если это так, вернитесь к keybd_event(), который напрямую обрабатывается драйвером клавиатуры. Конечно, окно должно быть активным

      #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);
}

Этот код работает, в этом случае вам не нужно иметь активный блокнот. Это использует С ++

Другие вопросы по тегам