Как определить, находится ли мышь внутри всей формы и дочерних элементов управления? - PullRequest
7 голосов
/ 12 июня 2009

Мне нужно определить, когда пользователь наводит указатель мыши на форму и все ее дочерние элементы управления, а также когда он покидает форму. Я пробовал MouseEnter и MouseLeave события формы, я пробовал пары оконных сообщений WM_MOUSEMOVE & WM_MOUSELEAVE и WM_NCMOUSEMOVE & WM_NCMOUSELEAVE, но ни одно из них не работает так, как я хочу ...

Большая часть моей Формы занята дочерними элементами управления многих видов, там не так много видимой клиентской области. Это означает, что если я перемещу мышь очень быстро, движение мыши не будет обнаружено, хотя мышь находится внутри формы.

Например, у меня есть TextBox, который закреплен внизу, между рабочим столом и TextBox, граница очень маленькая. Если я быстро переместлю мышь снизу в TextBox, движение мыши не будет обнаружено, но мышь находится внутри TextBox, поэтому внутри формы.

Как мне добиться того, что мне нужно?

Ответы [ 4 ]

13 голосов
/ 12 июня 2009

Вы можете перехватить основной цикл сообщений и предварительно обработать / постобработать любое сообщение (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;
        }

    }
}
2 голосов
/ 12 июня 2009

Как насчет этого: В 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);
   }
}
0 голосов
/ 01 июля 2015

Быстрое и грязное решение:

private bool MouseInControl(Control ctrl)
{
    return ctrl.Bounds.Contains(ctrl.PointToClient(MousePosition));
}
0 голосов
/ 08 апреля 2011

На вашем пользовательском элементе управления создайте событие указателя мыши для вашего элемента управления, как этот (или другой тип события), как этот

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 - тип пользовательского контроля

...