【问题标题】:PostMessage() to emulate input in c++?PostMessage() 在 C++ 中模拟输入?
【发布时间】:2012-11-07 23:42:38
【问题描述】:

我正在尝试为游戏制作一个简单的机器人程序。即使游戏失焦或最小化,我也希望它能够正常工作。因此,我不能使用 SendInput() 因为它模拟全局事件。我发现,要完成这项工作,我必须使用 PostMessage() 函数。我做了一个模拟记事本输入的测试程序:

#include <Windows.h>
HWND handle = FindWindow(NULL,CStringW("Untitled - Notepad"));
HWND edit = FindWindowEx(handle, NULL, CStringW("Edit"), NULL);
PostMessage(edit, WM_CHAR, 'a', 0 );

此示例成功模拟了在记事本中单击“a”,即使记事本失焦或最小化。我同样让鼠标事件也能正常工作。

但是,当我为我的游戏尝试同样的事情时,我无法发布点击命令。查了一下发现调用FindWindowEx()时获取了原来的句柄但是权限被拒绝,没有返回句柄。

如果阻止此功能,是否有办法获得对另一个进程的“编辑”访问权限?

【问题讨论】:

  • 在调用 FindWindowEx 后调用 GetLastError 会得到什么?
  • 另外,如果您的游戏窗口没有名为“编辑”的子窗口,它将返回 null。你应该 PostMessage 到调用 FindWindow 时获得的句柄来找到你的游戏的窗口句柄。
  • 请编辑您的问题。您似乎正在尝试获取应用程序中不存在的窗口的句柄。

标签: c++ sendmessage sendkeys postmessage sendinput


【解决方案1】:

当然 Windows 不会让你这样做,如果你试图窃取用户的密码怎么办?没有焦点时不允许接收输入!

但是你可以在这里做一些技巧:你应该为鼠标或键盘编写一个钩子函数,这个函数应该在一个 DLL(不是你的 EXE)中实现,使用SetWindowsHookEx 来安装它,然后在你的 DLL 中使用 IPC 机制将鼠标和/或键盘消息发送到您的主 EXE。

但除此之外:虽然它通常工作正常

HWND handle = FindWindow(NULL,CStringW("Untitled - Notepad"));

敌人没有任何意义,windows 必须对大多数函数进行版本化,这些函数至少获得一个字符串参数:一个用于 ANSI,其名称以 A 结尾,另一个用于以 @ 结尾的宽(UTF-16)字符987654325@。 MSVC 在此设计之上有一个名为TCHAR 的额外层,并且通过使用定义将所有此类函数映射到ANSI 或Wide,因此如果您使用该版本的API,直接使用生成宽字符串的CStringW 是不明智的。由于 Windows API 与 char*wchar_t* 一起使用,为什么要将字符串文字转换为 CString 然后将其传递给函数?你应该使用其中之一:

// This also work with CStringA
HWND handleA = FindWindowA(NULL, "Untitled - Notepad");
// This also work with CStringW
HWND handleW = FindWindowW(NULL, L"Untitled - Notepad");
// This also work with CString
HWND handleT = FindWindow(NULL, _T("Untitled - Notepad") );

【讨论】:

  • "Windows当然不会让你这样做,如果你试图窃取用户的密码怎么办??你不能在没有焦点的情况下接收输入!!"这不是问题的一部分,但是是的,GetAsyncKeyState() 允许程序监视键盘,即使它不在焦点上。我提供的代码 sn-p 允许在记事本和/或程序失焦时输入记事本。您是否有示例说明如何按照您建议的模拟输入方式挂钩记事本?
  • @ReedB 您没有仔细阅读我的示例,请注意 L"", L 在文字开头使其成为宽字符串文字,并且由于您没有使用 TCHAR 版本,因此您应该使用 _T("") 确实有效!
  • 啊,我明白了,谢谢。我以前从未注入过 DLL。如果我选择尝试这个,你有什么建议吗?
  • 查看SetWindowsHookEx的文档,你会得到它,那里还有十几个样本
  • 谢谢。有没有办法简单地获得编辑权限?就像我说的,我让它在记事本中工作,但它在我的游戏中不起作用。跟代币有关系吗? msdn.microsoft.com/en-us/library/aa379295(VS.85).aspx
【解决方案2】:

您确定您尝试向其发送文本的游戏拥有可以从客户端的子项中枚举的 Windows 编辑控件吗?您所指的编辑控件很可能是客户端图形容器的一个实体。如果是这种情况,您可能必须将 WM_KEYDOWNWM_KEYUP 消息发送到客户端窗口本身以实现所需的功能。

希望对您有所帮助。

【讨论】:

  • 感谢您的回答!程序可以通过两种不同的方式处理用户输入。一种是从操作系统获取输入。用我的例子成功地模拟了这一点。另一种方法是不断检查给定键或按钮的状态。据我所知,这不能轻易复制。制作模拟这种类型输入的机器人程序的唯一方法是注入一个 dll,该 dll 执行通常会在按钮状态更改时运行的代码。
  • 在我看来,您试图从进程内存之外向程序发送字符,所以我相应地回复了。当然,从进程内存中运行可以使事情更容易访问,但是您在问题中描述的功能可以从进程本身之外实现。不管怎样,谢谢你的回复。
猜你喜欢
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 2016-10-05
  • 1970-01-01
  • 1970-01-01
  • 2015-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多