Ralf Westphal Archiv

weblogs.asp.net

Ausgeschlafen - Reagieren auf Windows Events beim Systemstart nach Standby/Hibernate

9. Sept. 2003Erstveröffentlichung: weblogs.asp.net/ralfwOriginaladresseralfw.de/archiv/2003/ausgeschlafen-reagieren-auf-windows-events-beim-systemstart-nach-stand/

Gerade bastle ich an einer kleinen Anwendung, mit der ich mir im System Tray immer die aktuell günstigsten Call-by-Call-Nummern anzeigen lassen kann. Wenn ich dann einen Anruf machen möchte, muss ich nur die Maus über das Tray Icon bewegen und sehe schon, welche Vorwahl ich wählen muss. Das finde ich einfacher, als eine Seite wie www.telefontarife.de im Browser aufzurufen oder gar ein Tarifvergleichsprogramm zu installieren.

Mein kleines Programm soll einfach im Hintergrund laufen, ein Tray Icon zeigen und periodisch seine Daten durch Zugriff auf ein Informationsangebot im Internet aktualisieren. Das ist auch alles kein Problem - solange ich meinen Laptop nicht schlafen lege. Meist fahre ich den Rechner am Tagesende (oder auch zwischendurch) nicht herunter, sondern schalte ihn nur in den Standby- oder Hibernate-Modus.

Wenn ich ihn aus einem dieser Modi wieder erwecke, läuft meine Anwendung zwar noch, aber das Timer-Control feuert nicht mehr periodisch. Das Programm aktualisiert seine Daten also nicht mehr automatisch.

Da andere Programme aber sehr wohl auf die Erweckung aus einem der Schlummerzustände reagieren (Outlook holt dann z.B. die Email ab), dachte ich mir, dass auch meine Anwendung sich über diese Systemzustandsänderung informieren lassen könnte. Wie könnte sie aber an die Ereignisse, die Windows zu diesem Zweck sicherlich wirft, herankommen? Die Antwort liegt im Windows Platform SDK unter dem Stichwort "Power Management".

Windows meldet Ereignisse des Power Management Systems mit der Windows Nachricht WM_POWERBROADCAST an alle Anwendungen:

define WM_POWERBROADCAST               0x0218

Der wparam der Nachricht enthält dann einen der folgenden Werte:

define PBT_APMQUERYSUSPEND             0x0000

define PBT_APMQUERYSTANDBY             0x0001

define PBT_APMQUERYSUSPENDFAILED       0x0002

define PBT_APMQUERYSTANDBYFAILED       0x0003

define PBT_APMSUSPEND                  0x0004

define PBT_APMSTANDBY                  0x0005

define PBT_APMRESUMECRITICAL           0x0006

define PBT_APMRESUMESUSPEND            0x0007

define PBT_APMRESUMESTANDBY            0x0008

define PBTF_APMRESUMEFROMFAILURE       0x00000001

define PBT_APMBATTERYLOW               0x0009

define PBT_APMPOWERSTATUSCHANGE        0x000A

define PBT_APMOEMEVENT                 0x000B

define PBT_APMRESUMEAUTOMATIC          0x0012

Davon sind für meine Zwecke PBT_APMRESUMESUSPEND und PBT_APMRESUMESTANDBY interessant. Die erhält meine Anwendung, wenn der Rechner aufgeweckt wird.

Um auf die Power-Management-Nachricht zu reagieren, muss ich dann nur die WndProc()-Methode meines Anwendungsfensters überschreiben:

Public Class Form1
    Inherits System.Windows.Forms.Form

...

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_POWERBROADCAST As Integer = &H218
        Const PBT_APMRESUMESUSPEND As Integer = 7
        Const PBT_APMRESUMESTANDBY As Integer = 8

If m.Msg = WM_POWERBROADCAST Then
            If m.WParam.ToInt32 = PBT_APMRESUMESTANDBY Or m.WParam.ToInt32 = PBT_APMRESUMESUSPEND Then
                Timer1.Enabled = False
                Timer1.Enabled = True
            End If
        End If
        MyBase.WndProc(m)
    End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        ' aktuelle Tarifdaten laden...
    End Sub
End Class

Die WndProc()-Methode schaltet dann nur meinen Timer aus und wieder an und schon läuft alles wieder automatisch - bis zur nächsten Schlafenszeit.

← Zurück ins Archiv