понедельник, 17 марта 2014 г.

Создаем обработчик событий уровня приложения.

Иногда бывает необходимо отлавливать события внутри приложения вне зависимости от того, какой контрол активен. Например, вы хотите реализовать аналог "IDDQD" в своем приложении ;))) Или просто хотите обрабатывать события по каким-то своим законам. Сегодня я расскажу вас как это сделать.

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

    
    public delegate void MouseWheelEvent(int rotation);
    public delegate void KeyDownEvent(int keyCode);

    public class GlobalEventHandler : IMessageFilter
    {
        public event MouseWheelEvent TheMouseWheel;
        public event KeyDownEvent TheKeyDown;

        public bool PreFilterMessage(ref Message m)
        {

        }

    }
следующий этап - реализовать метод PreFilterMessage:



        public bool PreFilterMessage(ref Message m)
        {
            //WM_MOUSEWHEEL
            if (m.Msg == 0x20A)
            {
                if (TheMouseWheel != null)
                {
                    try
                    {
                        TheMouseWheel(m.WParam.ToInt32());
                    }
                    catch { }
                    //возвращаем true, чтобы предотвратить дальнейшую обработку события                
                    return true;
                }
            }
            //WM_KEYDOWN
            else if (m.Msg == 0x100)
            {
                if (TheKeyDown != null)
                {
                    try
                    {
                        TheKeyDown(m.WParam.ToInt32());
                    }
                    catch { }
                    //еcли дальнейшую обработку предотвращать не нужно, то возвращаем false
                    //в таком случае, и вы будете знать о нажатии клавиши, и, например, textbox получит событие нажатия
                    return false;
                }
            }
            return false;
        }

Внутри этого метода вы можете отлавливать какие угодно события. Вот тут их относительно полный список ( http://msdn.microsoft.com/en-us/library/ms644927%28v=VS.85%29.aspx#system_defined )
Ну и последний этап - нам надо написать методы обработчиков событий. Обратите внимание на строчку получения смещения из параметра delta. В сообщении WM_MOUSEWHEEL смещение прокрутки колеса находится в старшем слове параметра. Так, что, нам нужно сдвинуть его значение вправо и обрезать до short. Это я к тому, что внимательнее читайте описание сообщений
        public void WheelRotate(int delta)
        {
            short realRotateDelta = ((short)(delta >> 16));
            textBox1.Text += realRotateDelta.ToString() + Environment.NewLine;            
        }

        public void KeyPressed(int keyCode)
        {
            textBox1.Text += keyCode.ToString() + Environment.NewLine;
        }

И, добавить ваш фильтр в очередь обработки сообщений приложения. Делать это нужно в Form_Load
        private void Form1_Load(object sender, EventArgs e)
        {
            GlobalEventHandler geh = new GlobalEventHandler();
            geh.TheMouseWheel += new MouseWheelEvent(WheelRotate);
            geh.TheKeyDown += new KeyDownEvent(KeyPressed);
            Application.AddMessageFilter(geh);
        }

Вот и все.

Комментариев нет:

Отправить комментарий