问题
I have a Panel named panel1. panel1 has a "mosuseHover" eventhandler .panel1 also has some controls like pictureBox , label etc.
When i move mouse on panel1 , the event fire correctly , but when the mouse courser goes on panel1 controls , like pictureBox , the event not work . how can i make event to be invoke when mouse courser is on child controls.
I should note that i dont want create eventhandler for each child contol.
Best Regards
回答1:
You can add an IMessageFilter to implement your own global MouseHover for your Panel like this:
//This code uses some reflection so you must add using System.Reflection
public partial class Form1 : Form, IMessageFilter
{
public Form1(){
InitializeComponent();
Application.AddMessageFilter(this);
}
public bool PreFilterMessage(ref Message m) {
Control c = Control.FromHandle(m.HWnd)
if (HasParent(c,panel1)){
if (m.Msg == 0x2a1){//WM_MOUSEHOVER = 0x2a1
//Fire the MouseHover event via Reflection
typeof(Panel).GetMethod("OnMouseHover", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(panel1, new object[] {EventArgs.Empty});
}
}
return false;
}
//This method is used to check if a child control has some control as parent
private bool HasParent(Control child, Control parent) {
if (child == null) return false;
Control p = child.Parent;
while (p != null) {
if (p == parent) return true;
p = p.Parent;
}
return false;
}
}
NOTE: The code above is implemented to work for nested controls of any level in your Panel. If your panel contains only child controls stopping at level 1. You can change the code a bit by using c = Control.FromChildHandle(m.Hwnd) and check the control's parent by c==panel1 without having to use the HasParent method to check for child-ancestor relationship.
回答2:
You may create an eventhandler on the children and simply call the panels handler with the same arguments. Also have a look at this thread
回答3:
I countered the same problem. I solved it by creating a MouseEnter event and in it I declared Control ctl = sender as Control; Then I called ctl's Parent, with, Control panel = ctl.Parent; Now do whatever you want, as in panel.BackColor = Color.Red;
Like this:
private void label_MouseEnter(object sender, System.EventArgs e)
{
Control ctl = sender as Control; // gets the label control
Control panel = ctl.Parent; // gets the label's parent control, (Panel in this case)
if (ctl != null)
{
ctl.Font = new Font(ctl.Font.Name, 11, FontStyle.Underline); // change the font of the Label and style...
panel.BackColor = Color.Blue; // change the panel's backColor
ctl.Cursor = Cursors.Hand;
// do more with the panel & label
}
}
But don't forget to iterate through all the controls and to get the Panel and whatever that's inside the Panel. Like this:
public YourApp()
{
InitializeComponent();
foreach (Control objCtrl in this.Controls) // get all the controls in the form
{
if (objCtrl is Panel) // get the Panel
{
objCtrl.MouseEnter += new EventHandler(panel_MouseEnter); // do something to the panel on MouseEnter
objCtrl.MouseLeave += new EventHandler(panel_MouseLeave);
foreach (Control ctl in objCtrl.Controls) // get all the controls inside the Panel
{
if (ctl is Label) // get the label inside the panel
{
ctl.MouseEnter += new System.EventHandler(label_MouseEnter);
ctl.MouseLeave += new EventHandler(label_MouseLeave);
ctl.Click += new EventHandler(label_Click);
}
if (ctl is PictureBox) // get the pictureBox inside the panel
{
ctl.MouseEnter += new EventHandler(label_MouseEnter);
}
}
}
}
}
You can figure out the rest. Hope this helps.
来源:https://stackoverflow.com/questions/19089095/fire-panel-events-for-child-controls