Diese Seite wurde zuletzt aktualisiert am 21.09.1999
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicAddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für IE, Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zur AVB-Web-Site, Kontakt und Impressum

Zurück...

Zurück...

(-hg) mailto:hg_timerex@aboutvb.de

Manchen ist die Kürze der Intervalle (die "Auflösung") des VB-Timers nicht kurz und fein genug, manchen ist sie viel zu kurz. Falls Sie ebenfalls einmal einen Timer brauchen, dessen höchste Intervallspanne die runde Minute des VB-Timers überschreitet, und Sie längere Sekundenspannen, Minuten-, Stunden- oder gar Tages-Intervalle benötigen, könnte der hier vorgestellte erweiterte Timer genau das sein, was Sie brauchen.


Dieser Timer bietet auch lange Intervalle - Maximum: 735.440 Jahre!

Mit ihm können Sie Intervalle von 1 Sekunde bis zu rund 735.440 Jahren setzen (Nein, dass ich die Höchstspanne nicht ausgetestet habe, ist kein Reklamationsgrund, wirklich nicht!). Intern arbeitet der Timer zwar mit Sekunden, doch damit Sie sich nicht die Arbeit des Umrechnens machen müssen, können Sie auch Intervalle in Minuten, Stunden und Tagen angeben. Allerdings nur in ganzen Teilen - ein Intervall etwa der Art "12 Tage, 7 Stunden, 34 Minuten und 59 Sekunden" müssen Sie leider doch selbst in Sekunden umrechen (Nein, das ist auch kein Reklamationsgrund!).

Damit der Timer nun aber weiß, welche Einheit gemeint ist, setzen Sie die Eigenschaft IntervalUnit entsprechend auf eine der enumerierten Konstanten txSeconds, txMinutes, txHours oder txDays. Der Grund für mich, Tage als größte Intervalleinheit zu vorzugeben, ist reine Bequemlichkeit gewesen - der Aufwand der Berücksichtigung von Monatslängen, Schaltjahren und anderen zeitmesstechnischen Spitzfindigkeiten hätte den praktischen Nutzen dieser kleinen Komponente sicher gesprengt. Aber wenn Sie unbedingt wollen - den Quelltext haben Sie hier ja vorliegen - Sie brauchen bloß die paar entsprechenden Zeilen zur Umrechnung in die interne Sekunden-Basis in der Ereignis-Prozedur tmr_Timer nachzurüsten.

Die riesige Höchstspanne ergibt sich übrigens daraus, dass ich Long als Datentyp für die Eigenschaft Interval verwendet habe und dies im Gegensatz zum VB-Original-Timer auch so gemeint habe. Das Original nimmt zwar ebenfalls Long-Werte an, motzt aber, wenn der Wert größer 65.535 wird (vorzeichenloser 16-Bit-Integer). Da maximale 268.435.455 Sekunden (der positive Höchstwert eines vorzeichenbehafteten 32-Bit-Long-Integers) gerade mal gut 3.100 Tage entsprechen bzw. rund achteinhalb Jahren, wollte ich die Lebensdauer Ihrer Software-Produkte, in denen Sie diesen Timer verwenden, nicht unnötig beschränken, indem ich VB-like eine Kappung eingebaut hätte.

Das Herz der Komponente ist natürlich ein VB-Timer. Dieser läuft nur, wenn sowohl seine Eigenschaft Enabled gleich True als auch sein Interval größer als 0 ist. Dieses Verhalten habe ich aufgegriffen - Sie brauchen also nicht weiter umzudenken. Ich denke, der übrige Code der Komponente ist soweit klar, dass fast nur noch ein Wort zur privaten Hilfsprozedur zCalcInterval übrig bleibt.

