发送鼠标单击以管理员身份运行DirectX游戏

时间:2017-02-14 04:41:30

标签: c++ windows directx directinput

我一直在构建一个游戏相关程序,需要将模拟输入发送到游戏(这是屏幕上的顶部窗口并以全屏模式运行)。经过一番挣扎,我终于得到鼠标移动(光标拖动)和键盘输入工作,但由于某种原因,游戏不会响应模拟鼠标点击。

我尝试了以下内容:

#if TRUE // SendInput works for keyboard simulation and mouse drag, but not clicks:
    INPUT mouse = {0};
    mouse.type = INPUT_MOUSE;
    mouse.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    SendInput(1, &mouse, sizeof(INPUT));

    Sleep(100);

    ZeroMemory(&mouse, sizeof INPUT);
    mouse.type = INPUT_MOUSE;
    mouse.mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(1, &mouse, sizeof(INPUT));
#else // tried this, but it did not work:
    mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
    Sleep(75);
    mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
#endif

我遇到的第一个困境是发送消息,但我意识到这个问题是由游戏进程权限引起的。发送应用程序权限在此之后,我遇到了另一个问题,按键仅在某些游戏窗口/屏幕上注册,但经过一些搜索,我能够使用扫描码来克服这个问题。例如:

void SendSpacePress(bool bHardwareLevel){
    INPUT space = {0};
    space.type = INPUT_KEYBOARD;
    space.ki.time = 0;
    space.ki.dwExtraInfo = 0;

    if(!bHardwareLevel){
        space.ki.wVk = VK_SPACE;
    }else{
        space.ki.wScan = 0x39; // physical keyboard scan code
    }

    space.ki.dwFlags = bHardwareLevel ? KEYEVENTF_SCANCODE : 0;
    SendInput(1, &space, sizeof(INPUT));

    Sleep(rand()%25 + 25);

    space.ki.dwFlags = bHardwareLevel ? KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP : KEYEVENTF_KEYUP;
    SendInput(1, &space, sizeof(INPUT));
}

我也可以使用INPUT进行鼠标移动,如下所示:

void PanMouse(){
    INPUT mouse = {0};
    mouse.type = INPUT_MOUSE;
    mouse.mi.time = 0;
    mouse.mi.mouseData = 0;
    mouse.mi.dwExtraInfo = 0;
    mouse.mi.dwFlags = MOUSEEVENTF_MOVE;
    mouse.mi.dx = rand()%10 -5;
    mouse.mi.dy = rand()%10 -5;
    SendInput(1, &mouse, sizeof(INPUT));
}

现在我遇到的一个大问题是游戏拒绝注册我的模拟鼠标点击。我最好想要一种方法来发送鼠标输入而不必潜入钩子。 (游戏有多个客户端反作弊机制,所以我冒昧地猜测任何类型的外部进程挂钩或DLL注入都会触发保护。)从我读过的,我可能需要编写一个自定义驱动程序模拟硬件鼠标,因此输入来自内核级别。不是一个更好的选择,但如果需要,sobeit。 (如果需要的话,任何人都可以为此提供有用的信息吗?我从来没有搞过写作驱动程序,但我认为这是第一次。)

TL; DR :我需要做些什么来模拟鼠标点击才能在似乎忽略非硬件输入的游戏中注册? (即,在模拟键盘输入时,如何使用KEYEVENTF_SCANCODE类似于鼠标点击是合法的,可以让游戏欺骗游戏?)

所有建议,解决方案和建议表示赞赏。提前谢谢!

1 个答案:

答案 0 :(得分:-1)

不需要在输入之间休眠,而是需要注入一对鼠标输入,并time成员适当设置以指示“多长时间”。

这是你想要的东西。这将点击当前光标位置,鼠标模拟为100ms。

INPUT inputs[2] = {};

inputs[0].type = INPUT_MOUSE;
inputs[0].mi.time = 0;
inputs[0].mi.dx = 0;
inputs[0].mi.dy = 0;
inputs[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;

inputs[1].type = INPUT_MOUSE;
inputs[1].mi.time = 100;
inputs[1].mi.dx = 0;
inputs[1].mi.dy = 0;
inputs[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;

SendInput(2, inputs, sizeof(INPUT));

鼠标事件不会立即发生。它很快就会“排队”发生。

您应该对键盘事件使用相同的技巧。不要叫“睡觉”。