11

我想编写一个 C++ 代码来模拟按下键盘键“A”:

// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

// Press the "..." key
ip.ki.wVk = code; // virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

// Release the "..." key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));

当我启动其他程序并等待我的程序执行时,它工作正常,单击“A”并且第一个程序对其做出反应。但是我发现在另一个应用程序中我的操作被某种方式阻止了(我可以手动按键盘上的“A”,但使用我的程序不会导致任何操作)。

那么,我可以做些什么来使从程序中按“A”与手动按“A”更加相同(这样第二个程序就不会识别出它是从程序中调用的)?

我没有第二个程序的源代码,也不知道它是如何识别没有手动按下“A”的。

我确定我想对我的代码做出反应的窗口是前台,接收并阻止我的密钥(因此它可以确定事件不是来自用户而是来自程序)。

4

3 回答 3

26

您也可以使用 SendInput() 发送硬件扫描码(与 DirectInput 可能忽略的虚拟扫描码相反)。它的文档记录很差,但 SendInput() 确实可以绕过 DirectInput。Eric 的解决方案不起作用的原因是他设置了硬件扫描码,但最终使用了虚拟扫描码(通过将 dwFlags 设置为 0 并将 wVk 设置为非零)。

本质上,要做一个你想要设置的按键:

ip.ki.dwFlags = KEYEVENTF_SCANCODE;

要释放密钥,请设置:

ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;

下面是一个完整的工作示例,它会打印字母“a”。您可以在此处找到其他扫描码。

#define WINVER 0x0500
#include <windows.h>

using namespace std;

int main()
{

    //Structure for the keyboard event
    INPUT ip;

    Sleep(5000);

    //Set up the INPUT structure
    ip.type = INPUT_KEYBOARD;
    ip.ki.time = 0;
    ip.ki.wVk = 0; //We're doing scan codes instead
    ip.ki.dwExtraInfo = 0;

    //This let's you do a hardware scan instead of a virtual keypress
    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    ip.ki.wScan = 0x1E;  //Set a unicode character to use (A)

    //Send the press
    SendInput(1, &ip, sizeof(INPUT));

    //Prepare a keyup event
    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));



    return 0;
}

注意:您可以通过向 SendInput() 传递一个 INPUT 结构数组来组合按键(例如,对于 A 的 shift + a)。

于 2013-09-17T15:55:08.737 回答
4

经常需要设置扫码:

// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = MapVirtualKey(code, MAPVK_VK_TO_VSC); // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;

// Press the "..." key
ip.ki.wVk = code; // virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));

正如 IInspectable 所建议的那样构建一个数组也绝对是要走的路。

于 2013-09-06T06:35:23.747 回答
0

如果您正在寻找创建游戏机器人,您是否看过 AutoHotKey 程序? http://www.autohotkey.com/

它提供了一种脚本语言,允许您完成许多与“机器人”创建有关的任务,而且比尝试在 C++ 中完成所有任务要容易得多

(当我所有的家人都迫使我创建一个帐户时,它当然为我播放了 Farmville)

于 2013-09-19T13:58:58.867 回答