是否有可能在if语句中检测到鼠标单击(左/右)在任何位置(表单内部和外部)?如果可能,又是如何实现的?
if(MouseButtons.LeftButton == MouseButtonState.Pressed){
...
}发布于 2018-03-02 20:20:43
如果我理解你对“从窗口外点击”的需求,而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();
}
}
}如果我对您的理解有误,您可能会发现以下内容很有用:Pass click event of child control to the parent control
发布于 2018-03-02 19:50:19
当用户在表单控件外部单击时,它会失去焦点,您可以使用that.which,这意味着您必须使用表单控件的_Deactivate(object sender, EventArgs e)事件来执行此操作。因为它将在窗体失去焦点并且不再是活动窗体时触发。假设Form1是表单,那么事件将如下所示:
private void Form1_Deactivate(object sender, EventArgs e)
{
// Your code here to handle this event
}发布于 2021-01-02 23:33:48
一种方法是用一个无边框的窗体覆盖整个屏幕,并将属性设置为透明(在完全透明之上的几个百分比,不确定全透明是否有效,但您不会注意到差异),并将其设置为最高。然后使用表单中的事件。一旦检测到单击,这将不会影响窗体下面的任何东西(在我的应用程序中,这是我希望发生的事情),但是窗体可以关闭,然后在不到一秒的时间内再次单击鼠标,以激活下面的控件。我在VB6中使用windows API使用鼠标钩子没有问题,但似乎找不到在2019版本的.NET中可以在c#中工作的东西,所以这是一个很好的变通方法。当然,为了更聪明,您可以使用不规则表单方法来使透明表单具有与鼠标相同的形状,并遵循它。注意:我刚刚找到了使用钩子完成这项工作的完整代码,这些钩子一般人都可以立即启动和运行!KeyboardMouseHooks C#库- CodePlex存档PS如果您使用my (哑巴)方法,请记住创建一个退出键或按钮,否则您将不得不重新启动计算机,除非窗体被编程为在实际单击时消失,如建议的那样!
https://stackoverflow.com/questions/49068445
复制相似问题