diff --git a/System/PowerManager.cs b/System/PowerManager.cs
index bc25d786..8abd8759 100644
--- a/System/PowerManager.cs
+++ b/System/PowerManager.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -9,6 +10,7 @@ using Vanara.InteropServices;
using Vanara.PInvoke;
using static Vanara.PInvoke.Kernel32;
using static Vanara.PInvoke.PowrProf;
+using static Vanara.PInvoke.User32;
namespace Vanara.Diagnostics
{
@@ -94,8 +96,8 @@ namespace Vanara.Diagnostics
FastSystemS4 = 1 << 15,
///
- /// The system supports fast startup (aka: hiberboot, hybrid boot, or hybrid shutdown) which is a setting that helps your PC start up
- /// faster after shutdown.
+ /// The system supports fast startup (aka: hiberboot, hybrid boot, or hybrid shutdown) which is a setting that helps your PC start
+ /// up faster after shutdown.
///
Hiberboot = 1 << 16,
@@ -140,13 +142,126 @@ namespace Vanara.Diagnostics
///
public static class PowerManager
{
- /*
- public static event EventHandler BatteryStatusChanged;
- public static event EventHandler EnergySaverStatusChanged;
- public static event EventHandler PowerSupplyStatusChanged;
- public static event EventHandler RemainingChargePercentChanged;
- public static event EventHandler RemainingDischargeTimeChanged;
- */
+ private static readonly Singleton Instance = new Singleton();
+
+ public static event EventHandler> AwayModeChanged
+ {
+ add => Instance.AddEvent(GUID_SYSTEM_AWAYMODE, value);
+ remove => Instance.RemoveEvent(GUID_SYSTEM_AWAYMODE, value);
+ }
+
+ public static event EventHandler> BatteryCapacityChanged
+ {
+ add => Instance.AddEvent(GUID_BATTERY_PERCENTAGE_REMAINING, value);
+ remove => Instance.RemoveEvent(GUID_BATTERY_PERCENTAGE_REMAINING, value);
+ }
+
+ public static event EventHandler> BatterySaverStatusChanged
+ {
+ add => Instance.AddEvent(GUID_POWER_SAVING_STATUS, value);
+ remove => Instance.RemoveEvent(GUID_POWER_SAVING_STATUS, value);
+ }
+
+ ///
+ /// Occurs when the current monitor's display state has changed.
+ ///
+ /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: This notification is available
+ /// starting with Windows 8 and Windows Server 2012.
+ ///
+ /// The Data member is a DWORD with one of the following values.
+ ///
+ /// - 0x0 - The display is off.
+ /// - 0x1 - The display is on.
+ /// - 0x2 - The display is dimmed.
+ ///
+ ///
+ public static event EventHandler> CurrentMonitorDisplayStateChanged
+ {
+ add => Instance.AddEvent(GUID_CONSOLE_DISPLAY_STATE, value);
+ remove => Instance.RemoveEvent(GUID_CONSOLE_DISPLAY_STATE, value);
+ }
+
+ public static event EventHandler> GlobalUserStatusChanged
+ {
+ add => Instance.AddEvent(GUID_GLOBAL_USER_PRESENCE, value);
+ remove => Instance.RemoveEvent(GUID_GLOBAL_USER_PRESENCE, value);
+ }
+
+ internal static event EventHandler LowBattery;
+
+ public static event EventHandler> PowerSchemePersonalityChanged
+ {
+ add => Instance.AddEvent(GUID_POWERSCHEME_PERSONALITY, value);
+ remove => Instance.RemoveEvent(GUID_POWERSCHEME_PERSONALITY, value);
+ }
+
+ public static event EventHandler PowerStatusChanged;
+
+ public static event EventHandler> PrimarySystemMonitorPowerChanged
+ {
+ add => Instance.AddEvent(GUID_MONITOR_POWER_ON, value);
+ remove => Instance.RemoveEvent(GUID_MONITOR_POWER_ON, value);
+ }
+
+ internal static event CancelEventHandler QueryStandby;
+
+ internal static event CancelEventHandler QuerySuspend;
+
+ internal static event EventHandler ResumedAfterFailure;
+
+ public static event EventHandler ResumedAfterSleep;
+
+ internal static event EventHandler ResumedAfterStandby;
+
+ public static event EventHandler ResumedAfterSuspend;
+
+ ///
+ /// Occurs when the display associated with the application's session has been powered on or off.
+ ///
+ /// Windows 7, Windows Server 2008 R2, Windows Vista and Windows Server 2008: This notification is available
+ /// starting with Windows 8 and Windows Server 2012.
+ ///
+ ///
+ /// This notification is sent only to user-mode applications.Services and other programs running in session 0 do not receive this notification.
+ ///
+ /// The Data member is a DWORD with one of the following values.
+ ///
+ /// - 0x0 - The display is off.
+ /// - 0x1 - The display is on.
+ /// - 0x2 - The display is dimmed.
+ ///
+ ///
+ public static event EventHandler> SessionDisplayStatusChanged
+ {
+ add => Instance.AddEvent(GUID_SESSION_DISPLAY_STATUS, value);
+ remove => Instance.RemoveEvent(GUID_SESSION_DISPLAY_STATUS, value);
+ }
+
+ public static event EventHandler> SessionUserStatusChanged
+ {
+ add => Instance.AddEvent(GUID_SESSION_USER_PRESENCE, value);
+ remove => Instance.RemoveEvent(GUID_SESSION_USER_PRESENCE, value);
+ }
+
+ internal static event EventHandler StandbyFailed;
+
+ internal static event EventHandler StandingBy;
+
+ internal static event EventHandler SuspendFailed;
+
+ public static event EventHandler Suspending;
+
+ public static event EventHandler> SystemIsBusy
+ {
+ add => Instance.AddEvent(GUID_IDLE_BACKGROUND_TASK, value);
+ remove => Instance.RemoveEvent(GUID_IDLE_BACKGROUND_TASK, value);
+ }
+
+ public static event EventHandler> SystemPowerSourceChanged
+ {
+ add => Instance.AddEvent(GUID_ACDC_POWER_SOURCE, value);
+ remove => Instance.RemoveEvent(GUID_ACDC_POWER_SOURCE, value);
+ }
/// Gets the device's battery status.
/// Returns a value.
@@ -243,6 +358,193 @@ namespace Vanara.Diagnostics
private static SYSTEM_POWER_CAPABILITIES GetCapabilities() => GetPwrCapabilities(out var c) ? c : default;
private static SYSTEM_POWER_STATUS GetStatus() => GetSystemPowerStatus(out var s) ? s : default;
+
+ private class Singleton : IDisposable
+ {
+ private readonly Dictionary eventHandles = new Dictionary();
+ private readonly BasicMessageWindow msgWindow;
+ private readonly Dictionary regs = new Dictionary();
+
+ internal Singleton() => msgWindow = new BasicMessageWindow(ListenerWndProc);
+
+ public void AddEvent(Guid guid, EventHandler> value)
+ {
+ lock (regs)
+ {
+ if (!eventHandles.TryGetValue(guid, out var h))
+ {
+ eventHandles.Add(guid, value);
+ regs.Add(guid, RegisterNotification(guid));
+ }
+ else
+ eventHandles[guid] = Delegate.Combine(h, value);
+ }
+ }
+
+ public void InvokeEvent(Guid guid)
+ {
+ if (!eventHandles.TryGetValue(guid, out var h))
+ throw new InvalidOperationException($"Event for {guid} is not registered.");
+ h.DynamicInvoke(null, new PowerEventArgs