【问题标题】:How to simulate a mouse movement如何模拟鼠标移动
【发布时间】:2011-11-21 11:51:46
【问题描述】:

如何模拟导致指针向左移动 500 像素的鼠标事件,然后使用 C++ 进行单击。我该怎么做这样的事情?

【问题讨论】:

  • 哪个操作系统?视窗?操作系统? Linux?它们都将完全不同。
  • 它被标记为 windows。

标签: c++ windows simulation


【解决方案1】:

对于那些使用Linux的人来说,这是一个使用Xlib的解决方案:

#include <X11/Xlib.h>
#include<stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>

void mouseClick(int button)
{
    Display *display = XOpenDisplay(NULL);

    XEvent event;

    if(display == NULL)
    {
        fprintf(stderr, "Errore nell'apertura del Display !!!\n");
        exit(EXIT_FAILURE);
    }

    memset(&event, 0x00, sizeof(event));

    event.type = ButtonPress;
    event.xbutton.button = button;
    event.xbutton.same_screen = True;

    XQueryPointer(display, RootWindow(display, DefaultScreen(display)), &event.xbutton.root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);

    event.xbutton.subwindow = event.xbutton.window;

    while(event.xbutton.subwindow)
    {
        event.xbutton.window = event.xbutton.subwindow;

        XQueryPointer(display, event.xbutton.window, &event.xbutton.root, &event.xbutton.subwindow, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.x, &event.xbutton.y, &event.xbutton.state);
    }

    if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");

    XFlush(display);

    usleep(100000);

    event.type = ButtonRelease;
    event.xbutton.state = 0x100;

    if(XSendEvent(display, PointerWindow, True, 0xfff, &event) == 0) fprintf(stderr, "Error\n");

    XFlush(display);

    XCloseDisplay(display);
}


int main(int argc, char * argv[]) {

    int x , y;
    x = atoi(argv[1]);
    y = atoi(argv[2]);
    Display *display = XOpenDisplay(0);

    Window root = DefaultRootWindow(display);
    XWarpPointer(display, None, root, 0, 0, 0, 0, x, y);
    mouseClick(Button1);
    XFlush(display);
    XCloseDisplay(display);
    return 0;
}

只需构建它,然后模拟在 x 处的点击,就可以:

$ ./a.out x y

即

$g++ -lX11 sgmousesim2.cpp

$./a.out 123 13

【讨论】:

  • 这对 X11 来说是完全正确的,但问题确实得到了澄清,要求提供 Windows 解决方案。
  • 刚刚注意到 :) 。也许它会帮助那些来寻找 Linux 特定解决方案的人。
  • 我仍然感谢您的帮助
【解决方案2】:

下面是一些修改过的 Win32 代码:

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#include <string.h>
#include <windows.h>


#define X 123
#define Y 123
#define SCREEN_WIDTH 1024
#define SCREEN_HEIGHT 800


void MouseSetup(INPUT *buffer)
{
    buffer->type = INPUT_MOUSE;
    buffer->mi.dx = (0 * (0xFFFF / SCREEN_WIDTH));
    buffer->mi.dy = (0 * (0xFFFF / SCREEN_HEIGHT));
    buffer->mi.mouseData = 0;
    buffer->mi.dwFlags = MOUSEEVENTF_ABSOLUTE;
    buffer->mi.time = 0;
    buffer->mi.dwExtraInfo = 0;
}


void MouseMoveAbsolute(INPUT *buffer, int x, int y)
{
    buffer->mi.dx = (x * (0xFFFF / SCREEN_WIDTH));
    buffer->mi.dy = (y * (0xFFFF / SCREEN_HEIGHT));
    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE);

    SendInput(1, buffer, sizeof(INPUT));
}


void MouseClick(INPUT *buffer)
{
    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN);
    SendInput(1, buffer, sizeof(INPUT));

    Sleep(10);

    buffer->mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP);
    SendInput(1, buffer, sizeof(INPUT));
}


int main(int argc, char *argv[])
{
    INPUT buffer[1];

    MouseSetup(&buffer);

    MouseMoveAbsolute(&buffer, X, Y);
    MouseClick(&buffer);

    return 0;
}

在使用之前,您需要将MouseSetup() 调用到每个 INPUT 缓冲区。

资源

MSDN - SendInput()
MSDN - INPUT
MSDN - MOUSEINPUT

【讨论】:

  • 更好地使用x * 0xFFFF / SCREEN_WIDTH + 1 进行像素完美的坐标归一化。 (对于 SCREEN_WIDTH
  • 这是必需的 - 否则从左到右和从上到下的光标定位精度会变差。
  • MouseSetup() to each INPUT 表示INPUT 类型的每个变量...我很困惑 - 乍一看我以为你必须先调用它每个鼠标输入(这毫无意义......)。
  • 如何检索 SCREEN_WIDTH 和 SCREEN_HEIGHT 以使 MouseMoveAbsolute() 显示大小(分辨率)独立?
  • " (x * (0xFFFF / SCREEN_WIDTH));"产生非常巨大的价值。它应该是这样的吗?
【解决方案3】:

使用mouse_event 函数。

【讨论】:

  • 如果您阅读文档,它会说“注意此功能已被取代。请改用 SendInput。”
  • 它在 Win2k 和 WinXP 中都能正常工作。我已经检查过了。我不知道 W7 中的支持,但我认为 mouse_event 也可以工作,因为有很多遗留代码使用它。而且这个函数的语法比 SendInput 的语法更明显。
  • 某事是否有效并不重要。很多事情都很好。一次,或在您的测试时,或在一台机器上。重要的是供应商告诉您不要使用它,而您忽略了它们。您不会在该供应商平台上通过认证。如果你不需要认证,你很可能会通过卖给他们破烂的废话来惹恼客户。它被弃用是有原因的。不要使用它。可能有万分之一的机会杀死某人。你不知道。所以不要使用它。
【解决方案4】:

使用SendInput 生成您要模拟的输入。来自 MSDN 文档:

合成击键、鼠标移动和按钮点击。

【讨论】:

    【解决方案5】:

    我从来没有用 C++ 做过这个。然而,有一个名为 Robot 的 Java 类能够产生鼠标事件。我在 Java 1.4 版上使用了它,但它仍然有效。我尝试了这个Simulate a physical mouse move in Mac OS X 中的示例。它可以在 MacOSX Lion 上与 Oracle Java 1.6.0_26 一起顺利运行。 Java 的优点在于它独立于平台。

    import java.awt.AWTException;
    import java.awt.Robot;
    
    public final class MovingMouseDemo
    {
       public static void main(String[] args) throws AWTException
       {
         Robot robot = new Robot();
         robot.setAutoDelay(5);
         robot.setAutoWaitForIdle(true);
    
         //put mouse in the top left of the screen
         robot.mouseMove(0, 0);
         //wait so that you can see the result
         robot.delay(1000);
         //put the mouse 200 pixels away from the top
         //10 pixels away from the left 
         robot.mouseMove(200, 10);
         robot.delay(1000);
         robot.mouseMove(40, 130);
      }
    }
    

    您仍然可以使用 JNI 将其与 C++ 绑定。

    希望对你有帮助

    【讨论】:

      【解决方案6】:

      仅 C++ 无法做到这一点。它没有“鼠标”的概念,更没有“点击”的概念。

      您需要某种与您的窗口系统对话的库。例如,QT。然后是搜索 API 并进行正确的 C++ 调用的问题。

      【讨论】:

        猜你喜欢
        • 2015-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多