Vb.net 如何在不向每个窗体添加代码的情况下为MDI子窗体设置事件?

Vb.net 如何在不向每个窗体添加代码的情况下为MDI子窗体设置事件?,vb.net,winforms,event-handling,mdichild,mdiparent,Vb.net,Winforms,Event Handling,Mdichild,Mdiparent,我想在所有打开的子窗体上为某种类型的控件设置背景色。我有一个MDI父窗体,用于打开自身内的其他窗体。我不想为每个子表单添加代码,因为这将非常广泛。这将被用作应用程序的主题功能,因此我希望它能够根据主窗体中的逻辑自动更改背景颜色。是否有类似全局事件的东西可以触发所有Form.Load事件 到目前为止,我已经在父窗体中创建了一个事件,但它不适用于嵌套控件 Private Sub frmMain_MdiChildActivate(sender As Object, e As EventArgs) Ha

我想在所有打开的子窗体上为某种类型的控件设置背景色。我有一个MDI父窗体,用于打开自身内的其他窗体。我不想为每个子表单添加代码,因为这将非常广泛。这将被用作应用程序的主题功能,因此我希望它能够根据主窗体中的逻辑自动更改背景颜色。是否有类似全局事件的东西可以触发所有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

在父窗体中,保留已激活的所有子窗体的集合。然后可以遍历该集合并更改每个集合的相关控件属性

For Each ChildForm in MyCollection
    ChildForm.TextBox.BackColor = Red
Next
当然:

  • 父窗体必须可以访问子窗体控件
  • 子窗体必须仍然存在(即未在中间关闭 时间)
  • 无法检查子窗体闭包,因为您没有添加任何子窗体闭包 向子窗体发送代码以发出此类事件的信号
  • 当您试图更改 已经关闭了

ChangeColour()
的子窗体设计中包含方法要容易得多,该方法是由事件触发还是直接调用是您的设计决策。并包含一种方法,用于在子窗体死亡时通知父窗体,以便它停止查找它。

在父窗体中,保留已激活的所有子窗体的集合。然后可以遍历该集合并更改每个集合的相关控件属性

For Each ChildForm in MyCollection
    ChildForm.TextBox.BackColor = Red
Next
当然:

  • 父窗体必须可以访问子窗体控件
  • 子窗体必须仍然存在(即未在中间关闭 时间)
  • 无法检查子窗体闭包,因为您没有添加任何子窗体闭包 向子窗体发送代码以发出此类事件的信号
  • 当您试图更改 已经关闭了

ChangeColour()
的子窗体设计中包含方法要容易得多,该方法是由事件触发还是直接调用是您的设计决策。并包含一种方法,用于在子窗体死亡时通知父窗体,以便它停止查找它。

我可以通过使用
form.mdichildactive
并基于
事件和
事件处理程序将事件添加到相应的控件中来完成此操作

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()
会将处理程序分配给该控件及其也将应用于的任何子控件。在本例中,我将
控件.Paint
事件设置为以特定方式绘制
组框。这可能不是实现这一点的最干净的方法,但我能够为所有子窗体创建一个“全局事件”,而不必触及每个窗体上的代码

我可以通过使用
Form.mdichildactive
并基于
事件和
事件处理程序将事件添加到相应的控件中来完成此操作

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()
会将处理程序分配给该控件及其也将应用于的任何子控件。在本例中,我将
控件.Paint
事件设置为以特定方式绘制
组框。这可能不是实现这一点的最干净的方法,但我能够为所有子窗体创建一个“全局事件”,而不必触及每个窗体上的代码

确实有,您试图做什么?创建一个包含所有共享属性值的静态类(VB中的模块)。此外,您还可以继承
表单
,并根据您的需要对其进行自定义needs@Codexer我在父窗体中创建了一个MdiChildActivate事件,该事件为我要在子窗体中更改的每个控件创建一个绘制事件处理程序。问题是这对嵌套控件不起作用。@jonathana我不想在现有窗体中添加任何代码,除了父窗体之外。@jonathana我不想在现有窗体中添加任何代码。如果不想添加任何代码,您打算如何解决此问题?我同意,为共享属性创建一个模块。确实有,您试图做什么?创建一个包含所有共享属性值的静态类(VB中的模块)。此外,您还可以继承
表单
,并根据您的需要对其进行自定义needs@Codexer我在父窗体中创建了一个MdiChildActivate事件,该事件为我要在子窗体中更改的每个控件创建一个绘制事件处理程序。问题是这对嵌套控件不起作用。@jonathana我不想在现有窗体中添加任何代码,除了父窗体之外。@jonathana我不想在现有窗体中添加任何代码。如果不想添加任何代码,您打算如何解决此问题?我同意,为共享属性创建一个模块。这对子窗体是如何工作的?在代码示例中,已将ChildForm设置为控件,而不是窗体。因此,它不会回答您自己的问题(“我想为所有打开的窗体上的某种类型的控件设置背景色。我有一个父窗体,用于打开其他窗体。”)。如果您能演示如何对子窗体进行此操作,我很高兴删除否决票,非子控件。@AJD这适用于所有子窗体,因为它们包含在父窗体中。查看父窗体的活动控件时,您会发现在本例中返回子窗体,因为我们在MdiChildActivate事件处理程序中。使用Form.ActiveControl将子窗体作为控件返回。我已将其更改为Form.ActiveMdiChild,这将返回一个表单,该表单仍然用作AddEventToControls()中的控件。OP中缺少该上下文,我认为子表单是独立于父表单的派生表单。我的另一个印象是,颜色的变化发生在孩子们出生后。添加此上下文和clea