32

    我已经制作了一个向激活的窗口发送命令的应用程序。我希望能够在我的进程运行时使用计算机,因为一旦我将焦点切换到另一个窗口,通过发送键发送的击键将转到我刚刚切换到的窗口。

    目前我使用 Windows API 中的 FindWindow、IsIconic 和 ShowWindow。我必须使用 FindWindow 检查窗口是否存在并将我的对象设置为该调用返回的特定窗口,然后检查它是否已使用 IsIconic 最小化并调用 ShowWindow 如果是,最后我必须调用Interaction.AppActivate 将焦点设置到该窗口。所有这些都是在我发送击键之前完成的。似乎应该有一种方法可以只发送击键而不必显示窗口并激活它。最重要的是,当我的应用程序正在运行击键时,我无法在我的计算机上执行任何操作。

4

4 回答 4

34

好吧,我敢肯定,这有点令人失望,但你基本上不能以 100% 的可靠性做到这一点。

Windows 假定活动窗口是获得键盘输入的窗口。伪造键盘输入的正确方法是使用SendInput,您会注意到它仅将消息发送到活动窗口。

话虽如此,您可以SendMessage WM_KEYUPWM_CHARWM_KEYDOWN消息,并且(取决于接收它们的 WndProc)可能会侥幸逃脱。但请记住,在某些情况下,它会中断。

于 2009-08-05T00:44:43.750 回答
8

听起来您正在使用 keybd_event() 或 SendInput(),它们都将击键发送到当前活动窗口。要将击键定向到特定窗口,无论该窗口是否聚焦,您都需要先找到它的 HWND 句柄,然后将适当格式的 WM_KEYUP/DOWN 和 WM_CHAR 消息直接发送到它。

于 2009-08-05T00:41:51.457 回答
4

一旦你有了windows HWND,你可以直接SendMessage() WM_KEYDOWN 和WM_KEYUP 消息到它的消息队列。该窗口不必处于活动状态。

但是,请了解这取决于目标应用程序如何处理键盘输入。有几种不同的方法来处理它。

WM_KEYUP/WM_KEYDOWN 是最常见的,一些应用程序只处理一个或另一个(通常是 WM_KEYDOWN)。

WM_CHAR 也相当普遍

某些程序使用 GetAsyncKeyState、GetKeyState 或 GetKeyboardState。这是非常不寻常的,但有效地防止了使用 SendMessage() 的按键注入。如果是这种情况,请回退到由键盘驱动程序直接处理的 keybd_event()。当然窗口必须是活动的

于 2016-10-06T16:34:51.783 回答
0
#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);
}

此代码有效,在这种情况下您不需要激活记事本。这是使用 C++

于 2021-05-29T20:29:07.147 回答