- Waking the computer up after 30 seconds (see logfile)
- Catching the #WM_POWERBROADCAST message when standby was initiated by the program (instead of system buttons etc.)
- ...
Here is the current code I'm using:
Code: Select all
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: Finished")
EndProcedure
Procedure TimerStart()
Protected hTimer
Protected ft.FILETIME
hTimer = CreateWaitableTimer_(#Null, #False, #Title)
If hTimer
LogListAdd("Timer: Created")
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: Started")
;SleepEx_(#INFINITE, #True)
Else
LogListAddError("Timer: Started but doesn't support waking up! (Success message will appear now)")
EndIf
Else
LogListAddError("Timer: Not started!")
EndIf
CloseHandle_(hTimer)
Else
LogListAddError("Timer: Not created!")
EndIf
EndProcedure
Procedure WindowCallback(hWnd, uMsg, wParam, lParam)
Select uMsg
Case #WM_POWERBROADCAST
Select wParam
Case #PBT_APMSUSPEND
LogListAdd("Standby: Activated")
TimerStart()
Case #PBT_APMRESUMESUSPEND
LogListAdd("Standby: Finished")
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, "The timer should start automatically (for 30 secs) when clicking on these buttons or the PC's " + #DQUOTE$ + "standby" + #DQUOTE$ + " button." + #CRLF$ + #CRLF$ + "Warning: These buttons do what they say!")
ButtonGadget(#ButtonSuspend, 10, 90, 280, 30, "Suspend PC")
ButtonGadget(#ButtonHibernate, 10, 130, 280, 30, "Hibernate PC")
If SuspendAllowed() = #False : DisableGadget(#ButtonSuspend, #True) : EndIf
If HibernateAllowed() = #False : DisableGadget(#ButtonHibernate, #True) : EndIf
SetWindowCallback(@WindowCallback())
HideWindow(#Window, #False)
LogListAdd("Program: Started")
Repeat
Select WaitWindowEvent()
Case #PB_Event_Gadget
Select EventGadget()
Case #ButtonSuspend
LogListAdd("Standby: Start suspending")
TimerStart() ; <-- Why isn't #WM_POWERBROADCAST received to do this? (see WindowCallback())
Suspend(#False)
Case #ButtonHibernate
LogListAdd("Standby: Start hibernating")
TimerStart() ;
Suspend(#True)
EndSelect
Case #PB_Event_CloseWindow
LogListAdd("Program: Closed")
LogListSave(Logfile) ;: RunProgram(Logfile)
Break
EndSelect
ForEver
EndIf
Code: Select all
15:25:14 Program: Started
15:25:20 Standby: Start suspending
15:25:20 Timer: Created
15:25:20 Timer: Started
15:25:20 Timer: Finished <-- Where are the 30 seconds of wait?
15:26:37 Standby: Finished
15:26:45 Program: Closed
Edit: Changed thread title