簡體   English   中英

c# 檢測任意位置的鼠標點擊(表單內部和外部)

[英]c# Detect mouse clicks anywhere (Inside and Outside the Form)

這是否可以在 if 語句中的任何位置(表單內部和外部)檢測鼠標單擊(左/右)? 如果可能的話,怎么做?

if(MouseButtons.LeftButton == MouseButtonState.Pressed){

...

}

當用戶在表單控件之外單擊時,它會失去焦點,您可以使用它。這意味着您必須使用表單控件的_Deactivate(object sender, EventArgs e)事件才能使其工作。 因為 which 將在表單失去焦點並且不再是活動表單時觸發。 Form1為表單,那么事件將如下所示:

private void Form1_Deactivate(object sender, EventArgs e)
{
    // Your code here to handle this event
}

如果我了解您對“從窗口外單擊”的需求並且 Hans Passant 的建議不符合您的需求,那么這是一個首發。 您可能需要為Form1_Click添加事件處理程序。

注意:提供此代碼是為了說明這個概念。 此示例中的線程同步不是 100% 正確的。 檢查此答案的歷史,以嘗試更“線程正確”的答案,有時會引發異常。 作為替代方案,要擺脫所有線程問題,您可以讓 StartWaitingForClickFromOutside 中的任務始終運行(也就是始終處於“偵聽”模式),而不是嘗試檢測“表單內”或“表單外” " 狀態並相應地啟動/停止循環。

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();
        }
    }
}

如果我對您的理解不正確,您可能會發現這很有用: 將子控件的單擊事件傳遞給父控件

一種方法是用無邊框的窗體覆蓋整個屏幕,並將屬性設置為透明(比完全透明高幾個百分點,不確定全透明是否有效,但您不會注意到差異),並將其設置為最頂層。 然后使用表單中的事件。 一旦檢測到點擊,這不會影響表單下方的任何內容(在我的應用程序中這是我想要發生的事情),但是可以關閉表單,並且在幾分之一秒后模擬另一個鼠標點擊以激活控件下。 我在 VB6 中使用 Windows API 使用鼠標鈎子沒有問題,但似乎找不到適用於 2019 版 .NET 的 c# 的東西,所以這是一個很好的解決方法。 當然,要真正聰明,您可以使用不規則形狀的方法使透明形狀與鼠標形狀相同並跟隨它。 注意:我剛剛找到了完整的代碼來使用普通人可以立即啟動並運行的鈎子! KeyboardMouseHooks C# 庫 - CodePlex Archive PS 如果您使用我的(愚蠢的)方法,請記住創建一個轉義鍵或按鈕,否則您將不得不重新啟動計算機,除非該表單被編程為按照建議消失以進行真正的點擊!

我知道這已經晚了,但也許它可以幫助某人。 使用任何控件的MouseUp事件的MouseEventArgs ,您可以檢查鼠標按鈕和滾輪等。 這是一個例子。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        this.MouseUp += Form1_MouseUp;
    }

    private void Form1_MouseUp(object sender, MouseEventArgs e)
    {
        if(e.Button == MouseButtons.Left)
        {
            DoSomething_LeftClick();
        }
        else if(e.Button == MouseButtons.Right)
        {
            DoSomething_RightClick();
        }
    }

    private void DoSomething_LeftClick()
    {
        //Here some code
    }
    private void DoSomething_RightClick()
    {
        //Here some code
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM