Как определить, находится ли мышь внутри всей формы и дочерних элементов управления?

StackOverflow https://stackoverflow.com/questions/986529

Вопрос

Мне нужно определить, когда пользователь наводит указатель мыши на форму и все ее дочерние элементы управления, а также когда он покидает форму.Я попробовал 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));
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top