Переопределение WndProc, чтобы увидеть, когда пользователь нажимает любой элемент управления на форме в C#

Метод WndProc формы обрабатывает сообщения, отправленные в форму операционной системой Windows. Это чрезвычайно важный метод, который позволяет формам перемещаться, изменять размер, перерисовывать и выполнять другие критические операции. Хотя обычно вам не нужно менять реализацию по умолчанию WndProc, вы можете переопределить значение по умолчанию WndProc, чтобы заставить его выполнять специальные действия. В этом примере используется следующий код для обнаружения, когда пользователь нажимает на любой элемент управления, содержащийся в форме.

// Ищите сообщения WM_MOUSEACTIVATE.
protected override void WndProc(ref Message m)
{
    // Ищите WM_MOUSEACTIVATE.
    const UInt32 WM_MOUSEACTIVATE = 0x0021;
    if (m.Msg == WM_MOUSEACTIVATE)
    {
        // Смотрите, где находится мышь.
        Point screen_coords = Cursor.Position;

        // Начнем смотреть на детей формы.
        Control ctl = this;
        for (; ; )
        {
            // Преобразуем позицию мыши в
            // система координат элемента управления.
            Point ctl_coords = ctl.PointToClient(screen_coords);

            // Посмотрим, есть ли ребенок в этой позиции.
            Control child = ctl.GetChildAtPoint(
                ctl_coords, GetChildAtPointSkip.Invisible);
            if (child == null) break;

            // Поиск ребенка.
            ctl = child;
        }

        // Покажите самый внутренний элемент управления в этой точке.
        txtControl.Text = ctl.Name;
    }

    base.WndProc(ref m);
}

Объявлен метод, который переопределяет реализацию по умолчанию WndProc.

Сначала метод проверяет параметр Message метода, чтобы узнать, есть ли сообщение WM_MOUSEACTIVATE, указывающее, что элемент управления был нажат.

Если он видит это сообщение, код получает позицию курсора мыши. Затем он будет использовать метод GetChildAtPoint, чтобы узнать, какой элемент управления находится в местоположении мыши, но есть два осложнения для этого подхода. Во-первых, элемент управления, содержащийся в контейнере в форме, не является прямым дочерним элементом формы. Например, в этой программе label3 содержится в groupBox2, который содержится в tabPage1, который содержится в tabControl1 , которое содержится в форме. Если вы нажмете label3, это не является прямым дочерним элементом формы, поэтому GetChildAtPoint не найдет его. Вместо этого он найдет tabControl1, потому что это элемент управления, содержащийся непосредственно в форме.

Второе осложнение возникает, когда один элемент управления находится над другим. В этом примере две вкладки расположены друг над другом. Если вы выберете вторую вкладку и затем щелкните по ней, GetChildAtPoint вернет первую вкладку, потому что она находится в одной и той же точке, и метод встречает эту страницу сначала в своем поиске.

Чтобы решить эти проблемы, код начинается с установки переменной ctl в форму. Обратите внимание, что форма является специальным типом Control, поэтому вы можете установить переменную ctl равной форме.

Далее код вводится в бесконечный цикл. Он вызывает метод PointToClient текущего элемента управления, чтобы преобразовать позицию мыши из экранных координат в систему координат элемента управления. Затем программа вызывает метод GetChildAtPoint элемента управления, чтобы узнать, какой дочерний элемент управления находится в этой позиции мыши. Он передает этот метод параметру GetChildAtPointSkip.Invisible, чтобы он не учитывал скрытые дочерние элементы управления. Это позволяет GetChildAtPoint возвращать правильный элемент управления, когда один элемент управления закрывает другой.

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

Если код находит дочерний элемент управления в позиции мыши, он обновляет ctl, чтобы ссылаться на вновь обнаруженное дочернее управление и продолжает цикл. Код продолжается так, преобразуя положение мыши в систему координат текущего элемента управления и используя GetChildAtPoint, чтобы узнать, содержится ли позиция дочерним элементом управления. Код проходит по иерархии элементов управления до тех пор, пока не найдет тот, у которого нет дочернего элемента, который содержит положение мыши.

После выхода из цикла код отображает имя найденного элемента управления.

Источник: http://csharphelper.com/blog/2016/11/override-wndproc-to-see-when-the-user-clicks-any-control-on-a-form-in-c/

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Adblock
detector