How To: Use Vista's Power Management APIs to Be A Good Laptop Citizen
- Posted: Jun 26, 2006 at 2:24 PM
- 21,528 Views
- 1 Comment
Loading User Information from Channel 9
Something went wrong getting user information from Channel 9
Loading User Information from MSDN
Something went wrong getting user information from MSDN
Loading Visual Studio Achievements
Something went wrong getting the Visual Studio Achievements
Right click “Save as…”
Is your application the reason why my laptop only gets two hours of battery life? That's not a question you want to hear from your paying customers. Windows Vista provides an
enhanced power management API
and control panel which lets the user express their desired power usage profile, and lets applications query and respond to changes in power state.
In the second of our Vista How To series,
Ian Griffiths shows how to listen to power change events in a WPF app, and respond to low power or power saver modes by reducing the amount of animation in the app (thus saving GPU and CPU cycles)
Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation,
please create a new thread in our Forums,
or
Contact Us and let us know.
Follow the Discussion
Oops, something didn't work.
What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in. You need to be signed in to Channel 9 to use this feature.What does this mean?
Following an item on Channel 9 allows you to watch for new content and comments that you are interested in and view them all on your notifications page.sign up for email notifications?
Here are some relevant sections of the code from Ian's sample app. I've added the interop definitions to PInvoke.net for easy reference.
void Window1_Loaded(object sender, RoutedEventArgs e)
{
source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
source.AddHook(new HwndSourceHook(WndProc));
RegisterForPowerNotifications(source.Handle);
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
UnregisterForPowerNotifications();
}
private IntPtr hBattCapacity;
private IntPtr hMonitorOn;
private IntPtr hPowerScheme;
private IntPtr hPowerSrc;
private void RegisterForPowerNotifications(IntPtr hwnd)
{
hPowerSrc = RegisterPowerSettingNotification(hwnd,
ref GUID_ACDC_POWER_SOURCE,
DEVICE_NOTIFY_WINDOW_HANDLE);
hBattCapacity = RegisterPowerSettingNotification(hwnd,
ref GUID_BATTERY_PERCENTAGE_REMAINING,
DEVICE_NOTIFY_WINDOW_HANDLE);
hMonitorOn = RegisterPowerSettingNotification(hwnd,
ref GUID_MONITOR_POWER_ON,
DEVICE_NOTIFY_WINDOW_HANDLE);
hPowerScheme = RegisterPowerSettingNotification(hwnd,
ref GUID_POWERSCHEME_PERSONALITY,
DEVICE_NOTIFY_WINDOW_HANDLE);
}
private void UnregisterForPowerNotifications()
{
UnregisterPowerSettingNotification(hBattCapacity);
UnregisterPowerSettingNotification(hMonitorOn);
UnregisterPowerSettingNotification(hPowerScheme);
UnregisterPowerSettingNotification(hPowerSrc);
}
static bool onBattery;
enum PowerPersonality { Savings, Performance, Mixed };
static PowerPersonality personality;
private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_POWERBROADCAST && wParam.ToInt32() == PBT_POWERSETTINGCHANGE)
{
// Extract data from message
POWERBROADCAST_SETTING ps =
(POWERBROADCAST_SETTING)Marshal.PtrToStructure(
lParam, typeof(POWERBROADCAST_SETTING));
IntPtr pData = (IntPtr)(lParam.ToInt32() + Marshal.SizeOf(ps));
// Examine notification
if (ps.PowerSetting == GUID_POWERSCHEME_PERSONALITY &&
ps.DataLength == Marshal.SizeOf(typeof(Guid)))
{
// New power scheme selected.
Guid newPersonality =
(Guid)Marshal.PtrToStructure(pData, typeof(Guid));
if (newPersonality == GUID_MAX_POWER_SAVINGS)
{
personality = PowerPersonality.Savings;
}
else if (newPersonality == GUID_MIN_POWER_SAVINGS)
{
personality = PowerPersonality.Performance;
}
else if (newPersonality == GUID_TYPICAL_POWER_SAVINGS)
{
personality = PowerPersonality.Mixed;
}
else
{
Debug.WriteLine("switched to unknown Power savings");
personality = PowerPersonality.Mixed;
}
}
else if (ps.PowerSetting == GUID_ACDC_POWER_SOURCE &&
ps.DataLength == Marshal.SizeOf(typeof(Int32)))
{
Int32 iData = (Int32)Marshal.PtrToStructure(pData, typeof(Int32));
Debug.WriteLine("ACDC: " + iData);
onBattery = iData != 0;
}
// Select the best resources for the current
// power state.
if (personality == PowerPersonality.Performance
|| (personality == PowerPersonality.Mixed && !onBattery))
{
Application.Current.Resources = fullPowerResources;
}
else
{
Application.Current.Resources = lowPowerResources;
}
}
return IntPtr.Zero;
}
Remove this comment
Remove this thread
close