Проблемы с переопределением OnPaint и захватом событий мыши в C # UserControl, содержащем другие элементы управления - PullRequest
2 голосов
/ 25 декабря 2010

Я создал элемент управления, который содержит несколько других элементов управления, таких как PictureBox, Label и TextBox.Но у меня две проблемы:

1. Я пытался нарисовать некоторые вещи поверх моего контроля, и когда я переопределяю OnPaint, это приводит к тому, что я пытаюсьDraw находятся под контролем, который содержит мой контроль.Области, на которых я хотел бы рисовать, пересекаются с элементами управления способами, которые нелегко предсказать.Я имею в виду, что это включает в себя что-то нарисованное на элементах управления внутри, а также на основе контроля.Есть ли простой способ нарисовать что-то поверх всего содержимого моего элемента управления?Установка ForeColor в значение «Прозрачный» не очень помогает мне.

2. У меня проблема с захватом событий щелчка мыши, когда я помещаю свой элемент управления в форму и добавляюобработка событий клика.Это работает только когда я нажимаю на область, не занятую элементами управления внутри.Я хотел бы, чтобы весь элемент управления реагировал на щелчки и другие действия, как если бы это был один последовательный элемент управления.Как я могу перенаправить / обработать эти клики, чтобы они работали так, как я хочу?

Заранее благодарим за любые советы

edit:

Спасибо за ответ, я надеялся на что-то менее сложное.

Наконец я решил сделать это с нуля, нарисовав все необходимые вещи прямо на поверхности моего UserControl, TextBox только появляетсякогда это необходимо.Это решило все мои проблемы с рисованием и событиями.

MTH

1 Ответ

3 голосов
/ 25 декабря 2010

1) Переопределение события OnPaint элемента управления позволяет рисовать на этого элемента управления. Всякий раз, когда этот элемент управления окрашен, ваш код рисования будет выполняться. Тогда , и только тогда, дочерние элементы управления будут нарисованы поверх этого элемента управления, каждый из которых будет выполнять свои собственные OnPaint события. Каждый элемент управления - это свое собственное окно (в смысле Windows API), и поэтому каждый отвечает за рисование своей собственной поверхности. Это объясняет, почему ваша графика закрыта дочерними элементами управления, и почему они видны только в пустых местах, где дочерние элементы управления не размещены.

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

Первым возможным взломом является рисование вашей графики на контроле контейнера, как вы уже сделали, а затем также рисование поверх самих дочерних элементов управления . Однако для того, чтобы это работало, вам нужно переопределить событие OnPaint каждого дочернего элемента управления, что сразу же вызывает проблему. Элемент управления TextBox (вместе с ComboBox, ListView, TreeView и несколькими другими элементами управления) не выполняет рисование в событии OnPaint; это изначально нарисовано операционной системой. Возможные обходные пути для этого настолько болезненны, что вы можете забыть об этом и изменить свой дизайн.

Второй возможный хак - это добавление другого элемента управления, который находится поверх элемента управления контейнера, и рисование на его поверхности. Возможно, самый простой способ сделать это - создать нечто вроде прозрачной панели, используя расширенный стиль окна WS_EX_TRANSPARENT:

public class TransparentPanel : Panel
{
    protected override CreateParams CreateParams
    {
        get
        {
            const int WS_EX_TRANSPARENT = 0x00000020;

            CreateParams cp = base.CreateParams;
            cp.ExStyle |= WS_EX_TRANSPARENT
            return cp;
        }
    }

    protected override void OnPaintBackground(PaintEventArgs e)
    {
        //Do nothing
    }
}

2) Опять же, становится уместным, что каждый дочерний элемент управления является собственным окном и обрабатывает свои собственные события ввода мыши. Вот почему элемент управления, событие которого MouseClick, которое вы переопределили, обнаруживает только те щелчки, которые происходят непосредственно на его поверхности. Другие щелчки передаются дочерним элементам управления, которые просто игнорируют их. События в WinForms не всплывают в иерархии элементов управления.

Как и раньше, одним из возможных решений является обработка события MouseClick (и любых других, которые вы хотите) для дочерних элементов управления и контейнера. Если вы решите пойти по этому пути, думаю, я бы порекомендовал объединить вашу логику в одну подпрограмму и просто вызывать эту подпрограмму из обработчика событий каждого элемента управления.

Если вы ищете что-то более всеобъемлющее, вы можете проверить Трансляция событий через управляющую иерархию , хотя я не потратил время на ее чтение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...