How To: Use Vista's Power Management APIs to Be A Good Laptop Citizen

Sign in to queue

The Discussion

  • User profile image
    jmazner

    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;
            }

Add Your 2 Cents