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?
相关问题
- Sorting 3 numbers without branching [closed]
- Graphics.DrawImage() - Throws out of memory except
- Why am I getting UnauthorizedAccessException on th
- 求获取指定qq 资料的方法
- How to know full paths to DLL's from .csproj f
Technically, you'll need to p/invoke SetCapture() in order to receive click events that happen outside of your control.
But in your case, handling the Leave event, as @Martin suggests, should be sufficient.
EDIT: While looking for an usage example for
SetCapture()
, I came across the Control.Capture property, of which I was not aware. Using that property means you won't have to p/invoke anything, which is always a good thing in my book.So, you'll have to set
Capture
totrue
when showing the dropdown, then determine if the mouse pointer lies inside the control in your click event handler and, if it doesn't, setCapture
tofalse
and close the dropdown.You are probably looking for the leave event:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx
Leave occurs when the input focus leaves the control.
I've done this myself, and this is how I did it.
When the drop down is opened, register a click event on the control's parent form:
But this only takes you half the way. You probably want your drop down to close also when the current window gets deactivated. The most reliable way of detecting this has for me been through a timer that checks which window is currently active:
and
You should of course only let the timer run when the drop down is visible. Also, there's probably a few other events on the parent form you'd want to register when the drop down is opened:
Just don't forget to unregister all these events in the CloseDropDown method :)
EDIT:
I forgot, you should also register the Leave event on you control to see if another control gets activated/clicked:
I think I've got it now, this should cover all bases. Let me know if I'm missing something.
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. TheLeave
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:
Overriding your UserControl's
OnLeave
method is the best way to handle this:And then for testing purposes, I created a form that shows the drop-down UserControl on command:
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.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: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'sCapture
property provides an even simpler way to do the same thing.Handle the Form's
MouseDown
event, or override the Form'sOnMouseDown
method:And then:
The Contains method old
System.Drawing.Rectangle
can be used to indicate if a point is contained inside a rectangle. The Bounds property of a Control is the outerRectangle
defined by the edges of the Control. The Location property of theMouseEventArgs
is the Point relative to the Control which received theMouseDown
event. The Bounds property of a Control in a Form is relative to the Form.