I need to detect when the user moves the mouse over the Form and all its child controls and also when it leaves the Form. I tried the MouseEnter
and MouseLeave
events of the Form, I tried the WM_MOUSEMOVE
& WM_MOUSELEAVE
and WM_NCMOUSEMOVE
& WM_NCMOUSELEAVE
pairs of windows messages but none seem to work as I want...
Most of my Form is occupied by child controls of many sorts, there's not much client area visible. This means that if I move the mouse very quickly the mouse movement will not be detected, although the mouse is inside the Form.
For instance, I have a TextBox that is docked at the bottom and between the desktop and the TextBox, there's only a very small border. If I quickly move the mouse from the bottom into the TextBox, the mouse movement won't be detected, but the mouse is inside the TextBox, therefore, inside the Form.
How can I achieve what I need?
You can hook the main message loop and preprocess/postprocess any (WM_MOUSEMOVE) message what you want.
public class Form1 : Form {
private MouseMoveMessageFilter mouseMessageFilter;
protected override void OnLoad(EventArgs e) {
base.OnLoad( e );
this.mouseMessageFilter = new MouseMoveMessageFilter();
this.mouseMessageFilter.TargetForm = this;
Application.AddMessageFilter(this.mouseMessageFilter);
}
protected override void OnClosed(EventArgs e) {
base.OnClosed(e);
Application.RemoveMessageFilter(this.mouseMessageFilter);
}
private class MouseMoveMessageFilter : IMessageFilter {
public Form TargetForm { get; set; }
public bool PreFilterMessage( ref Message m ) {
int numMsg = m.Msg;
if ( numMsg == 0x0200 /*WM_MOUSEMOVE*/)
this.TargetForm.Text = string.Format($"X:{Control.MousePosition.X}, Y:{Control.MousePosition.Y}");
return false;
}
}
}