5

I've been trying to write a small utility that will modify the boundaries of where my mouse can go on the whole screen. I've used the the global mouse hook library that I found here (I'm using version 1), and then pass the mouse position information from the event it generates to my own function (just a test to see it working for now).

internal void ProcessMouseEvent(System.Drawing.Point point)
{
    Cursor.Position = new Point(50,50);
}

When running it, the mouse does appear to flash to the specified point, but will instantly revert back to where it was before the change if it was a movement event. Only when it was done through a click event does it actually remain at the new position.

Machavity
  • 30,841
  • 27
  • 92
  • 100
littlerat
  • 51
  • 2

2 Answers2

3

To limit where the mouse can go efficiently, you need to use cursor.clip. You can find its documentation here. It will do what you want much easier and is the recommended way.

FrostyFire
  • 3,212
  • 3
  • 29
  • 53
  • What if my boundaries aren't rectangular? – littlerat Dec 28 '12 at 01:51
  • @littlerat Your question did not mention a circle. You must use a rectangle with cursor.clip. Sorry! – FrostyFire Dec 28 '12 at 01:53
  • Well it's not circular either. What I'm trying to do is turn [this](http://i.imgur.com/6lpmk.jpg) into [this](http://i.imgur.com/KhWb0.jpg) without actually changing the screen resolutions. – littlerat Dec 28 '12 at 01:57
  • @littlerat Well I don't understand the images, but a rectangular clip with cursor.clip should work. Why would you want to do this? – FrostyFire Dec 28 '12 at 02:11
  • I'm trying to make my mouse movements more predictable across three different sized monitors that I have. It's a little difficult to explain, but a rectangular clip won't work as I need to prevent the mouse from moving in various corners. The bounds would look like the combination of all three monitors in the [second image](http://i.imgur.com/KhWb0.jpg) from earlier. – littlerat Dec 28 '12 at 03:25
  • @littlerat well sorry I cant help you any further. – FrostyFire Dec 28 '12 at 03:27
3

The problem here is that the hook gives you a notification of the mouse message. But doesn't prevent it from being processed by the application that is going to actually process the notification. So it gets handled as normal and the mouse moves where it wants to go. What you need to do is actually block the message from being passed on, that requires returning a non-zero value from the hook callback.

The library does not permit you to tinker with the hook callback return value, it is going to require surgery. Beware it is buggy. I'll instead use this sample code. With this sample callback method:

private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) {
    if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam) {
        System.Windows.Forms.Cursor.Position = new Point(50, 50);
        return (IntPtr)1;   // Stop further processing!
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}

And you'll see it is now solidly stuck. Use Alt+Tab, Alt+D, E to regain control.

Community
  • 1
  • 1
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Excellent answer, what I did is add `return new IntPtr(1)` only once right after setting the cursor position and it remained in place and still allowed the user to move the mouse in subsequent events. – MathuSum Mut Oct 15 '16 at 10:55