Как установить событие для дочерних форм MDI без добавления кода в каждую форму?

Я хотел бы установить цвет фона для определенного типа элемента управления для всех открываемых дочерних форм. У меня есть форма MdiParent, которая используется для открытия других форм внутри себя. Я не хочу добавлять код в каждую дочернюю форму, так как это было бы очень обширно. Это будет использоваться в качестве функции темы для приложения, поэтому я хотел бы, чтобы оно автоматически меняло цвета фона на основе логики в основной форме. Есть ли что-то вроде глобального события, которое может срабатывать для всех событий Form.Load?

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

Private Sub frmMain_MdiChildActivate(sender As Object, e As EventArgs) Handles Me.MdiChildActivate
    Dim ParentControl As frmMain = sender
    Dim ChildControl = ParentControl.ActiveControl

    If ChildControl IsNot Nothing Then
        For Each FormControl As Control In ChildControl.Controls
            If FormControl.GetType = GetType(GroupBox) Then
                RemoveHandler FormControl.Paint, AddressOf PaintBorderlessGroupbox
                AddHandler FormControl.Paint, AddressOf PaintBorderlessGroupbox
            End If
        Next
    End If

End Sub

person Programmer    schedule 05.02.2018    source источник
comment
Конечно есть, что вы пытались сделать?   -  person zaggler    schedule 05.02.2018
comment
создайте статический класс (модуль в VB), который будет содержать все значения общих свойств. также вы также можете наследовать от Form и настроить его в соответствии с вашими потребностями   -  person jonathana    schedule 05.02.2018
comment
@Codexer Я создал событие MdiChildActivate в родительской форме, которое создает обработчик событий Paint для каждого элемента управления, который я хочу изменить в дочерней форме. Проблема в том, что это не работает для вложенных элементов управления.   -  person Programmer    schedule 05.02.2018
comment
@jonathana Я не хочу добавлять какой-либо код в существующие формы, кроме родительской формы   -  person Programmer    schedule 05.02.2018
comment
Если вы не хотите добавлять какой-либо код, как вы планируете решить проблему? Я согласен, сделать модуль для общих свойств.   -  person Jacob H    schedule 05.02.2018
comment
@programmer Хорошо, когда я увижу ваш код, я лучше пойму ваш вопрос ... если вы найдете, как это сделать, не добавляя код в существующие файлы, дайте мне знать (без сарказма).   -  person jonathana    schedule 05.02.2018
comment
@JacobH Вот почему я прошу совета.   -  person Programmer    schedule 05.02.2018
comment
@jonathana Я смог сделать это на основе того, что я опубликовал. Код находится в ответе ниже.   -  person Programmer    schedule 06.02.2018


Ответы (2)


Я смог добиться этого, используя Form.MdiChildActivate и добавив событие в соответствующие элементы управления на основе Event и EventHandler.

Private Sub frmMain_MdiChildActivate(sender As Object, e As EventArgs) Handles Me.MdiChildActivate
    Dim ParentForm As frmMain = sender
    Dim ChildForm = ParentForm.ActiveMdiChild
    Dim EventName = "Paint"
    Dim EventHandlerName = "PaintBorderlessGroupBox"

    If ChildForm IsNot Nothing Then
        AddEventToControls(ChildForm, GetType(GroupBox), EventName, EventHandlerName)
    End If
End Sub

Private Sub AddEventToControls(Control As Control, ControlType As Type, ControlEventName As String, ControlEventMethod As String)
    For Each ChildControl In Control.Controls
        If ChildControl.GetType = ControlType Then

            If ChildControl.Controls.Count > 0 Then
                AddEventToControls(ChildControl, ControlType, ControlEventName, ControlEventMethod)
            End If

            Dim EventMethod = Me.GetType().GetMethod(ControlEventMethod, BindingFlags.NonPublic Or BindingFlags.Instance)
            Dim ControlEvent As EventInfo = ControlType.GetEvent(ControlEventName)
            Dim del = [Delegate].CreateDelegate(ControlEvent.EventHandlerType, Me, EventMethod)

            ControlEvent.RemoveEventHandler(ChildControl, del)
            ControlEvent.AddEventHandler(ChildControl, del)
        End If
    Next
End Sub

Вызов AddEventToControls() назначает обработчик элементу управления и любым дочерним элементам управления, к которым он также будет применяться. В этом случае я устанавливаю событие Control.Paint для рисования GroupBox определенным образом. Возможно, это не самый чистый метод для достижения этой цели, но мне удалось создать «Глобальное событие» для всех дочерних форм, даже не касаясь кода в каждой форме.

person Programmer    schedule 05.02.2018
comment
Как это работает для дочерних форм? В вашем примере кода вы установили ChildForm в элемент управления, а не в форму. Таким образом, он не отвечает на ваш собственный вопрос (Я хотел бы установить цвет фона для определенного типа элемента управления во всех открываемых формах. У меня есть родительская форма, которая используется для открытия других форм.). С удовольствием удалим минус, если вы можете показать, как это работает для дочерних форм, а не для дочерних элементов управления. - person AJD; 06.02.2018
comment
@AJD Это работает для всех дочерних форм, поскольку они содержатся в родительской форме. При просмотре активных элементов управления для родительской формы вы обнаружите, что в этом случае возвращается дочерняя форма, потому что мы находимся в обработчике событий MdiChildActivate. Использование Form.ActiveControl возвращает дочернюю форму как элемент управления. Я изменил его на Form.ActiveMdiChild, и это возвращает форму, которая все еще используется в качестве элемента управления в AddEventToControls(). - person Programmer; 06.02.2018
comment
этот контекст отсутствовал в ОП, у меня сложилось впечатление, что дочерние формы были порожденными формами, независимыми от родителя. Другое впечатление, которое у меня сложилось, заключалось в том, что изменение цвета произошло после появления детей. Добавление этого контекста и четкого объяснения того, что вы сказали выше, к вашему ответу поможет будущим исследователям. Тогда я думаю, что ответ полезен. - person AJD; 06.02.2018
comment
@AJD Я согласен, что контекст отсутствовал. Я изменил OP, чтобы отразить взаимосвязь между формами и добавить ясности, что это для MdiForms. - person Programmer; 06.02.2018
comment
ОК - теперь понятнее. Вы думали, как вы могли бы сделать это для форм, которые уже были загружены? - person AJD; 07.02.2018

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

For Each ChildForm in MyCollection
    ChildForm.TextBox.BackColor = Red
Next

Конечно:

  • Элемент управления ChildForm должен быть доступен родительской форме.
  • ChildForm все еще должен существовать (т.е. не был закрыт в то же время)
  • Вы не можете проверить закрытие ChildForm, потому что вы не добавляете никакого кода в ChildForm, чтобы сигнализировать о таком событии.
  • Вы должны обрабатывать исключения, когда пытаетесь изменить закрытую форму.

Гораздо проще включить метод в ваш дизайн ChildForm для ChangeColour(), независимо от того, запускается ли этот метод событием или прямым вызовом, это ваше дизайнерское решение. И включить метод, сообщающий родительской форме, когда ChildForm умирает, чтобы она перестала его искать.

person AJD    schedule 05.02.2018