7

I've attached some MouseMove and MouseClick events to my program and next up is one of these:

  1. Get "global" mouse movement, so that I can read the mouse location even outside the form.
  2. Prevent my mouse from leaving the form in the first place.

My project is a game so it'd be awesome to prevent the mouse leaving my form like most other games do (ofc. you can move it out if you switch focus with alt+tab fe.) and taking a look at answers to other questions asking for global mosue movement, they seem pretty messy for my needs.

Is there an easy way to prevent my mouse from going outside my form's borders? Or actually to prevent it from going OVER the borders in the first place, I want the mouse to stay inside the client area.


Additional info about the game:

The game is a short, 5-30 seconds long survival game (it gets too hard after 30 seconds for you to stay alive) where you have to dodge bullets with your mouse. It's really annoying when you move your mouse out of the form and then the player (System.Windows.Forms.Panel attached to mouse) stops moving and instantly gets hit by a bullet. This is why preventing mouse from leaving the area would be good.

  • 7
    As I user I would consider that a rude thing to do. Maybe would it be better if you just stop the game when the mouse is not over your window? – SJuan76 Feb 22 '13 at 16:57
  • Just to pile on a bit (as a comment, not an answer), but this behavior would *seriously* aggravate me. It would, in fact, prevent me from being able to play such a game quite often (since I typically switch windows by mouse-clicking) – Andrew Barber Feb 22 '13 at 17:05
  • Read the "Additional info" section I added, that's not really a problem since the mouse is only locked for 10-30 seconds and you can suicide any time you want. –  Feb 22 '13 at 17:05
  • So, say you've succeeded in getting the mouse to remain inside your game's client area. Now, suppose your game happens to crash. Oops! The mouse is now stuck inside that area of the screen with no way out! Better to take SJuan76's suggestion and just freeze the game until the mouse moves back into the client area. – RobH Feb 22 '13 at 17:11
  • @RobH I've seen games do this, I used to play "League of Legends" and you couldn't move the cursor out of the game window as long as the window had focus. As soon as the focus was lost (or the game was closed, or game crashed, etc.) the mouse would work normal again. –  Feb 22 '13 at 17:19
  • I can see it returning to normal when the focus is lost or the game is closed, because it is the game that is limiting (and unlimiting) the mouse movement, but for precisely that same reason, I don't see how the mouse movement is returned to normal if the game crashes. The OS is not going to unlimit the mouse movement just because the game isn't running anymore. All it knows is that some program told it to limit mouse movement, and so it's expecting the same program to set it back to normal. Just because other games do it doesn't make it the right thing to do. – RobH Feb 22 '13 at 17:38
  • @RobH Well it works properly in other games, so I can't see why not to use it. And the game I referred to is the worlds most played game, so it's nothing small. –  Feb 22 '13 at 17:59
  • Every game I've seen which traps the mouse *also* has a custom cursor, and that cursor often stays visible and motionless if you move the mouse outside of the game. I suspect that they're not actually capturing the mouse so much as turning off the cursor and using the mouse events to move their custom pointer (which is trivial to keep in bounds). – Bobson Feb 22 '13 at 18:32

5 Answers5

5

Late answer but might come in handy. You could subscribe the form to MouseLeave and MouseMove events and handle them like this :

    private int X = 0;
    private int Y = 0;

    private void Form1_MouseLeave(object sender, EventArgs e)
    {
        Cursor.Position = new Point(X, Y);
    }

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        if (Cursor.Position.X < this.Bounds.X + 50 )
            X = Cursor.Position.X + 20;
        else
            X = Cursor.Position.X - 20;

        if (Cursor.Position.Y < this.Bounds.Y + 50)
            Y = Cursor.Position.Y + 20;
        else
            Y = Cursor.Position.Y - 20;           
    }

The above will make sure the mouse cursor never leaves the bounds of the form. Make sure you unsubscribe the events when the game is finished.

Edit :

Hans Passants's answer makes more sense than my answer. Use Cursor.Clip on MouseEnter :

private void Form1_MouseEnter(object sender, EventArgs e)
    {
        Cursor.Clip = this.Bounds;
    }

You could free the cursor in case of any error/crash (I'm sure you could catch'em) :

Cursor.Clip = Rectangle.Empty;
Community
  • 1
  • 1
Abdusalam Ben Haj
  • 5,343
  • 5
  • 31
  • 45
  • This simple and yet everyone complaining of it? Woah, thanks :P –  Feb 22 '13 at 18:59
  • `Make sure you unsubscribe the events when the game is finished.` If your program happens to crash, then it can't unsubscribe the events, and you're left in the lurch. That's what the complaints are all about. – RobH Feb 22 '13 at 22:04
  • I am seriously confused as to why so many negative opinions surfaced back in 2013 about this question. Mouse capture is and was used by several Virtual Machine interfaces, and is very useful to keep the mouse focused on the virtual O/S *IF DESIRED*. Keywords there. – CrazyIvan1974 Jan 19 '17 at 14:54
4

You cannot trap the mouse, that would prevent the user from, say, operating the Start menu. Closest you can get is assigning the Cursor.Clip property. But it is easily defeated by the user pressing Ctrl+Esc for example, there is no notification for this.

Best thing to do is to subscribe the form's Deactivated event, it reliably tells you that the user switched to another program. The Activated event tells you when the user moved back. Of course the user will have few reasons to actually do this when the game score depends on keeping a game object moving. So don't forget to give the user an easy way to pause the game with, say, the Escape key.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
2

I don't know a solution for your exact problem, but I have a completely different idea for you. I don't know how your game works, but based on what you told me, why not make it a step harder: Add borders to the game-area, for example 4 pixels wide rectangles, which you are not allowed to touch. If you touch them, you die and the mouse gets released.

Patrik Lippojoki
  • 1,603
  • 4
  • 19
  • 22
  • 1
    The other answers didn't really comfort me, and this is actually pretty good idea. Hadn't thought of it before, thanks! :) –  Feb 22 '13 at 18:01
1

You can use the Cursor class. For example:

int X = Cursor.Position.X;
int Y = Cursor.Position.Y;

As for preventing the user to move the mouse outside the form, the best approach would probably be if you had someway to know what is the coordinates of your form on the screen and attach a MouseMove event, and check if the mouse is inside the form rectangle.

To know the form position on the screen take a look at this question.

Community
  • 1
  • 1
Bruno Klein
  • 3,217
  • 5
  • 29
  • 39
0

I wouldn't recommend the global mouse movement control for two reasons.

  • It's bad design, you should respect the bounds of the operating system. Make the application full screen if you want this kind of behaviour. The only applications that should perform these kind of operations are "kiosk" mode applications which lock down the entire OS (to prevent operator abuse).

  • Global key hooks are messy, aren't guaranteed to work and are dangerous because they affect a key part of the operating system (all controls). A bug in your code could result in requiring a reboot on the machine.

That said, last time I checked (a while ago, on Vista) SetWindowsHookEx still works (but its not officially supported IIRC), it's an unmanaged call so you'll have to pinvoke but with it you can refuse to pass on messages that would move the mouse outside of the bounds of your application. I'm not 100% sure if the OS will let you beat it to the cursor control (I've only blocked keyboards before on desktop boxes) but its probably your best shot.

Quibblesome
  • 25,225
  • 10
  • 61
  • 100