1

I have a game written in Directx (not mine it's mmo game). 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. Spy++ doesn't show anything in message when i'm clicking in game.

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...

P.S Sorry for my english.

Kaki
  • 55
  • 3
  • 9
  • Nobody plays in this game :D, and i want just click on PLAY button :D, so it's not a bot, i just want to know how i can do it and if it's even possible. This game is Duel of Champions and my skills are too low (for now) to write a AI or neural network :P – Kaki Dec 30 '12 at 20:20
  • I'd recommend `SendMessage` instead of trying to control the other window and the mouse. – chris Dec 30 '12 at 20:35
  • A little fail :D I was trying SendMesseage but without effect. Spy++ doesn't show me anything just because i was using a 64bit version of Spy++, 32bit works fine. – Kaki Dec 31 '12 at 14:04

2 Answers2

1

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);
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • Look at my first code it's almost the same. In function MakeLParam i have that: MouseX & 0xFFFF | (MouseY & 0xFFFF) << 16; If you can, you can download that game (only 10mb) and try with it. I would be grateful. – Kaki Dec 31 '12 at 18:33
  • Is the `Play` button in the game or on a loader? – Erik Philips Dec 31 '12 at 18:39
  • Also, says the game is not available in my country (US). – Erik Philips Dec 31 '12 at 18:43
  • Download link: http://pdc-doc-launcher.ubi.com/launcher/Installer/setup.exe I want try to click on Login button in the game. – Kaki Dec 31 '12 at 18:46
  • Using process explorer, launcher.exe never loads any directx dlls. The launcher is not using Direct X, so simulating key presses is VERY different. The wHnd you are looking for is most likely an actual MFC control. – Erik Philips Dec 31 '12 at 19:05
  • Actually taking a closer look, it appears to be a WebBrowser embeded in the application. – Erik Philips Dec 31 '12 at 19:09
  • Don't try on Launcher, start the right game by clicking "Start game" in Launcher. After that launcher.exe will create game.exe and in game.exe you will be have username, password field and LOGIN button. Game.exe is directx (i think), lanucher.exe isn't. – Kaki Dec 31 '12 at 19:17
  • Looks like it's not possible. Probably some protection from emulated mouse presses. – Erik Philips Dec 31 '12 at 19:39
  • It must be somehow possible :D But not my level yet (writting my own mouse driver, connect somehow to stream between mouse and game or something like that :D) – Kaki Dec 31 '12 at 19:45
  • PostMessage drops a message in the windows queue, that is the stream between the OS and the game. Writing your own driver is VERY complicated (I have one), getting it signed, and programmable is very difficult, and not worth clicking a button in a game :) – Erik Philips Dec 31 '12 at 19:47
  • But what kind of protection they had make. Connect directly to mouse and checking the real position of mouse or what? – Kaki Dec 31 '12 at 19:50
  • I have no idea, I don't reverse engineer software or attempt emulating keyboard/mouse events beyond extremely simple examples. – Erik Philips Dec 31 '12 at 19:54
0

You can try using Sendiput. here is the Documentation: https://msdn.microsoft.com/en-us/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);