简体   繁体   English

防止鼠标离开我的表格

[英]Prevent mouse from leaving my form

I've attached some MouseMove and MouseClick events to my program and next up is one of these: 我已经将一些MouseMoveMouseClick事件附加到我的程序中,接下来就是其中之一:

  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. 我的项目是一个游戏,因此像大多数其他游戏一样防止鼠标离开我的形状真是太棒了(如果你用alt + tab fe切换焦点,你可以把它移出来)并看看其他人的答案。要求全球摩苏运动的问题,他们似乎对我的需求非常混乱。

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. 这场比赛是一场5到30秒的短暂生存游戏(在你活着的30秒后变得太难了)你必须用鼠标躲避子弹。 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. 当你将鼠标移出表单然后播放器(连接到鼠标的System.Windows.Forms.Panel )停止移动并立即被子弹击中时,这真的很烦人。 This is why preventing mouse from leaving the area would be good. 这就是为什么防止鼠标离开该区域会很好。

Late answer but might come in handy. 迟到的答案可能会派上用场。 You could subscribe the form to MouseLeave and MouseMove events and handle them like this : 您可以将表单订阅到MouseLeaveMouseMove事件并按如下方式处理它们:

    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. Hans Passants的回答比我的回答更有意义。 Use Cursor.Clip on MouseEnter : MouseEnter上使用Cursor.Clip

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;

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. 最接近的是分配Cursor.Clip属性。 But it is easily defeated by the user pressing Ctrl+Esc for example, there is no notification for this. 但是用户按Ctrl + Esc很容易打败它,例如,没有通知。

Best thing to do is to subscribe the form's Deactivated event, it reliably tells you that the user switched to another program. 最好的办法是订阅表单的Deactivated事件,它可靠地告诉您用户切换到另一个程序。 The Activated event tells you when the user moved back. Activated事件告诉您用户何时向后移动。 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. 所以不要忘记给用户一个简单的方法来暂停游戏,比如Escape键。

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. 我不知道你的游戏是如何运作的,但是根据你告诉我的内容,为什么不更加努力:在游戏区域添加边框,例如4像素宽的矩形,你不允许触摸。 If you touch them, you die and the mouse gets released. 如果触摸它们,就会死掉,鼠标会被释放。

You can use the Cursor class. 您可以使用Cursor类。 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. 至于防止用户将鼠标移动到表单之外,最好的方法可能是如果你已经知道屏幕上表单的坐标是什么并附加一个MouseMove事件,并检查鼠标是否在表单内长方形。

To know the form position on the screen take a look at this question. 要知道屏幕上的表格位置,请看一下这个问题。

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). 应该执行这些操作的唯一应用程序是“kiosk”模式应用程序,它们锁定整个操作系统(以防止操作员滥用)。

  • 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. 也就是说,上次我检查(前一段时间,在Vista上) SetWindowsHookEx仍然可以工作(但它没有正式支持IIRC),这是一个非托管调用,所以你必须用pinvoke但是用它你可以拒绝传递消息将鼠标移动到应用程序的边界之外。 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. 我不是百分百确定操作系统是否会让你击败光标控件(我之前只在桌面盒上阻止了键盘)但它可能是你最好的镜头。

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

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