【问题标题】:How to simulate mouse click in a Directx game如何在 Directx 游戏中模拟鼠标点击
【发布时间】:2012-12-15 04:20:26
【问题描述】:

我有一个用 Directx 编写的游戏(不是我的,它是 mmo 游戏)。游戏窗口未激活(未最小化,只是位于其他窗口的后面,但如果可能,也可以将其最小化)。

我想模拟鼠标点击 x、y 位置。 当我在游戏中点击时,Spy++ 不会在消息中显示任何内容。

现在我就是这样做的:

private void start_Click(object sender, EventArgs e)
    {
        IntPtr ActualWindow = GetActiveWindow();

        ShowWindow(hWnd, ShowWindowCommands.Restore); //show game window
        Thread.Sleep(50);                             //a little slow down
        ClickOnPoint(hWnd, new Point(692, 87));       //click on x,y
        Thread.Sleep(50);                             //again a little slow down
        ShowWindow(hWnd, ShowWindowCommands.Minimize);//minimize game window
        ShowWindow(ActualWindow, ShowWindowCommands.Restore);//restore last active window
//sleep is needed for click, if i will do it too fast game will not detect the click
    }

private void ClickOnPoint(IntPtr wndHandle, Point clientPoint)
    {
        POINT oldPoint;
        GetCursorPos(out oldPoint);

        ClientToScreen(wndHandle, ref clientPoint);

        /// set cursor on coords, and press mouse
        SetCursorPos(clientPoint.X, clientPoint.Y);
        mouse_event(0x00000002, 0, 0, 0, UIntPtr.Zero); /// left mouse button down
        Thread.Sleep(18);
        mouse_event(0x00000004, 0, 0, 0, UIntPtr.Zero); /// left mouse button up
        Thread.Sleep(15);

        /// return mouse 
        SetCursorPos(oldPoint.X, oldPoint.Y);
    }

点击点恢复游戏窗口,最小化游戏窗口。

效果很好,但是当我不移动鼠标时...

我搜索别的东西。我想点击鼠标而不真正移动它。甚至有可能在游戏中做到这一点?我没有想要点击的按钮的句柄,因为它是一个游戏......

附言 对不起我的英语。

【问题讨论】:

  • 没有人在这个游戏中玩 :D,我只想点击 PLAY 按钮 :D,所以它不是机器人,我只是想知道我该怎么做以及是否有可能。这场比赛是冠军决斗,我的技能太低(目前)无法编写 AI 或神经网络:P
  • 我建议SendMessage 而不是试图控制另一个窗口和鼠标。
  • 有点失败 :D 我正在尝试 SendMesseage 但没有效果。 Spy++ 没有显示任何内容,因为我使用的是 64 位版本的 Spy++,32 位可以正常工作。

标签: c# c++ mouse simulation simulate


【解决方案1】:

我的一些模拟鼠标点击非活动窗口的代码如下所示:

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam);

// int MouseX
// int MouseY
// public static readonly uint WM_LBUTTONUP = 0x202;
// public static readonly uint WM_LBUTTONDOWN = 0x201;

int lparam = MouseX & 0xFFFF | (MouseY & 0xFFFF) << 16;
int wparam = 0;
PostMessage(windowHandle, WM_LBUTTONDOWN, wparam, lparam);      
Thread.Sleep(10);  
PostMessage(windowHandle, WM_LBUTTONUP, wparam, lparam);

【讨论】:

  • 看看我的第一个代码,它几乎是一样的。在 MakeLParam 函数中,我有:MouseX & 0xFFFF | (MouseY & 0xFFFF)
  • Play 按钮是在游戏中还是在加载器上?
  • 另外,说游戏在我的国家(美国)不可用。
  • 下载链接:pdc-doc-launcher.ubi.com/launcher/Installer/setup.exe我想尝试在游戏中点击登录按钮。
  • 使用进程资源管理器,launcher.exe 永远不会加载任何 directx dll。启动器没有使用 Direct X,所以模拟按键是非常不同的。您正在寻找的 wHnd 很可能是一个实际的 MFC 控件。
【解决方案2】:

您可以尝试使用 Sendiput。这是文档:https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx

这是我的例子:

包括:

    #include <stdio.h>
    #include <cstdlib>
    #include <windows.h>
    #include <winuser.h>
    #include <conio.h>

    INPUT input;
    int x = 889;
    int y = 451;

`// Mouse click up
    input.type = INPUT_MOUSE;
    input.mi.mouseData = 0;
    input.mi.dx = x * float(65536 / GetSystemMetrics(SM_CXSCREEN)); //x being coord in pixels
    input.mi.dy = y * float(65536 / GetSystemMetrics(SM_CYSCREEN)); //y being coord in pixels
    input.mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTDOWN);
    input.mi.time = 0;
    SendInput(1, &input, sizeof(input));`
`   
//Mouse click down
    input.type = INPUT_MOUSE;
    input.mi.mouseData = 0;
    input.mi.dx = x * float(65536 / GetSystemMetrics(SM_CXSCREEN)); //x being coord in pixels
    input.mi.dy = y * float(65536 / GetSystemMetrics(SM_CYSCREEN)); //y being coord in pixels
    input.mi.dwFlags = (MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_LEFTUP);
    input.mi.time = 0;
    SendInput(1, &input, sizeof(input));`

And You can do something like this to make sure you are in the focused window:

    HWND hWnd = ::FindWindowEx(0, 0, "YourGame - Use Spy++", 0);

    DWORD dwThreadID = GetWindowThreadProcessId(hWnd, NULL);
    AttachThreadInput(dwThreadID, GetCurrentThreadId(), true);

    SetForegroundWindow(hWnd);
    SetActiveWindow(hWnd);
    SetFocus(hWnd);

    AttachThreadInput(GetWindowThreadProcessId(GetForegroundWindow(), NULL),GetCurrentThreadId(), TRUE);

【讨论】:

    猜你喜欢
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    相关资源
    最近更新 更多