【问题标题】:Simulating a keypress in Windows 8.1在 Windows 8.1 中模拟按键
【发布时间】:2015-05-23 16:44:06
【问题描述】:

我一直在尝试制作一个垃圾左键点击的程序,因为我的朋友要求我在 10 秒内点击比他更多的次数。

这是我的代码:

#include <stdio.h>
#include <iostream>
#include <Windows.h>

using namespace std;

bool should_click = false;
char in;

int main()
{

    INPUT ip;

    ip.type = INPUT_MOUSE;
    ip.ki.wScan = 0x01; //code for left click ^.^
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;

    while (!should_click)
    {
        cin >> in;
        if (in == 'g')
            should_click = true;
    }
    while (should_click)
    {
        // Press the key
        ip.ki.wVk = 0x01; // virtual-key code for mouse left click
        ip.ki.dwFlags = 0; // 0 for key press
        SendInput(1, &ip, sizeof(INPUT));

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

        Sleep(100);
    }

    return 0;

}

当我启动程序并按 g 键时,Windows 会每 100 毫秒变为黑色,然后是屏幕保护程序,然后又回到桌面。我只模拟一次按键尝试了这个,它做了同样的事情(只有一次)。

有没有办法解决这个问题?

PS:不,我无法在 10 秒内击败 96 次点击
PPS:我设法做到了。但我仍然想知道一种解决方法来制造一般的垃圾邮件发送者。

【问题讨论】:

  • No, I can't beat 96 clicks in 10 secs 作弊确实会变得更好?第一次就得了91,没那么难
  • 是的。弄清楚如果我使用鼠标配置文件,我可以获得 217。但我仍然想知道这是否可能。我也想和朋友来一场垃圾邮件大战。是否有可能阻止 Windows 做这种奇怪的事情?
  • 我已回滚您的编辑,将(已解决)添加到标题和正文中的解决方案。问题是问题,而不是答案。您应该发布自己问题的答案。

标签: c++ visual-c++ visual-studio-2013 windows-8.1


【解决方案1】:

SendInput() 可用于实施恶意软件。这就是为什么,ars 在 MSDN 上评论说,它受制于UIPI。因此,您只能通过以管理权限运行来摆脱这种奇怪的行为。

编辑: 这个MSDN article 有一个关于 UIPI 以及如何赋予应用程序规避它的权利的部分。它不仅涉及以管理员身份运行代码,还涉及在可执行文件的清单中设置UIAccess 属性,并使用有效证书对代码进行签名。

【讨论】:

  • UIPI 不是这里的问题。 UIPI 将阻止向更高权限级别的进程注入输入。它不会影响注入到同一特权级别进程的输入,也不会破坏其他有效的输入。如果发送到更高权限的进程,SendInput 调用就会失败
  • @RobCaplan-MSFT 确实:你的帖子是正确的答案。对于这段特定的代码
【解决方案2】:

问题是您基本上是在向 SendInput 发送随机输入。随机输入 -> 随机输出。

要发送鼠标输入,您需要使用 INPUT 联合的 Input.mi (MOUSEINPUT) 版本,而不是 ki (KEYBOARDINPUT) 版本。如果您在设置输入结构后设置断点并查看 ip.mi 中的值,您可能会看到 x 和 y 超出范围以及无效的 dwFlags。

如果您在联合的 mi 版本之外设置 INPUT 结构,那么您应该得到合理的输入。您还需要同时按下鼠标和抬起鼠标来获得完整的点击。您可以通过设置 INPUT 结构数组在一次调用 SendInput 中执行此操作:

UINT click_at(int x, int y)
{
    INPUT ip[2] = { 0 };

    ip[0].type = INPUT_MOUSE;
    ip[0].mi.dx = x;
    ip[0].mi.dy = y;
    ip[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_MOVE;
    ip[1].type = INPUT_MOUSE;
    ip[1].mi.dx = x;
    ip[1].mi.dy = y;
    ip[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;

    return SendInput(ARRAYSIZE(ip), ip, sizeof(INPUT));
}

如果您只想单击鼠标碰巧所在的位置而不是单击特定位置,请忽略 MOUSEEVENTF_MOVE

【讨论】:

  • 优秀:使用此代码,它可以按预期工作! mi.dwFlags(在 2 个 long 和一个 dword 之后)与 ki.dwFlags(在 2 个词之后)确实不同的事实解释了您对垃圾的含义!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-20
  • 1970-01-01
  • 2013-11-02
  • 1970-01-01
相关资源
最近更新 更多