如何列出其他表单的所有计时器

时间:2017-07-06 11:07:07

标签: vb.net winforms timer components

我想创建一个程序来阻止任何给定表单的所有计时器。虽然在建造它时说

  

"组分'不是System.Windows.Forms.Form"。

的成员

以下是代码:

yyyymmdd_textbox1(.txt)

2 个答案:

答案 0 :(得分:1)

您可以使用反射:

Public Sub StopTimers(Form As Form)
    For Each Item In Form.GetType.GetFields(Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public).Where(Function(x) TypeOf x.GetValue(Form) Is Timer)
        Dim Timer As Timer
        Timer = Item.GetValue(Form)
        Timer.Stop()
    Next
End Sub

答案 1 :(得分:1)

正如我在评论中更正的那样,Controls集合不包含组件 - 它只包含控件。对非可视组件(如计时器)的引用保存在私有Container字段中,通常称为componentsContainer字段根本不是基本Form类的一部分。它由表单设计者在需要它的每个表单上单独声明和实现。由于它不是基类的成员,因此没有简单的方法可以在任何给定的表单上访问它。即使它是基类的成员,可访问性仍然是一个问题,因为它通常被声明为私有字段。

保持正确类型检查的安全方法是创建一个接口:

Public Interface IFormWithComponents
    ReadOnly Property Components As ComponentCollection
End Interface

然后您可以在每个表单上实施,如适用:

Public Class MyForm
    Implements IFormWithComponents

    Public ReadOnly Property Components As ComponentCollection Implements IFormWithComponents.Components
        Get
            Return components.Components
        End Get
    End Property
End Class

然后你的计时器停止方法可以将该接口作为其参数:

Public Sub _Timers_Stop(frm As IFormWithComponents)
    For Each t As Timer In frm.Components.Cast(Of Component).OfType(Of Timer)
       t.stop()
    Next
End Sub

但是,如果您真的不关心类型检查,并且不介意性能略有下降,您可以使用反射来查找表单对象中的私有字段并提取其值: / p>

Public Sub _Timers_Stop(frm As Form)
    Dim timers As IEnumerable(Of Timer) = frm.
        GetType().
        GetFields(BindingFlags.FlattenHierarchy Or BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public).
        Select(Function(fieldInfo) fieldInfo.GetValue(frm)).
        OfType(Of Container)().
        SelectMany(Function(container) container.Components.OfType(Of Timer)())
    For Each t As Timer In timers
        t.Stop()
    Next
End Sub