Parent Control Mouse Enter/Leave Events with Child Controls

Parent Control Mouse Enter/Leave Events With Child Controls

After more research, I discovered the Application.AddMessageFilter method. Using this, I created a .NET version of a mouse hook:

class MouseMessageFilter : IMessageFilter, IDisposable
{
public MouseMessageFilter()
{
}

public void Dispose()
{
StopFiltering();
}

#region IMessageFilter Members

public bool PreFilterMessage(ref Message m)
{
// Call the appropriate event
return false;
}

#endregion

#region Events

public class CancelMouseEventArgs : MouseEventArgs
{...}

public delegate void CancelMouseEventHandler(object source, CancelMouseEventArgs e);
public event CancelMouseEventHandler MouseMove;
public event CancelMouseEventHandler MouseDown;
public event CancelMouseEventHandler MouseUp;

public void StartFiltering()
{
StopFiltering();
Application.AddMessageFilter(this);
}

public void StopFiltering()
{
Application.RemoveMessageFilter(this);
}
}

Then, I can handle the MouseMove event in my container control, check to see if the mouse is inside my parent control, and start the work. (I also had to track the last moused over parent control so I could stop the previously started parent.)

---- Edit ----

In my form class, I create and hookup the filter:

public class MyForm : Form
{
MouseMessageFilter msgFilter;

public MyForm()
{...
msgFilter = new MouseMessageFilter();
msgFilter.MouseDown += new MouseMessageFilter.CancelMouseEventHandler(msgFilter_MouseDown);
msgFilter.MouseMove += new MouseMessageFilter.CancelMouseEventHandler(msgFilter_MouseMove);
}

private void msgFilter_MouseMove(object source, MouseMessageFilter.CancelMouseEventArgs e)
{
if (CheckSomething(e.Control)
e.Cancel = true;
}
}

mouse event fires when I mouse over child control

This question may address your problem. Basically you work out whether your mouse is over a child control or not using GetChildAtPoint.

Apply parent mouse events to child elements

When I'm making pictureBox1.Controls.Add(label1) label1 is
disappearing and I tried bring to front and change color but couldn't
do it. Please if you will have any idea show me in provided code by me
to be understandable for me. Thank you all again and again :)

You'd use code like this, maybe in the Load() event of the Form:

private void Form1_Load(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}

This keeps the label in the same position as it was, but makes the picturebox the parent.

Not sure where you're going wrong. Here's an example showing it in action. Both the PictureBox (Card) and Label (CardName) are inside a Panel (panel1). Clicking on button2 toggles the visibility of the Card. Clicking on button1 makes Card the Parent of CardName. You can see that at first, only the Card toggles visibility, but after clicking on button1 and setting the Parent, both toggle visibility together since CardName is a Child of Card (it also changes its BackColor to match that of its new Parent):

Sample Image

Code:

public partial class Form1 : Form
{

private void button1_Click(object sender, EventArgs e)
{
Point pt = CardName.Parent.PointToScreen(CardName.Location);
Card.Controls.Add(CardName);
CardName.Location = Card.PointToClient(pt);
}

private void button2_Click(object sender, EventArgs e)
{
Card.Visible = !Card.Visible;
}

}

When I move mouse over label, panel thinks mouse left it and rises
MouseLeave event

Here is how you can tell if the cursor has actually left the BOUNDS of the Panel, as opposed to simply enter a child control within the Panel:

private void panel1_MouseEnter(object sender, EventArgs e)
{
panel1.BackColor = Color.Red;
}

private void panel1_MouseLeave(object sender, EventArgs e)
{
Point pt = panel1.PointToClient(Cursor.Position);
if (!panel1.ClientRectangle.Contains(pt))
{
// we only get in here when the cursor leaves the BOUNDS of panel1
panel1.BackColor = Control.DefaultBackColor;
}
}

MouseLeave doesn't fire when moving from child control to parent's parent

My tests show this as a working solution. Just requires a custom user control.

    public class MyPanel : Panel
{
protected override void OnControlAdded(ControlEventArgs e)
{
e.Control.MouseLeave += DidMouseReallyLeave;
base.OnControlAdded(e);
}
protected override void OnMouseLeave(EventArgs e)
{
DidMouseReallyLeave(this, e);
}
private void DidMouseReallyLeave(object sender, EventArgs e)
{
if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
return;
base.OnMouseLeave(e);
}
}

Pass click event of child control to the parent control

While you can interact with parent form directly from child, It's better to raise some events by child control and subscribe for the events in parent form.

Raise event from Child:

public event EventHandler CloseButtonClicked;
protected virtual void OnCloseButtonClicked(EventArgs e)
{
CloseButtonClicked.Invoke(this, e);
}
private void CloseButton_Click(object sender, EventArgs e)
{
//While you can call `this.ParentForm.Close()` but it's better to raise the event
//Then handle the event in the form and call this.Close()

OnCloseButtonClicked(e);
}

Note: To raise the XXXX event, that's enough to invoke the XXXX event delegate; the reason of creating the protected virtual OnXXXX is just to follow the pattern to let the derivers override the method and customize the behavior before/after raising the event.

Subscribe and use event in Parent:

//Subscribe for event using designer or in constructor or form load
this.userControl11.CloseButtonClicked += userControl11_CloseButtonClicked;

//Close the form when you received the notification
private void userControl11_CloseButtonClicked(object sender, EventArgs e)
{
this.Close();
}

To learn more about events, take a look at:

  • Handling and raising events
  • Standard .NET event pattern


Related Topics



Leave a reply



Submit