views:

481

answers:

5

I have a Panel that contains child controls.

If i handling the Panel's MouseEnter and MouseLeave events, and his child's MouseEnter and MouseLeave events, here is the order of raising:

Panel.MouseEnter
Panel.MouseLeave
Child1.MouseEnter
Child1.MouseLeave
Panel.MouseEnter
Panel.MouseLeave

but i need the following order of raising:

Panel.MouseEnter
Child1.MouseEnter
Child1.MouseLeave
Panel.MouseLeave

Is that possible?

A: 

I believe so. A nice tool to have for verifying your WinForms application's events.

Windows.Forms Order of Events

http://missico.spaces.live.com/blog/cns!7178D2C79BA0A7E3!186.entry

  • Created with EventSpy written by Urs Eichmann. (ftp://missico.net/EventSpy.zip)
  • Using .NET Framework 3.5 and with Visual Basic’s Application Framework enabled.
AMissico
+2  A: 

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
}
ChrisF
Thanks, tried it out, but it has bug: there is race condition because the `Cursor.Position` is the current position, and not exactly the position when the mouse left the control.
DxCK
+1  A: 

This may not be the most elegant solution, but you could set a property in the parent control panel (subclass panel) that is a bool value like "bool selected". Then when the MouseEnter for the panel fires set it to true...then stop the mouseleave logic from firing unless it is set to false.

example

bool selected;

MouseEnter(..,..) { if (!selected) selected = true; else selected = false;

if (selected) /.. Logic Herer ../ }

MouseLeave() { if (selected) return;

/.. Logic Here ../ }

In reality i would just have the MouseLeave event of the child set the parameter.

Example:

Parent: bool doLeave;

MouseLeave(..,..) { if (doLeave) { /.. Logic ../ doLeave = false; }

Child: MouseLeave(..., ...) { DerivedPanel parent = this.Parent as DerivedPanel; if (parent != null) parent.doLeave = true; }

Neither are elegant but it will work.

JMcCarty
A: 

This is a tricky one, and will be difficult to code reliably for. One idea is to "capture" the 3 incoming events in a list and execute your desired code once the list is complete (has the 3 desired events in the list). Then when you're done executing whatever code (or perhaps capture the combo of events in reverse), you could empty your list and have it ready for the next time that particular combo-event happens. Not ideal, but just a thought.

Of course, that doesn't overcome the potential resolution issues & possible missed events Hans raised. Perhaps more context is in order.

pinkeerach
+1  A: 

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.

Threecoins