Как определить, находится ли мышь внутри всей формы и дочерних элементов управления?
-
13-09-2019 - |
Вопрос
Мне нужно определить, когда пользователь наводит указатель мыши на форму и все ее дочерние элементы управления, а также когда он покидает форму.Я попробовал MouseEnter
и MouseLeave
события формы, я попробовал WM_MOUSEMOVE
& WM_MOUSELEAVE
и WM_NCMOUSEMOVE
& WM_NCMOUSELEAVE
пары сообщений Windows, но ни одно из них не работает так, как я хочу...
Большую часть моей формы занимают различные дочерние элементы управления, видимой клиентской области не так много.Это означает, что если я двигаю мышь очень быстро, движение мыши не будет обнаружено, хотя мышь находится внутри формы.
Например, у меня есть TextBox, который закреплен внизу, а между рабочим столом и TextBox есть лишь очень маленькая граница.Если я быстро перемещу мышь снизу в TextBox, движение мыши не будет обнаружено, но мышь окажется внутри TextBox, следовательно, внутри формы.
Как я могу достичь того, что мне нужно?
Решение
Вы можете подключить основной цикл обработки сообщений и выполнить предварительную/постобработку любого сообщения (WM_MOUSEMOVE), которое захотите.
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 );
}
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:{0}, Y:{1}", Control.MousePosition.X, Control.MousePosition.Y );
}
return false;
}
}
}
Другие советы
Как насчет этого:В OnLoad вашей формы рекурсивно просмотрите все дочерние элементы управления (и их дочерние элементы) и подключите событие MouseEnter.
Затем всякий раз, когда мышь входит в любого потомка, будет вызываться обработчик событий.Аналогичным образом вы можете подключить события MouseMove и/или MouseLeave.
protected override void OnLoad()
{
HookupMouseEnterEvents(this);
}
private void HookupMouseEnterEvents(Control control)
{
foreach (Control childControl in control.Controls)
{
childControl.MouseEnter += new MouseEventHandler(mouseEnter);
// Recurse on this child to get all of its descendents.
HookupMouseEnterEvents(childControl);
}
}
В вашем пользовательском элементе управления создайте событие наведения мыши для вашего элемента управления, подобное этому (или другого типа события), например это
private void picBoxThumb_MouseHover(object sender, EventArgs e)
{
// Call Parent OnMouseHover Event
OnMouseHover(EventArgs.Empty);
}
На вашем WinFrom, на котором размещен UserControl, есть это для UserControl для обработки MouseOver в вашем Designer.cs
this.thumbImage1.MouseHover += new System.EventHandler(this.ThumbnailMouseHover);
Который вызывает этот метод в вашем WinForm
private void ThumbnailMouseHover(object sender, EventArgs e)
{
ThumbImage thumb = (ThumbImage) sender;
}
Где ThumbImage — тип пользовательского элемента управления.
Быстрое и грязное решение:
private bool MouseInControl(Control ctrl)
{
return ctrl.Bounds.Contains(ctrl.PointToClient(MousePosition));
}