Dort wird die innere Auflösung des Timers eingestellt. Sie sehen dort, dass ich das Intervall des VB-Timers auf 100 setze, wenn die gewünschte Intervalleinheit Sekunden sein soll. Warum ich das VB-Timer-Intervall nicht auf 1.000 setze, also ebenfalls auf einen festen Sekundenschritt? Das Problem ist die Funktionsweise der wiederum hinter dem VB-Timer steckenden Windows-Timer-Geschichte.

Der Intervallablauf eines Windows-Timers wird über Nachrichten des internen Windows-Nachrichtensystems übermittelt (Wenn Sie nicht wissen sollten, was dieses Nachrichtensystem ist, wäre es vielleicht eine Idee sich damit einmal zu befassen, aber das ist hier nicht das Thema. Notwendig ist dieses Wissen nur, wenn Sie in VB unter der Motorhaube basteln möchten.). Innerhalb dieses Systems werden Nachrichten nach Prioritäten gewichtet und verschickt. Timer-Nachrichten gehören zur niedrigsten Prioritätsstufe und glänzen daher nicht gerade durch Zuverlässigkeit. Sie werden zwar ziemlich exakt zum richtigen Intervall-Zeitpunkt abgesandt, müssen aber oft Schlange stehen, bis sie ihr Ziel erreichen. Und wie das mit Warteschlangen halt so ist, ist deren Länge und damit die Verweildauer darin fast nie gleich, oder gar verlässlich kalkulierbar. Damit dieses etwas wackelige System nicht vollends aus den Fugen gerät und unter Umständen in ein Timer-Nachrichten-Stakkato ausartet, wenn eine besonders lange Warteschlange abgebaut worden sein sollte und die hintenanstehenden, mittlerweile verspäteten Nachrichten dann im Pulk eintreffen, wird dafür gesorgt, dass verspätete Nachrichten gar nicht erst ankommen, wenn bereits die nächste fällig geworden und schon unterwegs ist.

Die Festlegung des VB-Timer-Intervalls auf 100 (Tausendstel Sekunden) bedeutet daher eine Genauigkeit von +/- 1/10 Sekunde. Wenn Ihnen das zu ungenau ist, können Sie den Wert reduzieren. Das Gleiche gilt im Prinzip für die übrigen Intervalleinheiten - die von mir vorgeschlagenen Auflösungen sind eigentlich willkürliche Annahmen. So gehe ich einfach mal davon aus, dass etwa bei einem Tagesintervall eine Genauigkeit von +/- 1 Minute ausreichend ist. Letztlich ist es eine Abwägung - zwischen Genauigkeit und Systembelastung. Alle Minute ein Timer-Tick stört schließlich überhaupt nicht. Aber Sie können sich vielleicht vorstellen, wie viel das System zu tun bekommt, wenn in vielen Anwendungen viele Timer mit kürzesten Intervallen am werkeln sein sollten. Meine Annahmen zu ändern, bleibt Ihnen jedoch frei überlassen.

Das Steuerelement bleibt zur Laufzeit unsichtbar (auch wenn Sie es im Bild oben sehen können), wie der VB-Timer auch. Zur Designzeit behält das UserControl immer eine Größe von 32x32 Pixels bei. Die darauf platzierte Schaltfläche (CommandButton) hat keinerlei Funktion und wird zur Laufzeit gar nicht geladen. Sie sorgt nur für die 3D-Optik zur Designzeit und enthält auch die kleine Grafik zur Repräsentation (Style = grafisch).

Zu dem kleinen Testprogramm ist nichts Besonderes zu sagen. Erwähnenswert ist vielleicht, dass die einzeilige TextBox zur Eingabe des Intervalls unter Windows 98 rechtsbündig ausgerichtet erscheint und dass darin nur Ziffern eingegeben werden können.

Private mLastDate As Date

Public Event Timer()

Public Enum txIntervalUnitConstants
  txSeconds
  txMinutes
  txHours
  txDays
End Enum

Private pInterval As Long
Private pIntervalUnit As txIntervalUnitConstants

Public Property Get Enabled() As Boolean
  Enabled = tmr.Enabled
