Ich will einen Timer starten, wenn der Computer in den Ruhezustand geht und dann nach 30 Sekunden wieder aufwecken.
Blöderweise funktionieren ein paar Sachen noch nicht:
- Computer nach 30 aufwecken (siehe Logfile)
- #WM_POWERBROADCAST abfangen, wenn der Ruhezustand durch das Programm eingeleitet wurde (anstelle von Standby-Buttons des Systems etc.)
- ...
Hier ist der aktuelle Code:
Code: Alles auswählen
EnableExplicit
#Title = "TimerTest"
Enumeration
#Window
#Text
#ButtonSuspend
#ButtonHibernate
#FileLog
EndEnumeration
#PBT_APMRESUMESUSPEND = $0007
#PBT_APMSUSPEND = $0004
Structure LogListItem
Text.s
Time.l
Level.l
EndStructure
Global NewList LogList.LogListItem()
Define Logfile.s
Logfile.s = GetPathPart(ProgramFilename()) + #Title + "_LOG.txt"
Procedure LogListAdd(Text.s, Level=0)
If AddElement(LogList())
With LogList()
\Text = Text
\Time = Date()
\Level = Level
EndWith
EndIf
EndProcedure
Procedure LogListAddError(Text.s, Level=2, Info=#True)
Protected Error, ErrorInfo.s
If Info = #True
Error = GetLastError_()
ErrorInfo = Space(#MAX_PATH)
FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, Error, 0, @ErrorInfo, Len(ErrorInfo), 0)
ErrorInfo = " -> (" + RSet(Hex(Error, #PB_Long), 8, "0") + ") " + #DQUOTE$ + ErrorInfo + #DQUOTE$
EndIf
LogListAdd(Text + ErrorInfo, Level)
EndProcedure
Procedure LogListSave(Filename.s)
Protected FileNr
Protected Result = #False
FileNr = CreateFile(#PB_Any, Filename)
If FileNr
ForEach LogList()
WriteStringN(FileNr, FormatDate("%hh:%ii:%ss", LogList()\Time) + #TAB$ + LogList()\Text)
Next
Result = #True
CloseFile(FileNr)
EndIf
ProcedureReturn Result
EndProcedure
Procedure DateToFiletime(Date, *ft.FILETIME)
Protected st.SYSTEMTIME
With st
\wYear = Year(Date)
\wMonth = Month(Date)
\wDay = Day(Date)
\wDayOfWeek = DayOfWeek(Date)
\wHour = Hour(Date)
\wMinute = Minute(Date)
\wSecond = Second(Date)
\wMilliseconds = 0
EndWith
SystemTimeToFileTime_(@st, *ft)
LocalFileTimeToFileTime_(@*ft, *ft)
EndProcedure
Procedure TimerCallback(*ArgToCompletionRoutine, TimerLowValue.l, TimerHighValue.l)
LogListAdd("Timer: Beendet")
EndProcedure
Procedure TimerStart()
Protected hTimer
Protected ft.FILETIME
hTimer = CreateWaitableTimer_(#Null, #False, #Title)
If hTimer
LogListAdd("Timer: Erstellt")
DateToFiletime(Date() + 30, @ft) ; Wait 30 seconds until "waking up"
If SetWaitableTimer_(hTimer, @ft, 0, @TimerCallback(), 0, #True)
If GetLastError_() <> #ERROR_NOT_SUPPORTED
LogListAdd("Timer: Gestartet")
;SleepEx_(#INFINITE, #True)
Else
LogListAddError("Timer: Gestartet aber Aufwecken wird nicht unterstützt! (Meldung folgt nun sofort)")
EndIf
Else
LogListAddError("Timer: Nicht gestartet!")
EndIf
CloseHandle_(hTimer)
Else
LogListAddError("Timer: Nicht erstellt!")
EndIf
EndProcedure
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
Select uMsg
Case #WM_POWERBROADCAST
Select wParam
Case #PBT_APMSUSPEND
LogListAdd("Standby: Aktiviert")
TimerStart()
Case #PBT_APMRESUMESUSPEND
LogListAdd("Standby: Beendet")
EndSelect
EndSelect
ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure
Procedure Suspend(Hibernate, ForceCritical=#False, DisableWakeEvent=#False)
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "SetSuspendState", Hibernate, ForceCritical, DisableWakeEvent)
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
Procedure SuspendAllowed()
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "IsPwrSuspendAllowed")
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
Procedure HibernateAllowed()
Protected LibraryID
Protected Result = #False
LibraryID = OpenLibrary(#PB_Any, "powrprof.dll")
If LibraryID
Result = CallFunction(LibraryID, "IsPwrHibernateAllowed")
CloseLibrary(LibraryID)
EndIf
ProcedureReturn Result
EndProcedure
If OpenWindow(#Window, #PB_Ignore, #PB_Ignore, 300, 170, #Title, #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_Invisible)
TextGadget(#Text, 10, 10, 280, 70, "Der Timer sollte automatisch starten (für 30 Sec.), wenn auf einen dieser Buttons oder im Startmenü entsprechendes geklickt wird." + #CRLF$ + #CRLF$ + "Hinweis: Die Buttons sollten funktionieren!")
ButtonGadget(#ButtonSuspend, 10, 90, 280, 30, "Standby-Modus")
ButtonGadget(#ButtonHibernate, 10, 130, 280, 30, "Ruhezustand")
If SuspendAllowed() = #False : DisableGadget(#ButtonSuspend, #True) : EndIf
If HibernateAllowed() = #False : DisableGadget(#ButtonHibernate, #True) : EndIf
SetWindowCallback(@WindowCallback())
HideWindow(#Window, #False)
LogListAdd("Programm: Gestartet")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #ButtonSuspend
LogListAdd("Standby: Starte Standby-Modus")
TimerStart() ; <-- Warum wird #WM_POWERBROADCAST nicht abgefangen um das hier zu machen? (siehe WindowCallback())
Suspend(#False)
Case #ButtonHibernate
LogListAdd("Standby: Starte Ruhezustand")
TimerStart() ;
Suspend(#True)
EndSelect
Case #PB_Event_CloseWindow
LogListAdd("Programm: Beendet")
LogListSave(Logfile) ;: RunProgram(Logfile)
Break
EndSelect
ForEver
EndIf
Code: Alles auswählen
15:25:14 Programm: Gestartet
15:25:20 Standby: Starte Standby-Modus
15:25:20 Timer: Erstellt
15:25:20 Timer: Gestartet
15:25:20 Timer: Beendet <-- Wo sind die 30 Sec.?
15:26:37 Standby: Beendet
15:26:45 Programm: Beendet
Momentan denke ich, dass es mehrere Probleme geben könnte: DateToFiletime() erstellt aus welchen Gründen auch immer eine Zeit in der Vergangenheit, SleepEx_() wird benötigt, Sicherheitsgründe (Privilegien benötigt?), mein PC unterstützt diese Art von Standby nicht und/oder Konflikte mit dem Message-Handling von PureBasic...
Bitte probiert mal den Code und postet welche Ergebnisse ihr bekommt, damit ich eventuell herausfinden kann, warum es nicht funktioniert. Danke.