【问题标题】:How do I send key strokes to a window without having to activate it using Windows API?如何在无需使用 Windows API 激活的情况下将击键发送到窗口?
【发布时间】:2010-11-16 06:56:30
【问题描述】:

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

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

【问题讨论】:

  • 我使用的是 Windows Vista。我还在 C# 中使用带有 Visual Studio 2008 的 .NET 3.5 SP1 框架。
  • 您不能将键盘输入定向到活动窗口以外的任何内容,这是有充分理由的。它们有点微妙,但它们就在那里。
  • 我曾经在 Windows 上的 C++ 中做过类似的事情。我捕获了记事本实例的 HDC(设备上下文),并使用 SendMessage 将其输入镜像到另一个(非活动)记事本中。如果您有设备上下文,您甚至可以写入最小化的应用程序。
  • @Annie 这是一个旧线程,但您的回答似乎与我的需要非常相关。您的 HDC(设备上下文)捕获是否比 SendMessage 更可靠?将模拟输入发送到最小化窗口

标签: winapi sendmessage sendkeys keystroke


【解决方案1】:
#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++

【讨论】:

    【解决方案2】:

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

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

    话虽如此,您可以使用SendMessageWM_KEYUPWM_CHARWM_KEYDOWN 消息,并且(取决于接收它们的 WndProc)可能会侥幸逃脱。但请记住,在某些情况下,它是going to break

    【讨论】:

    【解决方案3】:

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

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

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

    WM_CHAR 也相当普遍

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

    【讨论】:

    • 如果某些程序使用GetAsyncKeyState,有没有办法伪造键盘来发送模拟输入?也许拦截系统调用或者我不确定是什么
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 2011-01-08
      • 2010-10-30
      • 1970-01-01
      • 2011-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多