End Property

Public Property Let Enabled(ByVal New_Enabled As Boolean)
  tmr.Enabled = New_Enabled
  zCalcInterval
  PropertyChanged "Enabled"
End Property

Public Property Get Interval() As Long
  Interval = pInterval
End Property

Public Property Let Interval(ByVal New_Interval As Long)
  Select Case New_Interval
    Case 0
      pInterval = 0
      tmr.Interval = 0
    Case Is > 0
      pInterval = New_Interval
      zCalcInterval
    Case Else
      Err.Raise 380
      Exit Property
  End Select
  PropertyChanged "Interval"
End Property

Public Property Get IntervalUnit() As txIntervalUnitConstants
  IntervalUnit = pIntervalUnit
End Property

Public Property Let IntervalUnit(ByVal New_IntervalUnit _
 As txIntervalUnitConstants)
  Select Case New_IntervalUnit
    Case txSeconds To txDays
      pIntervalUnit = New_IntervalUnit
      zCalcInterval
      PropertyChanged "IntervalUnit"
    Case Else
      Err.Raise 380
  End Select
End Property

Private Sub tmr_Timer()
  Dim nInterval As Double

  Select Case pIntervalUnit
    Case txSeconds
      nInterval = pInterval
    Case txMinutes
      nInterval = pInterval * 60
    Case txHours
      nInterval = pInterval * 3600
    Case txDays
      nInterval = pInterval * 86400
  End Select
  If Abs(DateDiff("s", Now, mLastDate)) >= nInterval Then
    RaiseEvent Timer
    mLastDate = Now
  End If
End Sub

Private Sub UserControl_ReadProperties(PropBag As PropertyBag)
  Me.Enabled = PropBag.ReadProperty("Enabled", False)
  Me.Interval = PropBag.ReadProperty("Interval", 0)
  Me.IntervalUnit = PropBag.ReadProperty("IntervalUnit", txSeconds)
End Sub

Private Sub UserControl_Resize()
  Static sInProc As Boolean
  
  If sInProc Then
    Exit Sub
  Else
    sInProc = True
  End If
  UserControl.Size 32 * Screen.TwipsPerPixelX, _
   32 * Screen.TwipsPerPixelY
  sInProc = False
End Sub

Private Sub UserControl_WriteProperties(PropBag As PropertyBag)
  PropBag.WriteProperty "Enabled", tmr.Enabled, False
  PropBag.WriteProperty "Interval", pInterval, 0
  PropBag.WriteProperty "IntervalUnit", pIntervalUnit, txSeconds
End Sub

Private Sub zCalcInterval()
  With tmr
    If .Enabled Then
      If pInterval Then
        Select Case pIntervalUnit
          Case txSeconds
            .Interval = 100
          Case txMinutes
            .Interval = 1000
          Case txHours
            .Interval = 30000
          Case txDays
            .Interval = 60000
        End Select
        mLastDate = Now
      End If
    End If
  End With
End Sub

Code des ActiveX-Controls avbTimerEx

Code des Beispiel-Projekts avbTimerExOCXTest Code des Beispiel-Projekts avbTimerExOCXTest


Das Projekt avbTimerExOCX (timerex.zip - ca. 6,5 KB)

ActiveX-Control als Setup (ohne VB 6-Runtime!) (timerexs.zip - ca. 248 KB)



Komponenten-Übersicht

Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Visual Basic
ABOUT Visual Basic
Visual
Basic
Programmieren
Programmierung
Timer
ActiveX-Control
VB
VBA
Visual Basic for Applications
VBS
VBScript
Scripting
Windows
ActiveX
COM
OLE
API
Computer
PC
Microsoft Office
Microsoft
Office 97
Office 2000
Access
Word
Winword
Excel
Outlook
Addins
ASP
Active Server Pages
COMAddIns
ActiveX-Controls
OCX
UserControl
UserDocument
Komponenten