MouseEnter and MouseLeave events from a Panel and its child controls
Solution 1
If you dont mind creating a usercontrol(derived from the panel or other parent container you wish),
Override your parent's OnMouseLeave
method to look like the following..
protected override void OnMouseLeave(EventArgs e)
{
if(this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
return;
else
{
base.OnMouseLeave(e);
}
}
Then, the event raising will be in the required order.
Solution 2
The mouse is "leaving" the panel as it enters the child control which is why it fires the event.
You could add something along the following lines in the panel MouseLeave
event handler:
// Check if really leaving the panel
if (Cursor.Position.X < Location.X ||
Cursor.Position.Y < Location.Y ||
Cursor.Position.X > Location.X + Width - 1 ||
Cursor.Position.Y > Location.Y + Height - 1)
{
// Do the panel mouse leave code
}
Solution 3
The solution is to track the number of enters/leaves. In you overall control add a counter:
private int mouseEnterCount = 0;
In the MouseEnter handler do this:
if (++mouseEnterCount == 1)
{
// do whatever needs to be done when it first enters the control.
}
In the MouseLeave handler do this:
if (--mouseEnterCount == 0)
{
// do whatever needs to be done when it finally leaves the control.
}
and do the above MouseEnter and MouseLeave event handlers for ALL the child controls as well as the containing object.
Solution 4
Matthew's answer will not work always. Especially if the child control is set to the edge of its container and the mouse moves off the controls in that direction. You will never detect the MouseLeave event.
The best approach is to create a user control container then hook all the child controls' MouseEnter and MouseLeave events so that you can properly detect when and where the mouse is at all times. THEN if it enters your container's bounds you can fire a custom MouseEnter event and when it leaves MouseLeave event.
Solution 5
Jimmy T. is right. There will be problems if there is no (or small) space betwean Parent Control (Panel) edge and Child Control.
This is how I solve this problem in UserControl-derived class:
public CSStackPanelItem()
{
InitializeComponent();
MouseEnter += new EventHandler(CSStackPanelItem_MouseEnter);
foreach (Control child in Controls)
{
child.MouseEnter += (s, e) => CSStackPanelItem_MouseEnter(s, e);
child.MouseLeave += (s, e) => OnMouseLeave(e);
}
}
protected override void OnMouseLeave(EventArgs e)
{
if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
return; //suppress mouse leave event handling
if (m_bIsHover)
{
m_bIsHover = false;
Invalidate(); //actually my mouse Enter/Leave event
}
base.OnMouseLeave(e);
}
void CSStackPanelItem_MouseEnter(object sender, EventArgs e)
{
m_bIsHover = true;
Invalidate(); //actually my mouse Enter/Leave event
}
DxCK
Programming for fun. Download my fastest file search program from my website.
Updated on August 05, 2022Comments
-
DxCK almost 2 years
I have a
Panel
that contains child controls.If I handle the
Panel
'sMouseEnter
andMouseLeave
events, and its child'sMouseEnter
andMouseLeave
events, the events are raised in this order:Panel.MouseEnter Panel.MouseLeave Child1.MouseEnter Child1.MouseLeave Panel.MouseEnter Panel.MouseLeave
But I need the following order:
Panel.MouseEnter Child1.MouseEnter Child1.MouseLeave Panel.MouseLeave
Is that possible?