Is there a way to detect mouseclick outside of a user control?

I am creating a custom drop-down list and I want to register when the mouse is called outside the drop-down list to hide it. Is it possible to detect a click outside the control? or should I make some kind of mechanism in the contained form and check mouseclick when any dropdown is open?

user control

+8
c # winforms user-controls mouseevent
source share
5 answers

So, I finally understand that you only want it to close when the user clicks outside. In this case, the Leave event should work fine ... For some reason, I got the impression that you wanted it to close whenever they moved the mouse outside of your custom drop-down list. The Leave event occurs every time your control loses focus, and if the user clicks on something else, he will certainly lose focus, because the thing they clicked on gets focus.

The documentation also states that this event cascades up and down the control chain as needed:

Enter and Leave events are hierarchical and will cascade up and down the parent chain until appropriate control is achieved. For example, suppose you have a form with two GroupBox controls, and each GroupBox control has one TextBox control. When a carriage moves from one text field to another, a Leave event is raised for TextBox and GroupBox, and an Enter event is raised for another GroupBox and TextBox.

Overriding the UserControl 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 UserControl dropdown command:

 public partial class Form1 : Form { private UserControl1 customDropDown; public Form1() { InitializeComponent(); // Create the user control customDropDown = new UserControl1(); // Add it to the form 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 } } 

Everything works fine with the above code, except for one: if the user clicks on an empty area of ​​the form, UserControl does not close. Hmm, why not? Well, because the form itself does not want focus. Only controls can get focus, and we did not click on the control. And since nothing else stole the focus, the Leave event never went up, which meant that UserControl did not know that it had to shut itself down.

If you need UserControl to close when the user clicks on an empty area in the form, you need special case handling for this. Since you say that only clicks bother you, you can simply handle the Click event for the form and set focus to another 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); } } 

Yes, this last part seems to be hacked. The best solution, as others have said, is to use the SetCapture function to instruct Windows to grab the mouse over the UserControl window. The Capture control provides an even easier way to do the same.

+10
source share

Handle the Form MouseDown event or override the MouseDown form Method:

 enter code here 

And then:

 protected override void OnMouseDown(MouseEventArgs e) { if (!theListBox.Bounds.Contains(e.Location)) { theListBox.Visible = false; } } 

The Contains old System.Drawing.Rectangle method can be used to indicate if the point is inside the rectangle. The Bounds property of the control is an external Rectangle defined by the edges of the control. The Location property of the MouseEventArgs is the Point relative to Control that received the MouseDown event. The Bounds property of the control in the form relative to the form.

+4
source share

Technically, you will need p / invoke SetCapture () to receive click events that occur outside of your control.

But in your case, handling the Leave event, as @Martin suggests, should be sufficient.

EDIT:. Looking for a usage example for SetCapture() , I came across a Control.Capture property that I did not know about. Using this property means that you will not need to p / call anything, which is always good in my book.

So, you need to set Capture to true when showing the drop-down list, and then determine if the mouse pointer is inside the control in your click event handler, and if not, set Capture to false and close the drop-down list.

+2
source share

You are probably looking for a holiday event:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx

Leave when the input focus leaves the control.

+1
source share

I did it myself, and that’s how I did it.

When the drop-down list opens, register the click event in the parent form of the control:

 this.Form.Click += new EventHandler(CloseDropDown); 

But it only takes halfway. You probably want your drop to also close when the current window is deactivated. The most reliable way to detect this for me was through a timer that checks which window is currently active:

 [System.Runtime.InteropServices.DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); 

and

 var timer = new Timer(); timer.Interval = 100; timer.Tick += (sender, args) => { IntPtr f = GetForegroundWindow(); if (this.Form == null || f != this.Form.Handle) { CloseDropDown(); } }; 

Of course, you should, of course, only start the timer when the drop-down image is visible. In addition, there may be several other events in the parent form that you want to register when you open the drop-down list:

 this.Form.LocationChanged += new EventHandler(CloseDropDown); this.Form.SizeChanged += new EventHandler(CloseDropDown); 

Do not forget to unregister all these events in the CloseDropDown method :)

EDIT:

I forgot, you should also register a Leave event on your control to see if another control is activated / activated:

 this.Leave += new EventHandler(CloseDropDown); 

I think I have it now, this should cover all the bases. Let me know if I missed something.

0
source share

All Articles