Global Mouse Hook + Simulate Mouse Inputs

globalhookmouse

I'm looking to create a global mouse hook that works in XP/Vista/7 which would allow me to access the X,Y values that the mouse is inputting, and modify those values before they hit Windows…

I also want to be able to simulate mouse inputs in between actual mouse inputs…

For example, lets say our inputs looked like this:

1: 1,0
2: 2,0
3: 3,0
4: ?,?

I want to be able to intercept input number 4 and run it through an 'if' statement: If the value of the input matches certain parameters, I want to modify the value by adding or subtracting from it…

A USB Mouse has a default polling rate of 125Hz and a maximum of 1000hz…

If possible (especially when the polling rate is set less than 1000hz) I would like to 'inject' inputs 'between' actual mouse updates (critical) so for example:

(in milliseconds)

0008 – 1,0
0016 – 1,0
0032 – 2,0

So the mouse is updating at 125Hz… Could I detect the frequency of inputs, and send an input every other input??? So for example I could 'double' the mouse frequency from 125hz to 250hz, and simulate my own 'in between' updates based on whatever rules I set…

Does any of these seem reasonable? Right now I am working in C# and I was working with the "Gma.UserActivityMonitor" from this tutorial here: http://www.codeproject.com/KB/cs/globalhook.aspx but for some reason I get a performance hit which makes utilizing this code with fullscreen games have an unusable lag on the mouse inputs due to the hook…

Perhaps I need to write something in C++? Any help would be greatly appreciated. Thanks!

Best Answer

I've build a library that can help you with that, it's a simple c library and can work on games where common windows api would not.

The following sample shows how to invert mouse movements with this library, it basically just multiplies displacements at the vertical axis by -1 so they happen at the contrary direction:

#include <interception.h>
#include "utils.h" // for process priority control

enum ScanCode
{
    SCANCODE_ESC = 0x01
};

int main()
{
    InterceptionContext context;
    InterceptionDevice device;
    InterceptionStroke stroke;

    raise_process_priority();

    context = interception_create_context();

    interception_set_filter(context, interception_is_keyboard, INTERCEPTION_FILTER_KEY_DOWN | INTERCEPTION_FILTER_KEY_UP);
    interception_set_filter(context, interception_is_mouse, INTERCEPTION_FILTER_MOUSE_MOVE);

    while(interception_receive(context, device = interception_wait(context), &stroke, 1) > 0)
    {
        if(interception_is_mouse(device))
        {
            InterceptionMouseStroke &mstroke = *(InterceptionMouseStroke *) &stroke;

            if(!(mstroke.flags & INTERCEPTION_MOUSE_MOVE_ABSOLUTE)) mstroke.y *= -1;

            interception_send(context, device, &stroke, 1);
        }

        if(interception_is_keyboard(device))
        {
            InterceptionKeyStroke &kstroke = *(InterceptionKeyStroke *) &stroke;

            interception_send(context, device, &stroke, 1);

            if(kstroke.code == SCANCODE_ESC) break;
        }
    }

    interception_destroy_context(context);

    return 0;
}    

You may see there's a check of the INTERCEPTION_MOUSE_MOVE_ABSOLUTE flag before inverting the vertical displacements. Normally the operating system works with relative coordinates but I have experienced that inside virtual machines the mouse coordinates works in absolute form, not relative. For simplicity this sample is inverting relative displacements only.

You can check more documentation at http://oblita.com/Interception.