Как лучше всего определить, находится мышь над формой или нет? - PullRequest
3 голосов
/ 20 мая 2010

Я выяснил , как захватывать щелчки мышью по всей форме, но этот метод плохо подходит для MouseEnter и MouseLeave. Мой макет формы состоит из множества Panels и TableLayoutPanels, поэтому нет никакого всеобъемлющего элемента управления, для которого я могу отслеживать события, и, очевидно, событие MouseLeave для кнопки не означает, что курсор покинул всю форму. Кто-нибудь нашел хороший способ обойти это?

Ответы [ 5 ]

3 голосов
/ 20 мая 2010

Для начала нужно проверить, содержит ли ClientRectangle текущую позицию мыши. Так, например, на вашем обработчике MouseMove вы можете иметь:

if (ClientRectangle.Contains(e.Location))
{
    bool mouseIsOverThisControl = true;
}
0 голосов
/ 09 мая 2017

Выполните событие MouseEnter и MouseLeave над формой и элементами управления формой; используйте логическое значение, чтобы определить, вошла ли мышь или нет.

Примером будет

    private static bool mouseEnteredForm

    private void Form1_MouseMove(object sender, MouseEventArgs e)
    {
        mouseEnteredForm = true;
        Form.MouseLeave += Form1_MouseLeave;
        CheckMouseLocation();
    }

    private void Form1_MouseLeave(object sender, MouseEventArgs e)
    {
        mouseEnteredForm = false
        CheckMouseLocation();
    }

    private static void CheckMouseLocation()
    {
        if(!mouseOverForm)
        {
            MessageBox.Show("Mouse Not Over Form!);
        }
        else if(mouseOverForm) //else if is optional. You could also use else in this case. I used else if for the sake of the example.
        {
            MessageBox.Show("Mouse Is Over Form");
        }
    }

Это может быть утомительно, если у вас есть много объектов над формой

0 голосов
/ 09 марта 2016

Я нашел несколько ответов, которые были близки к тому, что я хотел, но я сделал что-то другое. Я хотел определить, ушла ли мышь из области формы (включая строку заголовка), и это сработало для меня:

В конструктор формы добавляю таймер:

time.Interval = 250;
time.Tick += time_Tick;
time.Start();

Затем в методе тиков я делаю следующее:

void time_Tick(object sender, EventArgs e)
{
    switch (RectangleToScreen(Bounds).Contains(PointToScreen(Cursor.Position))) {
        case true:
            if (Opacity != .9999D)
                Opacity = .9999D;
            break;
        case false:
            if (Opacity != .5D)
                Opacity = .5D;
            break;
    }
}
0 голосов
/ 21 мая 2010

Как кто-то указал здесь можно использовать SetWindowsHookEx () или просто подключить событие MouseMove ко всем элементам управления в форме. Последний работает у меня нормально. Единственный недостаток - если вы добавляете / удаляете элементы управления во время выполнения, вам может понадобиться другое решение.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsForms_MouseEvents
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            MouseMove += OnMouseMove;
            MouseLeave += OnMouseLeave;

            HookMouseMove(this.Controls);
        }

        private void HookMouseMove(Control.ControlCollection ctls)
        {
            foreach (Control ctl in ctls)
            {
                ctl.MouseMove += OnMouseMove;
                HookMouseMove(ctl.Controls);
            }
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            BackColor = Color.Plum;

            Control ctl = sender as Control;
            if (ctl != null)
            {
                // Map mouse coordinate to form
                Point loc = this.PointToClient(ctl.PointToScreen(e.Location));
                Console.WriteLine("Mouse at {0},{1}", loc.X, loc.Y);
            }
        }

        private void OnMouseLeave(object sender, EventArgs e)
        {
            BackColor = Color.Gray;
        }

    }
}
0 голосов
/ 20 мая 2010

Добавьте к форме таймер с разумным интервалом (возможно, 50 мс). Используйте этот код в обработчике событий Tick, чтобы увидеть, находится ли мышь над формой:

// Check if mouse is currently over the form
    bool temp_mof = ClientRectangle.Contains(
       Form.MousePosition.X - Location.X,
       Form.MousePosition.Y - Location.Y);

РЕДАКТИРОВАТЬ: Вот более полное решение для обнаружения, что мышь находится над формой и что кнопка была нажата. timer1Tick() - это обработчик события Tick для Timer в форме. Нет необходимости иметь дополнительные обработчики событий для других элементов управления в форме. Это сделает вашу форму "одной гигантской кнопкой":)

bool m_mouse_over_form = false;
// Assume the left button is down at onset
bool m_left_button_down = true;

void timer1Tick (object sender, EventArgs e)
{
   // Check if mouse is currently over the form
   bool temp_mof = ClientRectangle.Contains(
      Form.MousePosition.X - Location.X,
      Form.MousePosition.Y - Location.Y);

   // were we already over the form before this tick?
   if (temp_mof && m_mouse_over_form)
   {
       // we need to detect the mouse down and up to avoid
       // repeated calls if the mouse button is held down for more
       // than our Tick interval

       // was the mouse button up prior to now?
       if (!m_left_button_down)
       {
           // is the button down now?
           m_left_button_down = (MouseButtons == MouseButtons.Left);

           if (m_left_button_down)
           {
               // the button was down and has now been released
               LeftButtonClickHandler();
           }
           else
           {
               // do nothing, the button has not been release yet
           }
       }
       else
       {
           // update the button state
           m_left_button_down = (MouseButtons == MouseButtons.Left);
       }
   }
   else if (temp_mof)
   {
       // the mouse just entered the form

       m_mouse_over_form = true;

       // set the initial state of the left button
       m_left_button_down = MouseButtons == MouseButtons.Left);
   }
   else
   {
       // the mouse is not currently over the form
       m_mouse_over_form = false;
       m_left_button_down = true;
   }
}
...