Name des Timers-Control zur Laufzeit auslesen

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Name des Timers-Control zur Laufzeit auslesen

    Hallo,

    ich habe in meinem Projekt 2 Timer in die Form gezogen, das heiß die Timer landen ja nicht auf der Form sondern "unterhalb" der Form.
    Daher finde ich zur Laufzeit die Timer nicht unter den Controls sondern unter den Components.

    Ich würde gern zur Laufzeit bei einem Timer das Interval ändern, aber abhängig vom Name.
    Daher habe ich mir die folgende Schleife gebastelt, allerdings gibt es die Eigenschaft Name bei Timern nicht.

    In Zeile 9 kommt dann der Fehler "Name ist kein Member von Timer"
    Gibt es eine Möglichkeit an den Namen ran zu kommen?

    VB.NET-Quellcode

    1. Dim t As System.Windows.Forms.Timer
    2. Dim i As Integer
    3. For i = 0 To Me.components.Components.Count - 1
    4. Select Case Me.components.Components.Item(i).GetType.ToString
    5. Case "System.Windows.Forms.Timer"
    6. t = CType(Me.components.Components.Item(i), System.Windows.Forms.Timer)
    7. If t.name = "Timer2" Then
    8. t.Interval = 200
    9. End If
    10. End Select
    11. Next i


    03.06.: Edit kleine Korrektur im Code...

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „SoEinVBler“ ()

    SoEinVBler schrieb:

    Gibt es eine Möglichkeit an den Namen ran zu kommen?
    Verwende den von Dir vorgegebenen Namen:

    VB.NET-Quellcode

    1. Timer2.Interval = 42
    Feddich
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    naja das ich den Timer natürlich im Code so ansprechen kann ist mir schon klar.
    Es soll aber dynamisch sein, und nicht fest im Code verankert.

    im Prinzip geht es darum, dass ich mir mehrere Eigenschaften in einer Datei speicher und diese dann über den Namen des Controls beim Start zuweise.
    (Ich weiß man kann so was über Settings machen, hab da aber meine eigene Routine erstellt)

    Bei "normalen" Controls kann ich den Namen einfach auslesen und über diesen dann die Eigenschaften zuweisen.
    Beim Timer bekomme ich den Namen nicht, da behelfe ich mir gerade damit, den Namen in die Eigenschaft "TAG" zu schreiben und wieder aus zu lesen.
    Ist aber ein Workaround und würde es natürlich wie bei den anderen Controls gleich machen wollen.

    SoEinVBler schrieb:

    Es soll aber dynamisch sein
    Wie viele unterschiedliche Programme greifen auf diese Settings zu?
    Wie viele verschiedene Timer hast Du denn in dieser GUI?
    Mach Dir eine Liste aller Deiner Timer und und speichere dann deren Index ab.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Naja mit Reflection kann man alles mögliche auslesen und auch hacken.
    Grad dafür sind streng typisierte Hochsprachen erfunden worden, dass man sowas nicht tut.
    Aber ich vermute, dass SoEinVbler so ein Vbler ist, der über den langen schweren Weg drauf kommen muss, wenn überhaupt.
    Also: Reflection ist dein (zweifelhafter) Froind.
    Object.Gettype, Type.GetProperty, PropertyInfo.GetValue, usw ... - lauter ziemlich kryptisches Zeugs.

    Weiters könnte ich mir vorstellen, dass malwieder Controls zur Datenhaltung missbraucht werden - aber ist auch nur eine Vermutung.

    Also schliesse mich RFGs Frage an: Um wieviele Timer gehts?
    Und ausserdem: Um wieviele Controls gehts?
    Hallo,

    auf die Settings greift immer nur ein Programm zu, jedes Programm bekommt seine eigenen Settings.
    Aktuell sind es nur 2 Timer (von 3) bei denen ich mir das Intervall in eine Datei speicher, um sie leichter, also nicht im Code, ändern zu können.

    An sich geht es um 20-30 Controls die ich so mit den Settings fülle.
    Das ich da mit sehr kryptischem Zeug unterwegs bin, hab ich mir schon gedacht.

    Ich stelle hier mal mein Bespiel Code rein, wenn sich den jemand antun möchte.
    Einmal der Code der Form, und die Routinen für das Lesen und Speicher der Optionen.

    Das Prinzip basiert darauf, dass ich bei den Controls in die Eigenschaft ".TAG" ein Vermerk rein setzte ("mkO").
    Dieser Vermerk wird zum identifizieren des Controls benutzt.
    Parallel gibt es dann dazu eine Enum-Auflistung mit dem Namen des Controls und ein Dictonary in dem ich die Daten speichere.


    Ich vermute mal dass ich in euren Augen da ziemlich viel "Unsinn" mache.
    Zudem arbeite ich viel mit Enum und Dictionarys was es sicher noch kryptischer macht.
    Das wäre dann irgendwann die nächste Frage gewesen wie man so was einfach umsetzt.



    Form:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Sub New()
    3. StandardEinstellungen()
    4. ' Dieser Aufruf ist für den Designer erforderlich.
    5. InitializeComponent()
    6. ' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
    7. OptionenLesen()
    8. End Sub
    9. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    10. FormFuellenControls(Me.Controls)
    11. FormFuellennComponents(Me.components)
    12. End Sub
    13. Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    14. FormLesenControls(Me.Controls)
    15. FormLesenComponents(Me.components)
    16. OptionenSchreiben()
    17. End Sub
    18. End Class



    Routine für Optionen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Reflection.MethodBase
    2. Module Optionen
    3. Enum OptionenNamen As Byte
    4. ' Optionen die gespeichert werden
    5. TextBox1
    6. Timer1
    7. End Enum
    8. Public mOptionen As New Dictionary(Of OptionenNamen, String)
    9. Public Const mkO = "mkO"
    10. Dim Trennzeichen() As Char = "\".ToCharArray
    11. Public Sub StandardEinstellungen()
    12. ' Wichtig dass alle Optionen die benötigt werden auch hier mit Standard-Werten befüllt wird, sonnst kann es zu Problemen kommen.
    13. ' Wenn die Datei mit den Optionen nicht vorhanden ist wird sonst die Option nicht erzeugt, und kann auch nicht abgerufen werden.
    14. mOptionen(OptionenNamen.TextBox1) = ""
    15. mOptionen(OptionenNamen.Timer1) = "1500"
    16. End Sub
    17. Public Sub OptionenLesen()
    18. Dim userAppDatePfad As String = Environment.GetEnvironmentVariable("LOCALAPPDATA")
    19. Dim UnterPfad As String = Application.ProductName & "\"
    20. userAppDatePfad += If(userAppDatePfad.EndsWith("\"), "", "\")
    21. Dim myFileInfo As New IO.FileInfo(Application.StartupPath & "\" & Application.ProductName & ".dat") ' Optionen im Ordner der Exe
    22. 'Dim myFileInfo As New IO.FileInfo(userAppDatePfad & UnterPfad & Application.ProductName & ".dat") ' Optionen für jeden User extra
    23. If myFileInfo.Exists Then
    24. Dim s As String
    25. Using fs As IO.FileStream = myFileInfo.Open(IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.ReadWrite)
    26. Using sr As New IO.StreamReader(fs, System.Text.Encoding.UTF8)
    27. While Not sr.EndOfStream
    28. s = sr.ReadLine
    29. Dim x() As String = s.Split(Trennzeichen, 2)
    30. Dim a As OptionenNamen
    31. If OptionenNamen.TryParse(x(0), a) Then
    32. mOptionen(a) = x(1)
    33. End If
    34. End While
    35. sr.Close()
    36. sr.Dispose()
    37. End Using
    38. fs.Dispose()
    39. End Using
    40. End If
    41. End Sub
    42. Public Sub OptionenSchreiben()
    43. Dim userAppDatePfad As String = Environment.GetEnvironmentVariable("LOCALAPPDATA")
    44. Dim UnterPfad As String = Application.ProductName & "\"
    45. userAppDatePfad += If(userAppDatePfad.EndsWith("\"), "", "\")
    46. Dim myFileInfo As New IO.FileInfo(Application.StartupPath & "\" & Application.ProductName & ".dat") ' Optionen im Ordner der Exe
    47. 'Dim myFileInfo As New IO.FileInfo(userAppDatePfad & UnterPfad & Application.ProductName & ".dat") ' Optionen für jeden User extra
    48. If Not myFileInfo.Directory.Exists Then
    49. myFileInfo.Directory.Create()
    50. End If
    51. Using fs As IO.FileStream = myFileInfo.Open(IO.FileMode.Create, IO.FileAccess.Write)
    52. Using sw As New IO.StreamWriter(fs, System.Text.Encoding.UTF8)
    53. For Each x In mOptionen
    54. sw.WriteLine(OptionenNamen.GetName(GetType(OptionenNamen), x.Key) & Trennzeichen & x.Value)
    55. Next
    56. sw.Close()
    57. sw.Dispose()
    58. End Using
    59. fs.Dispose()
    60. End Using
    61. End Sub
    62. Public Sub FormFuellenControls(Controls As System.Windows.Forms.Control.ControlCollection)
    63. Dim o As Object
    64. Dim sTag As String
    65. Dim sNachricht As String = ""
    66. For Each o In Controls
    67. If o.tag IsNot Nothing Then
    68. sTag = o.tag
    69. If sTag.Contains(mkO) Then
    70. Dim a As OptionenNamen
    71. If OptionenNamen.TryParse(o.name, a) Then
    72. If mOptionen.ContainsKey(a) Then
    73. Select Case o.GetType().ToString
    74. Case "System.Windows.Forms.TextBox", "System.Windows.Forms.NumericUpDown", "System.Windows.Forms.Label"
    75. o.Text = mOptionen(a)
    76. Case "System.Windows.Forms.ComboBox"
    77. Dim s() As String ' Es könnte auch der Inhalt des Dropdown-Felds gespeichert und gefüllt werden
    78. Dim cbx As ComboBox = o
    79. s = mOptionen(a).Split("@".ToCharArray)
    80. If s.Length > 1 Then
    81. cbx.Items.Clear()
    82. cbx.Items.AddRange(s(1).Split(";".ToCharArray))
    83. cbx.Text = s(0)
    84. End If
    85. Case "System.Windows.Forms.CheckBox"
    86. o.checked = mOptionen(a)
    87. Case "System.Windows.Forms.TrackBar"
    88. If mOptionen(a) < o.maximum AndAlso mOptionen(a) > o.minimum Then
    89. o.value = mOptionen(a)
    90. Else
    91. End If
    92. Case "System.Windows.Forms.DataGridView"
    93. Dim zeile() As String = mOptionen(a).Split(";")
    94. For i As Integer = 0 To zeile.Count - 2
    95. Dim c() As String = zeile(i).Split(",")
    96. o.rows.add(i + 1, c(0), c(1), c(2) = "1")
    97. Next
    98. Case Else
    99. sNachricht = sNachricht & "Der Typ " & o.GetType().ToString & " wurde noch nicht abgefangen" & Environment.NewLine
    100. End Select
    101. Else
    102. sNachricht = sNachricht & "Schlüssel " & a.ToString & " fehlt in Standardeinstellungen" & Environment.NewLine
    103. End If
    104. Else
    105. sNachricht = sNachricht & o.name & " fehlt in Enumauflistung " & Environment.NewLine
    106. End If
    107. End If
    108. End If
    109. If o.controls.count Then
    110. FormFuellenControls(o.controls)
    111. End If
    112. Next
    113. If sNachricht.Length Then MessageBox.Show(sNachricht, GetCurrentMethod.Name)
    114. End Sub
    115. Public Sub FormLesenControls(Controls As System.Windows.Forms.Control.ControlCollection)
    116. Dim o As Object
    117. Dim sTag As String
    118. Dim sNachricht As String = ""
    119. For Each o In Controls
    120. If o.tag IsNot Nothing Then
    121. sTag = o.tag
    122. If sTag.Contains(mkO) Then
    123. Dim a As OptionenNamen
    124. If OptionenNamen.TryParse(o.name, a) Then
    125. Select Case o.GetType().ToString
    126. Case "System.Windows.Forms.TextBox", "System.Windows.Forms.NumericUpDown", "System.Windows.Forms.Label"
    127. mOptionen(a) = o.Text
    128. Case "System.Windows.Forms.ComboBox"
    129. Dim cbx As ComboBox = o
    130. mOptionen(a) = cbx.Text & "@" & String.Join(";", cbx.Items.OfType(Of String)) ' Es könnte auch der Inhalt des Dropdown-Felds gespeichert und gefüllt werden
    131. Case "System.Windows.Forms.CheckBox"
    132. mOptionen(a) = o.checked
    133. Case "System.Windows.Forms.TrackBar"
    134. mOptionen(a) = o.value
    135. Case "System.Windows.Forms.DataGridView"
    136. Dim s As String = ""
    137. For r As Integer = 0 To o.rows.count - 1
    138. For c As Integer = 1 To 3
    139. s = s & Math.Abs(Convert.ToInt32(o.rows(r).cells(c).value)) & ","
    140. Next
    141. s = s.Substring(1, s.Length - 1) & ";"
    142. Next
    143. mOptionen(a) = s
    144. Case Else
    145. sNachricht = sNachricht & "Der Typ " & o.GetType().ToString & " wurde noch nicht abgefangen" & Environment.NewLine
    146. End Select
    147. End If
    148. End If
    149. End If
    150. If o.controls.count Then
    151. FormLesenControls(o.controls)
    152. End If
    153. Next
    154. If sNachricht.Length Then MessageBox.Show(sNachricht, GetCurrentMethod.Name)
    155. End Sub
    156. Public Sub FormFuellennComponents(Komponenten As System.ComponentModel.Container)
    157. Dim o As Object
    158. Dim sTag As String
    159. Dim sNachricht As String = ""
    160. Dim x() As String
    161. For Each o In Komponenten.Components
    162. If o.tag IsNot Nothing Then
    163. sTag = o.tag
    164. x = sTag.Split(",".ToCharArray, 2)
    165. If x.Count > 1 AndAlso x(1).Contains(mkO) Then
    166. Dim a As OptionenNamen
    167. If OptionenNamen.TryParse(x(0), a) Then
    168. If mOptionen.ContainsKey(a) Then
    169. Select Case o.GetType().ToString
    170. Case "System.Windows.Forms.Timer"
    171. o.interval = mOptionen(a)
    172. Case Else
    173. sNachricht = sNachricht & "Der Typ " & o.GetType().ToString & " wurde noch nicht abgefangen" & Environment.NewLine
    174. End Select
    175. Else
    176. sNachricht = sNachricht & "Schlüssel " & a.ToString & " fehlt in Standardeinstellungen" & Environment.NewLine
    177. End If
    178. Else
    179. sNachricht = sNachricht & x(0) & " fehlt in Enumauflistung " & Environment.NewLine
    180. End If
    181. End If
    182. End If
    183. Next o
    184. If sNachricht.Length Then MessageBox.Show(sNachricht, GetCurrentMethod.Name)
    185. End Sub
    186. Public Sub FormLesenComponents(Komponenten As System.ComponentModel.Container)
    187. Dim o As Object
    188. Dim sTag As String
    189. Dim sNachricht As String = ""
    190. Dim x() As String
    191. For Each o In Komponenten.Components
    192. If o.tag IsNot Nothing Then
    193. sTag = o.tag
    194. x = sTag.Split(",".ToCharArray, 2)
    195. If x.Count > 1 AndAlso x(1).Contains(mkO) Then
    196. Dim a As OptionenNamen
    197. If OptionenNamen.TryParse(x(0), a) Then
    198. Select Case o.GetType().ToString
    199. Case "System.Windows.Forms.Timer"
    200. mOptionen(a) = o.interval
    201. Case Else
    202. sNachricht = sNachricht & "Der Typ " & o.GetType().ToString & " wurde noch nicht abgefangen" & Environment.NewLine
    203. End Select
    204. Else
    205. End If
    206. End If
    207. End If
    208. Next o
    209. If sNachricht.Length Then MessageBox.Show(sNachricht, GetCurrentMethod.Name)
    210. End Sub
    211. End Module

    SoEinVBler schrieb:

    Aktuell sind es nur 2 Timer (von 3) bei denen ich mir das Intervall in eine Datei speicher
    Machst Du

    Quellcode

    1. Intervall1 = 100
    2. Intervall2 = 200
    3. Intervall3 = 1000
    und

    Quellcode

    1. Timer1.Interval = Intervall1
    2. Timer2.Interval = Intervall2
    3. Timer3.Interval = Intervall3
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dynamisch soll heißen, ich verpasse den Controls, von denen ich Egenschaften speichern will, in den Eigenschaften ein Vermerk, und zwar im Property "TAG".
    Dort kommt ein Text als Erkennungszeichen rein.

    Dann sollen alle Controls durchlaufen werden und wenn das Erkennungszeichen im Property "TAG" gefunden wird, soll anhand vom dem erkannten Typ, die Eigenschaften gespeichert werden.
    Bei Textboxen oder NumericUpDown der Text, bei Checkboxen der Status von Checked etc.
    In dieser Routine kann dann entschieden werden was für Eigenschaften von dem jeweiligen Typ gespeichert wird.

    Heißt natürlich auch es wird für jeden Control-Typ immer die selben Eigenschaften gespeichert, aber meißtens sind das ja immer die gleiche.
    Wenn ich aber von einer Textbox z.B. noch die Hintergrundfarbe speichern will, dann muss das natürlich "von Hand" programiert werden.

    Hab mir auch kurz das Demo vom "ComplexConverter" angeschaut, und noch lange nicht alles verstanden.
    Aber dort kann man Eigenschaften wie WindowState oder Bounds dem Converter übergeben und der ermittelt den/die Wert/e und wandelt sie in ein string.

    Mein Weg ist aktuell dass ich nicht einzeln entscheide welche Property ich speicher, sondern der Control-Typ das vorgibt.
    @SoEinVBler Du willst VB.NET neu erfinden. :D
    Das können die Controls auch alleine, organisiere das im Designer:

    Ich bin dann mal draußen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Vielen Dank euch beiden.

    Das ich da was neu erfinde ist schon klar, man kann das alles mit Settings machen und dem Binding, hab da auch in einem Tutorial hier was dazu gelesen (war glaub ich von einem von euch)
    ich habe jetzt meine Routine so weit angepasst dass es läuft, ich nutzt das jetzt mal in dem Programm wo ich gerade drann bin.

    Das mit dem ComplexConverter schau ich mir auch noch mal an, aber da werde ich wohl noch etwas drann zu knappern haben, wenn ich es je komplett erfassen kann...
    Aber das mit in einer Routine das speicher und lesen zu machen hört sich gut an.
    Aktuell hab ich ja 2 Routinen die fast das gleich machen, nur einmal halt lesen und dann schreiben.