简体   繁体   English

如何在Directx游戏中模拟鼠标点击

[英]How to simulate mouse click in a Directx game

I have a game written in Directx (not mine it's mmo game). 我有一个用Directx编写的游戏(不是我的mmo游戏)。 The game window isn't active (not minimized, just it's behind other windows but if is possible it can be minimized also). 游戏窗口未激活(未最小化,只是在其他窗口后面,但如果可能,也可以最小化)。

I want to simulate mouse click on x, y position. 我想模拟鼠标单击x,y位置。 Spy++ doesn't show anything in message when i'm clicking in game. 当我在游戏中单击时,Spy ++不会在消息中显示任何内容。

For now i did just that: 现在,我只是这样做:

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);
    }

It's restore game window click on point and minimize game window. 这是还原游戏窗口上的点击并最小化游戏窗口。

It's works good, but just when i'm not moving mouse... 它的工作原理很好,但是当我不移动鼠标时...

I search something else. 我搜索其他东西。 I want to click mouse without moving it for real. 我想单击鼠标而不真正移动它。 It's even possible do it in game? 在游戏中甚至有可能吗? I don't have any handle for button i want to click because it's a game... 我没有要单击的按钮的手柄,因为它是游戏...

PS Sorry for my english. PS对不起,我的英语。

Some of my code for simulating a mouse click on a non-active window looks like: 我的一些用于在非活动窗口上模拟鼠标单击的代码如下所示:

[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);

You can try using Sendiput. 您可以尝试使用Sendiput。 here is the Documentation: https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx 这是文档: https : //msdn.microsoft.com/zh-cn/library/windows/desktop/ms646310(v=vs.85).aspx

Here is my example: 这是我的示例:

Includes: 包括:

    #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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM