0

I am trying to change the BackColor property of a User Control and ForeColor of a label inside it. Following is my code:

private void NRow_MouseLeave(object sender, EventArgs e)
{
   BackColor = Color.White;
   label1.ForeColor = Color.Black;
}

private void NRow_MouseEnter(object sender, EventArgs e)
{
   BackColor = Color.Lime;
   label1.ForeColor = Color.White;
}

But its not working. Even I tried to add breakpoint on BackColor changing line but control is not reaching there. I also checked the event binding, its ok. The user control is added to a panel like this:

notContainer.Controls.Add(new NRow());

I don't know what is happening. Please help.

UPDATE:

Event handlers are attached like this:

this.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
this.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);
Aishwarya Shiva
  • 3,460
  • 15
  • 58
  • 107
  • How do you attach the event handlers to your UserControl ? – Luc Morin Sep 20 '13 at 19:11
  • 5
    MouseEnter/Leave are very unreliable for a UserControl. The controls inside that UC tend to get the event instead. The only decent workaround is a Timer who's Tick event checks Cursor.Position. Check [this answer](http://stackoverflow.com/a/12553029/17034) – Hans Passant Sep 20 '13 at 19:16
  • But don't you think adding a timer will add an overhead to the processing? – Aishwarya Shiva Sep 20 '13 at 19:36
  • Have you seen this discussion? http://www.vbforums.com/showthread.php?641685-My-UserControl-MouseEnter-Leave-Events-aren-t-firing – dmm Sep 20 '13 at 19:48
  • Have you tried to see if notContainer is getting a MouseLeave or MouseEnter event? – Animal Style Sep 20 '13 at 21:44
  • Well, a 200 msec timer isn't going to put a huge workload on a modern machine. You can certainly make it event-driven, you'll need to implement the IMessageFilter. That's where I tend to lose the crowd. – Hans Passant Sep 21 '13 at 00:17
  • @AishwaryaShiva you should post he screen shot of our `UserControl`, remember to set `BorderStyle` of both `UserControl` and `Panel` to `FixedSingle`, so that we can see how large the label covers your usercontrol – King King Sep 21 '13 at 02:49

3 Answers3

2

If your label1 placed inside your user control (UC) NRow, you should be handle MouseEnter and MouseEvent of label1 too. Because, your label1 inside your UC can be handles your mouse events instead your UC when the mouse moves over it.

this.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
this.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);    
label1.MouseEnter += new System.EventHandler(this.NRow_MouseEnter);
label1.MouseLeave += new System.EventHandler(this.NRow_MouseLeave);

Note: all of above lines should be placed inside your UC NRow.

Huy Nguyen
  • 918
  • 1
  • 10
  • 11
2

I was able to get it working by overriding the UserControl's OnMouseLeave and OnMouseEnter and using the PointToClient Method to determine if the mouse coordinates are still within the UserControl before reverting, see if something like this works for you.

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }
    protected override void OnMouseEnter(EventArgs e)
    {
        BackColor = Color.Lime;
        label1.ForeColor = Color.White;

        base.OnMouseEnter(e);
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (! Bounds.Contains(PointToClient( MousePosition)))
        {
            BackColor = Color.White;
            label1.ForeColor = Color.Black;
            base.OnMouseLeave(e);
        }        
    }
}
Mark Hall
  • 53,938
  • 9
  • 94
  • 111
1

You can try this code to pass messages from child controls to your UserControl, in your case you need to pass the message WM_MOUSEMOVE plus some little code to make it work as expected:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();            
    }
    Dictionary<Control,NativeControl> controls = new Dictionary<Control,NativeControl>();
    protected override void OnLostFocus(EventArgs e)
    {
        base.OnLostFocus(e);
        OnMouseLeave(e);
    }                
    protected override void OnControlAdded(ControlEventArgs e)
    {
        e.Control.HandleCreated += ControlsHandleCreated;
        base.OnControlAdded(e);
    }
    protected override void OnControlRemoved(ControlEventArgs e)
    {
        e.Control.HandleCreated -= ControlsHandleCreated;
        base.OnControlRemoved(e);
    }
    private void ControlsHandleCreated(object sender, EventArgs e)
    {
        Control control = sender as Control;
        NativeControl nc;
        if(!controls.TryGetValue(control, out nc)) {
           nc = new NativeControl(this);
           controls[control] = nc;
        }
        nc.AssignHandle(control.Handle);            
    }        
    public class NativeControl : NativeWindow
    {
        public NativeControl(UserControl1 parent)
        {
            Parent = parent;
        }
        UserControl1 Parent;
        bool entered;
        protected override void WndProc(ref Message m)
        {
            //WM_MOUSEMOVE = 0x200
            //WM_LBUTTONDOWN = 0x201
            //WM_LBUTTONUP = 0x202
            //WM_NCHITTEST = 0x84
            if (m.Msg == 0x200 || m.Msg == 0x201 || m.Msg == 0x202 || m.Msg == 0x84){
                //Check if Parent is not nul, pass these messages to the parent
                if (Parent != null){
                    m.HWnd = Parent.Handle;
                    Parent.WndProc(ref m);
                }
                if (m.Msg == 0x200 && !entered){
                    entered = true;
                    Parent.OnMouseEnter(EventArgs.Empty);
                }
                else entered = false;
            }
            else if (entered) entered = false;
            base.WndProc(ref m);                
        }
    }
}
King King
  • 61,710
  • 16
  • 105
  • 130