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-функцию . Но я оставлю это как упражнение для читателя, потому что я чувствую, что вы задали простой вопрос, ожидая простого ответа.