In a Visual Studio 2005 C++ MFC application you will need to add an ON_MESSAGE()
to your message map looking for the WM_POWERBROADCAST
message as in this example:
BEGIN_MESSAGE_MAP(CFrameworkWndDoc, CWindowDocument)
//{{AFX_MSG_MAP(CFrameworkWndDoc)
ON_WM_CHAR()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_MESSAGE(WM_POWERBROADCAST, OnPowerMsgRcvd)
END_MESSAGE_MAP()
Then you will need to add the message handler function along with the class definition change to declare the member function for the message handler so that you can check the wParam
variable for the message type as in this skeleton:
// Handle the WM_POWERBROADCAST message to process a message concerning power management
// such as going to Sleep or Waking Up.
LRESULT CFrameworkWndDoc::OnPowerMsgRcvd(WPARAM wParam, LPARAM lParam)
{
switch (wParam) {
case PBT_APMPOWERSTATUSCHANGE:
TRACE0("PBT_APMPOWERSTATUSCHANGE received\n");
break;
case PBT_APMRESUMEAUTOMATIC:
TRACE0("PBT_APMRESUMEAUTOMATIC received\n");
break;
case PBT_APMRESUMESUSPEND:
TRACE0("PBT_APMRESUMESUSPEND received\n");
break;
case PBT_APMSUSPEND:
TRACE0("PBT_APMSUSPEND received\n");
break;
}
return 0;
}
What I have seen is that a test using the above in an application running on Windows 7 that is started in the debugger and then I manually make my PC running the application to Sleep I will see the following message:
PBT_APMSUSPEND received
Then when the PC is restarted and I sign-in what I will see in the debugger output window are two messages one after the other:
PBT_APMRESUMESUSPEND received
PBT_APMRESUMEAUTOMATIC received
Everything that I have found thus far indicates that you have no indication whether you are coming out of a Sleep state or a Hibernate state. I am still doing further research on what needs to be done when suspending or when resuming so far as file and device handles. I have seen indications that file handles to COM ports are no longer valid after resuming. I also am unsure about interfaces to other processes for instance database connections.
In addition to the standard Sleep and Hibernate power management states Microsoft has introduced the Connected Standby power state with Windows 8 and 8.1 which has some application design ramifications depending on the type of application.
Desktop applications typically require no extra work to integrate with
connected standby.
The Desktop Activity Moderator (DAM) is the Windows component that
pauses all desktop applications and throttles the runtime of
third-party system services during connected standby. The purpose of
the DAM is to maintain basic software compatibility with existing
applications and services, but mitigate their impact on battery life
during sleep.
Windows prevents desktop applications from running during any part of
connected standby after the DAM phase completes. Windows allows
third-party system services to execute in a throttled mode after
completing the DAM phase. In this mode, a third-party service can run
for no more than one second of wall-clock time every 30 seconds.
The Art of Graceful Application Suspension by Lynn Merrill from Intel has some information about handling the various Windows message types associated with Power Management under Windows however it is date 2005 so not all material may pertain to Windows after Windows XP. There is at least one no longer used message in the message sequence described in this document as beginning with Windows Vista the PBT_APMQUERYSUSPEND
message which was used to request whether an application was able to suspend is no longer used by Windows. The SetThreadExecutionState()
function is now used to indicate that a thread can not be interrupted with a change to Sleep or Hibernate state. See the answers in stackoverflow Can't catch sleep suspend messages (winxp) for details on Power Management state message changes.
System power state events since Windows XP
Microsoft has improved power management since Windows XP as the various versions of the Windows OS share more components and versions of Windows are now being deployed on smaller devices with battery requiring more careful power management. See Registering for Power Events. There is both a RegisterPowerSettingNotification()
function and an UnregisterPowerSettingNotification()
function.
An application or service uses the RegisterPowerSettingNotification
function to register for notifications. When the corresponding power
setting changes, the system sends notifications as follows:
- An application receives a
WM_POWERBROADCAST
message with a wParam
of PBT_POWERSETTINGCHANGE
and an lParam
that points to a
POWERBROADCAST_SETTING
structure.
- A service receives a call to the
HandlerEx
callback function it registered by calling the RegisterServiceCtrlHandlerEx
function. The
lpEventData
parameter sent to the HandlerEx
callback function
points to a POWERBROADCAST_SETTING
structure.
In the POWERBROADCAST_SETTING
structure, the PowerSetting
member
contains the GUID that identifies the notification and the Data member
contains the new value of the power setting.
See also Power Management Functions for the list of the power management functions in the Windows API since Windows Vista.
System power status and battery condition
You can use the Windows System Services API function GetSystemPowerStatus()
to retrieve the current power status.
Retrieves the power status of the system. The status indicates whether
the system is running on AC or DC power, whether the battery is
currently charging, how much battery life remains, and if battery
saver is on or off.
However note that the information returned in the SYSTEM_POWER_STATUS
struct is about battery status and AC/DC power source and not the actual device power state such as Sleep or Hibernate.
And if the Windows device is in a Sleep or Hibernate state, your application will not be running so this function can not be used to determine the current Windows power state. I include this note as it may be useful for someone who arrives at this post while researching this topic.