有什么方法可以检测用户控件之外的鼠标点击? [英] Is there any way to detect a mouseclick outside a user control?

查看:18
本文介绍了有什么方法可以检测用户控件之外的鼠标点击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个自定义下拉框,我想在鼠标在下拉框外单击时进行注册,以便将其隐藏.是否可以检测到控件外的点击?或者我应该在包含表单上创建一些机制并在任何下拉框打开时检查鼠标点击?

I'm creating a custom dropdown box, and I want to register when the mouse is clicked outside the dropdown box, in order to hide it. Is it possible to detect a click outside a control? or should I make some mechanism on the containing form and check for mouseclick when any dropdownbox is open?

推荐答案

所以我终于明白你只希望它在用户点击外部时关闭.在这种情况下,Leave 事件 应该可以正常工作...出于某种原因,我的印象是,每当他们将鼠标移到自定义下拉列表之外时,您都希望它关闭.Leave 事件在你的控件失去焦点时触发,如果用户点击其他东西,它肯定会失去焦点,因为他们点击的东西获得焦点.

So I finally understand that you only want it to close when the user clicks outside of it. In that case, the Leave event should work just fine... For some reason, I got the impression you wanted it to close whenever they moved the mouse outside of your custom dropdown. The Leave event is raised whenever your control loses the focus, and if the user clicks on something else, it will certainly lose focus as the thing they clicked on gains the focus.

文档还说,此事件根据需要在控制链上下级联:

The documentation also says that this event cascades up and down the control chain as necessary:

EnterLeave 事件是分层的,将在父链上下级联,直到达到适当的控制.例如,假设您有一个带有两个 GroupBox 控件的 Form,并且每个 GroupBox 控件都有一个 TextBox 控件.当插入符号从一个 TextBox 移动到另一个 TextBox 时,将为 TextBox 和 GroupBox 引发 Leave 事件,并为另一个 GroupBox 和 TextBox 引发 Enter 事件.

The Enter and Leave events are hierarchical and will cascade up and down the parent chain until the appropriate control is reached. For example, assume you have a Form with two GroupBox controls, and each GroupBox control has one TextBox control. When the caret is moved from one TextBox to the other, the Leave event is raised for the TextBox and GroupBox, and the Enter event is raised for the other GroupBox and TextBox.

覆盖您的 UserControl 的 OnLeave 方法是处理此问题的最佳方法:

Overriding your UserControl's OnLeave method is the best way to handle this:

protected override void OnLeave(EventArgs e)
{
   // Call the base class
   base.OnLeave(e);

   // When this control loses the focus, close it
   this.Hide();
}

然后出于测试目的,我创建了一个表单,在命令中显示下拉用户控件:

And then for testing purposes, I created a form that shows the drop-down UserControl on command:

public partial class Form1 : Form
{
   private UserControl1 customDropDown;

   public Form1()
   {
      InitializeComponent();

      // Create the user control
      customDropDown = new UserControl1();

      // Add it to the form's Controls collection
      Controls.Add(customDropDown);
      customDropDown.Hide();
   }

   private void button1_Click(object sender, EventArgs e)
   {         
      // Display the user control
      customDropDown.Show();
      customDropDown.BringToFront();   // display in front of other controls
      customDropDown.Select();         // make sure it gets the focus
   }
}

一切都与上面的代码完美配合,除了有一件事:如果用户点击表单的空白区域,UserControl 不会关闭.嗯,为什么不呢?好吧,因为表单本身不需要焦点.只有 controls 可以获得焦点,我们没有点击一个控件.而且因为没有其他东西偷走了焦点,所以 Leave 事件从未引发,这意味着 UserControl 不知道它应该自行关闭.

Everything works perfectly with the above code, except for one thing: if the user clicks on a blank area of the form, the UserControl doesn't close. Hmm, why not? Well, because the form itself doesn't want the focus. Only controls can get the focus, and we didn't click on a control. And because nothing else stole the focus, the Leave event never got raised, meaning that the UserControl didn't know it was supposed to close itself.

如果您需要 UserControl 在用户单击表单中的空白区域时自行关闭,您需要对此进行一些特殊情况处理.既然你说你只关心 clicks,你可以只处理表单的 Click 事件,并将焦点设置到不同的控件:

If you need the UserControl to close itself when the user clicks on a blank area in the form, you need some special case handling for that. Since you say that you're only concerned about clicks, you can just handle the Click event for the form, and set the focus to a different control:

protected override void OnClick(EventArgs e)
{
   // Call the base class
   base.OnClick(e);

   // See if our custom drop-down is visible
   if (customDropDown.Visible)
   {
      // Set the focus to a different control on the form,
      // which will force the drop-down to close
      this.SelectNextControl(customDropDown, true, true, true, true);
   }
}

是的,这最后一部分感觉就像一个 hack.正如其他人所提到的,更好的解决方案是使用 SetCapture 函数 指示 Windows 将鼠标悬停在 UserControl 的窗口上.该控件的 Capture 属性提供一种更简单的方法来做同样的事情.

Yes, this last part feels like a hack. The better solution, as others have mentioned, is to use the SetCapture function to instruct Windows to capture the mouse over your UserControl's window. The control's Capture property provides an even simpler way to do the same thing.

这篇关于有什么方法可以检测用户控件之外的鼠标点击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