如何使用Windows API将键击发送到窗口而不必激活它?

时间:2009-08-03 05:56:52

标签: winapi sendmessage sendkeys keystroke

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

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

4 个答案:

答案 0 :(得分:29)

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

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

话虽这么说,你可以SendMessage WM_KEYUPWM_CHARWM_KEYDOWN消息和(取决于接收它们的WndProc)可能会侥幸逃脱。但请记住,在某些情况下,它是going to break期间。

答案 1 :(得分:6)

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

答案 2 :(得分:1)

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

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

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

WM_CHAR也很常见

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

答案 3 :(得分: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++