[英]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.