首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c#检测鼠标在任意位置(窗体内部和外部)的点击

c#检测鼠标在任意位置(窗体内部和外部)的点击
EN

Stack Overflow用户
提问于 2018-03-02 19:44:03
回答 3查看 10.4K关注 0票数 4

是否有可能在if语句中检测到鼠标单击(左/右)在任何位置(表单内部和外部)?如果可能,又是如何实现的?

代码语言:javascript
复制
if(MouseButtons.LeftButton == MouseButtonState.Pressed){

...

}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-03-02 20:20:43

如果我理解你对“从窗口外点击”的需求,而Hans Passant的建议并不适合你的需求,那么这是一个开始。您可能需要为Form1_Click添加一个事件处理程序。

注意:提供此代码是为了说明这一概念。此示例中的线程同步不是100%正确的。检查这个答案的历史记录,尝试一个更“线程正确”的答案,有时会抛出异常。作为一种替代方案,为了摆脱所有线程问题,您可以让StartWaitingForClickFromOutside中的任务始终运行(也就是始终处于“侦听”模式),而不是尝试检测“表单内”或“表单外”状态并相应地启动/停止循环。

代码语言:javascript
复制
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            this.MouseLeave += Form1_MouseLeave;
            this.Leave += Form1_Leave;
            this.Deactivate += Form1_Deactivate;
            this.MouseEnter += Form1_MouseEnter;
            this.Activated += Form1_Activated;
            this.Enter += Form1_Enter;
            this.VisibleChanged += Form1_VisibleChanged;
        }

        private AutoResetEvent are = new AutoResetEvent(false);

        // You could create just one handler, but this is to show what you need to link to
        private void Form1_MouseLeave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void Form1_Leave(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void Form1_Deactivate(object sender, EventArgs e) => StartWaitingForClickFromOutside();
        private void StartWaitingForClickFromOutside()
        {
            are.Reset();
            var ctx = new SynchronizationContext();

            var task = Task.Run(() =>
            {
                while (true)
                {
                    if (are.WaitOne(1)) break;
                    if (MouseButtons == MouseButtons.Left)
                    {
                        ctx.Send(CLickFromOutside, null);
                        // You might need to put in a delay here and not break depending on what you want to accomplish
                        break;
                    }
                }
            });
        }

        private void CLickFromOutside(object state) => MessageBox.Show("Clicked from outside of the window");
        private void Form1_MouseEnter(object sender, EventArgs e) => are.Set();
        private void Form1_Activated(object sender, EventArgs e) => are.Set();
        private void Form1_Enter(object sender, EventArgs e) => are.Set();
        private void Form1_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible) are.Set();
            else StartWaitingForClickFromOutside();
        }
    }
}

如果我对您的理解有误,您可能会发现以下内容很有用:Pass click event of child control to the parent control

票数 5
EN

Stack Overflow用户

发布于 2018-03-02 19:50:19

当用户在表单控件外部单击时,它会失去焦点,您可以使用that.which,这意味着您必须使用表单控件的_Deactivate(object sender, EventArgs e)事件来执行此操作。因为它将在窗体失去焦点并且不再是活动窗体时触发。假设Form1是表单,那么事件将如下所示:

代码语言:javascript
复制
private void Form1_Deactivate(object sender, EventArgs e)
{
    // Your code here to handle this event
}
票数 5
EN

Stack Overflow用户

发布于 2021-01-02 23:33:48

一种方法是用一个无边框的窗体覆盖整个屏幕,并将属性设置为透明(在完全透明之上的几个百分比,不确定全透明是否有效,但您不会注意到差异),并将其设置为最高。然后使用表单中的事件。一旦检测到单击,这将不会影响窗体下面的任何东西(在我的应用程序中,这是我希望发生的事情),但是窗体可以关闭,然后在不到一秒的时间内再次单击鼠标,以激活下面的控件。我在VB6中使用windows API使用鼠标钩子没有问题,但似乎找不到在2019版本的.NET中可以在c#中工作的东西,所以这是一个很好的变通方法。当然,为了更聪明,您可以使用不规则表单方法来使透明表单具有与鼠标相同的形状,并遵循它。注意:我刚刚找到了使用钩子完成这项工作的完整代码,这些钩子一般人都可以立即启动和运行!KeyboardMouseHooks C#库- CodePlex存档PS如果您使用my (哑巴)方法,请记住创建一个退出键或按钮,否则您将不得不重新启动计算机,除非窗体被编程为在实际单击时消失,如建议的那样!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49068445

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档