Вопрос

У меня проблема с MouseEvents в моем приложении WinForm C#.

я хочу получить все щелкает мышью по моему приложению, но я не хочу помещать прослушиватель в каждый дочерний компонент и не использовать крючок мыши Windows.

Во Flash я мог бы поместить прослушиватель на сцену, чтобы получить все события MouseEvents в фильме.

Есть ли такое на С#?Глобальный MouseListener?


Редактировать:

Я создаю этот класс из IMessageFilter и использую Application.AddMessageFilter.

public class GlobalMouseHandler : IMessageFilter{

    private const int WM_LBUTTONDOWN = 0x201;

    public bool PreFilterMessage(ref Message m){
        if (m.Msg == WM_LBUTTONDOWN) {
            // Do stuffs
        }
        return false;
    }
}

И поместите этот код в элементы управления, которым необходимо прослушивать глобальные клики:

GlobalMouseHandler globalClick = new GlobalMouseHandler();
Application.AddMessageFilter(globalClick);
Это было полезно?

Решение

Один из простых способов сделать это — добавить фильтр цикла сообщений, вызвав Application.AddMessageFilter и написание класса, который реализует IMessageFilter интерфейс.

С помощью IMessageFilter.PreFilterMessage, ваш класс сможет видеть любые входные сообщения, которые проходят через цикл сообщений вашего приложения. PreFilterMessage также решает, передавать ли эти сообщения конкретному элементу управления, которому они предназначены.

Одна из сложностей, которую представляет этот подход, связана с необходимостью иметь дело с сообщениями Windows через структуру Message, передаваемую вашему PreFilterMessage метод.Это означает обращение к документации Win32 по WM\_LBUTTONDOWN, WM\_MOUSEMOVE, WM\_LBUTTONUP и т. д., вместо обычного MouseDown, MouseMove и MouseUp события.

Другие советы

Пример класса

class CaptureEvents : IMessageFilter
{
    #region IMessageFilter Members
    public delegate void Callback(int message);
    public event Callback MessageReceived;

    IntPtr ownerWindow;
    Hashtable interestedMessages = null;
    CaptureEvents(IntPtr handle, int[] messages)
    {
        ownerWindow = handle;
        for(int c = 0; c < messages.Length ; c++)
        {
            interestedMessages[messages[c]] = 0;
        }
    }
    public bool PreFilterMessage(ref Message m)
    {
        if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg))
        {
            MessageReceived(m.Msg);
        }
        return true;
    }

    #endregion
}

Взгляните на эту статью.Он рекурсивно перехватывает все управляющие события и транслирует их.Вы также можете переопределить ВндПрок в вашей форме.

Если вы не хотите обрабатывать сообщения путем переопределения Form.PreProcessMessage или Form.WndProc, вы можете создать подкласс Form, чтобы подключить обработчик событий ко всем событиям MouseClick из различных элементов управления в форме.
РЕДАКТИРОВАТЬ:забыл рекурсивно пройти через дочерние элементы управления в форме.

    public class MousePreviewForm : Form
    {
      protected override void OnClosed(EventArgs e)
      {
         UnhookControl(this as Control);
         base.OnClosed(e);
      }

      protected override void OnLoad(EventArgs e)
      {
         base.OnLoad(e);

         HookControl(this as Control);
      }

      private void HookControl(Control controlToHook)
      {
         controlToHook.MouseClick += AllControlsMouseClick;
         foreach (Control ctl in controlToHook.Controls)
         {
            HookControl(ctl);
         }      
      }

      private void UnhookControl(Control controlToUnhook)
      {
         controlToUnhook.MouseClick -= AllControlsMouseClick;
         foreach (Control ctl in controlToUnhook.Controls)
         {
            UnhookControl(ctl);
         }
      }

      void AllControlsMouseClick(object sender, MouseEventArgs e)
      {
         //do clever stuff here...
         throw new NotImplementedException();
      }
   }

Тогда ваши формы должны быть производными от MousePreviewForm, а не от System.Windows.Forms.Form.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top