Trigger4Win/Trigger/Events/Plugins/PowerEvents.cs

386 lines
12 KiB
C#
Raw Normal View History

2015-04-10 02:09:58 +02:00
using System;
using System.Collections.Generic;
using Microsoft.Win32;
using Win32_SystemEvents = Microsoft.Win32.SystemEvents;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Threading;
using System.ComponentModel;
using Trigger.Classes.Power;
using Trigger.Classes.System;
namespace Trigger.Events
{
/// <summary>
/// <para>A <see cref="EventPlugin"/> that provides events for Power stuff</para>
/// <para>It catches changes in the PowerMode (Battery Status, Battery Availability, PowerLine Status), Suspend and Resumes and a change of the active <see cref="PowerScheme"/></para>
/// </summary>
public class Power : EventPlugin
{
#region Dll Imports
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal extern static IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, int Flags);
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal extern static IntPtr UnregisterPowerSettingNotification(IntPtr Handle);
#endregion
#region Constants, Structs & Enums
internal enum EventType : byte
{
PowerModeChanged,
PowerLineStatusChanged,
BatteryStatusChanged,
PowerSchemeChanged,
}
#endregion
#region Properties
internal static Main Main;
internal Dictionary<EventType, object> oldValues = new Dictionary<EventType, object>();
internal static Dictionary<EventType, object> oldStaticValues = new Dictionary<EventType, object>();
#region Register Parent Events
internal byte powerModeChangedEnabled;
internal bool PowerModeChangedEnabled
{
get
{
return powerModeChangedEnabled > 0;
}
set
{
if (value)
powerModeChangedEnabled++;
else
powerModeChangedEnabled--;
if (value && powerModeChangedEnabled == 1)
Win32_SystemEvents.PowerModeChanged += Win32_SystemEvents_PowerModeChanged;
else if (powerModeChangedEnabled == 0)
Win32_SystemEvents.PowerModeChanged -= Win32_SystemEvents_PowerModeChanged;
}
}
internal static byte powerBroadcastChangedEnabled;
internal static IntPtr powerBroadcastChangedHandle = IntPtr.Zero;
internal static bool PowerBroadcastChangedEnabled
{
get
{
return powerBroadcastChangedEnabled > 0;
}
set
{
if (value)
powerBroadcastChangedEnabled++;
else
powerBroadcastChangedEnabled--;
if (value && powerBroadcastChangedEnabled == 1)
{
powerBroadcastChangedHandle = RegisterPowerSettingNotification(Main.Handle, ref Classes.Power.PowerScheme.GUID_POWERSCHEME_PERSONALITY, Main.DEVICE_NOTIFY_WINDOW_HANDLE);
Main.RegisterEventForMessage(Classes.System.WindowsMessages.WM_POWERBROADCAST);
Main.MessageReceived += Main_MessageReceived;
}
else if (powerBroadcastChangedEnabled == 0)
{
UnregisterPowerSettingNotification(powerBroadcastChangedHandle);
powerBroadcastChangedHandle = IntPtr.Zero;
Main.UnregisterEventForMessage(Classes.System.WindowsMessages.WM_POWERBROADCAST);
Main.MessageReceived -= Main_MessageReceived;
}
}
}
#endregion
#region Events
#region PowerModeChanged
internal EventPlugin.EventValue<PowerModes> OnPowerModeChanged;
/// <summary><para>Occurs when the user suspends or resumes the system.</para></summary>
public event EventPlugin.EventValue<PowerModes> PowerModeChanged
{
add
{
this.OnPowerModeChanged += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnPowerModeChanged -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region - Suspend
internal EventPlugin.Event OnSuspend;
/// <summary><para>Occurs when the user suspends the system.</para></summary>
public event EventPlugin.Event Suspend
{
add
{
this.OnSuspend += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnSuspend -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region - Resume
internal EventPlugin.Event OnResume;
/// <summary><para>Occurs when the user resumes the system.</para></summary>
public event EventPlugin.Event Resume
{
add
{
this.OnResume += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnResume -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region - PowerLineStatusChanged
internal EventPlugin.EventValues<PowerLineStatus> OnPowerLineStatusChanged;
/// <summary><para>Occurs when the user connects or disconnects the system from/to the power network.</para></summary>
public event EventPlugin.EventValues<PowerLineStatus> PowerLineStatusChanged
{
add
{
if (!oldValues.ContainsKey(EventType.PowerLineStatusChanged))
oldValues[EventType.PowerLineStatusChanged] = Status.Power.PowerLineStatus;
this.OnPowerLineStatusChanged += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnPowerLineStatusChanged -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region - BatteryAvailabilityChanged
internal EventPlugin.EventValue<bool?> OnBatteryAvailabilityChanged;
/// <summary><para>Occurs when the user connects or disconnects the computer from the battery.</para></summary>
public event EventPlugin.EventValue<bool?> BatteryAvailabilityChanged
{
add
{
if (!oldValues.ContainsKey(EventType.BatteryStatusChanged))
oldValues[EventType.BatteryStatusChanged] = Status.Power.BatteryChargeStatus;
this.OnBatteryAvailabilityChanged += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnBatteryAvailabilityChanged -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region - BatteryStatusChanged
internal EventPlugin.EventValues<BatteryChargeStatus> OnBatteryStatusChanged;
/// <summary><para>Occurs when the user connects or disconnects the computer from the battery.</para></summary>
public event EventPlugin.EventValues<BatteryChargeStatus> BatteryStatusChanged
{
add
{
if (!oldValues.ContainsKey(EventType.BatteryStatusChanged))
oldValues[EventType.BatteryStatusChanged] = Status.Power.BatteryChargeStatus;
this.OnBatteryStatusChanged += value;
PowerModeChangedEnabled = true;
}
remove
{
this.OnBatteryStatusChanged -= value;
PowerModeChangedEnabled = false;
}
}
#endregion
#region PowerSchemeChanged
internal static EventPlugin.EventValues<PowerScheme> OnPowerSchemeChanged;
/// <summary><para>Occurs when the user selects antoher power plan.</para></summary>
public event EventPlugin.EventValues<PowerScheme> PowerSchemeChanged
{
add
{
if (!oldStaticValues.ContainsKey(EventType.PowerSchemeChanged))
oldStaticValues[EventType.PowerSchemeChanged] = Status.Power.ActivePowerScheme;
OnPowerSchemeChanged += value;
PowerBroadcastChangedEnabled = true;
}
remove
{
OnPowerSchemeChanged -= value;
PowerBroadcastChangedEnabled = false;
}
}
#endregion
#endregion
#endregion
#region Constructor & Destructor
/// <summary>
/// <para>Creates an instance of this class</para>
/// </summary>
/// <param name="main"></param>
public Power(Main main)
{
Main = main;
}
/// <summary>
/// <para>Disables all SystemEvents because they are static</para>
/// </summary>
/// <remarks>http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.displaysettingschanged%28v=vs.110%29.aspx</remarks>
~Power()
{
if (PowerModeChangedEnabled)
Win32_SystemEvents.PowerModeChanged -= Win32_SystemEvents_PowerModeChanged;
if (PowerBroadcastChangedEnabled)
{
UnregisterPowerSettingNotification(powerBroadcastChangedHandle);
Main.MessageReceived -= Main_MessageReceived;
}
}
#endregion
#region Methods
/// <summary>
/// </summary>
/// <returns></returns>
public override EventList EventNames()
{
EventList list = new EventList();
EventListRow row = list.NewEventListRow();
row.Name = "PowerModeChanged";
row.Text = "Power mode changed";
row.Description = "The user suspends or resumes the system";
row.Type = Manager.EventTypes.SingleValue;
list.AddEventListRow(row);
row = list.NewEventListRow();
row.Name = "Suspend";
row.Text = "Suspend";
row.Description = "The user suspends the system";
row.Type = Manager.EventTypes.Simple;
list.AddEventListRow(row);
row = list.NewEventListRow();
row.Name = "Resume";
row.Text = "Resume";
row.Description = "The user resumes the system";
row.Type = Manager.EventTypes.Simple;
list.AddEventListRow(row);
return list;
}
/// <summary>
/// </summary>
/// <returns></returns>
public override TreeNode GetStatus()
{
TreeNode tnMain = new TreeNode("Power");
TreeNode tnEvents = tnMain.Nodes.Add("Registered events");
if (PowerModeChangedEnabled)
{
TreeNode tnEvent = tnEvents.Nodes.Add("PowerModeChanged");
tnEvent.ToolTipText = "Microsoft.Win32.SystemEvents.PowerModeChanged";
}
if (PowerBroadcastChangedEnabled)
{
TreeNode tnEvent = tnEvents.Nodes.Add("PowerBroadcastChanged");
tnEvent.ToolTipText = "Registered in Win32 message service (WM_POWERBROADCAST)";
}
return tnMain;
}
#endregion
#region Event Handler
internal void Win32_SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
if (OnPowerModeChanged != null)
OnPowerModeChanged(this, new EventArgsValue<PowerModes>(e.Mode));
switch (e.Mode)
{
case PowerModes.Resume:
if (OnResume != null)
OnResume(this, new EventArgs());
break;
case PowerModes.Suspend:
if (OnSuspend != null)
OnSuspend(this, new EventArgs());
break;
case PowerModes.StatusChange:
if (OnPowerLineStatusChanged != null)
{
PowerLineStatus oldValuePLS = (PowerLineStatus)oldValues[EventType.PowerLineStatusChanged];
PowerLineStatus newValuePLS = Status.Power.PowerLineStatus;
if (oldValuePLS != newValuePLS)
{
OnPowerLineStatusChanged(this, new EventArgsValues<PowerLineStatus>(oldValuePLS, newValuePLS));
oldValues[EventType.PowerLineStatusChanged] = newValuePLS;
}
}
BatteryChargeStatus oldValueBCS = (BatteryChargeStatus)oldValues[EventType.BatteryStatusChanged];
BatteryChargeStatus newValueBCS = Status.Power.BatteryChargeStatus;
if (OnBatteryStatusChanged != null)
{
if (oldValueBCS != newValueBCS)
{
OnBatteryStatusChanged(this, new EventArgsValues<BatteryChargeStatus>(oldValueBCS, newValueBCS));
oldValues[EventType.BatteryStatusChanged] = newValueBCS;
}
}
if (OnBatteryAvailabilityChanged != null)
{
bool? oldValueBCSb = null, newValueBCSb = null;
if (oldValueBCS == BatteryChargeStatus.NoSystemBattery)
oldValueBCSb = false;
else if (oldValueBCS != BatteryChargeStatus.Unknown)
oldValueBCSb = true;
if (newValueBCS == BatteryChargeStatus.NoSystemBattery)
newValueBCSb = false;
else if (newValueBCS != BatteryChargeStatus.Unknown)
newValueBCSb = true;
if (oldValueBCSb != newValueBCSb)
{
OnBatteryAvailabilityChanged(this, new EventArgsValue<bool?>(newValueBCSb));
}
}
break;
}
}
internal static void Main_MessageReceived(object sender, EventArgsValue<Message> e)
{
if (e.Value.Msg != (int)Classes.System.WindowsMessages.WM_POWERBROADCAST)
return;
PBT wParam = (PBT)e.Value.WParam.ToInt32();
switch (wParam)
{
case PBT.POWERSETTINGCHANGE:
PowerBroadcast_Setting pbs = (PowerBroadcast_Setting)Marshal.PtrToStructure(e.Value.LParam, typeof(PowerBroadcast_Setting));
PowerScheme oldPlan = (PowerScheme)oldStaticValues[EventType.PowerSchemeChanged];
PowerScheme newPlan = Status.Power.ActivePowerScheme;
if (oldPlan == newPlan)
return;
if (OnPowerSchemeChanged != null)
OnPowerSchemeChanged(null, new EventArgsValues<PowerScheme>(oldPlan, newPlan));
oldStaticValues[EventType.PowerSchemeChanged] = newPlan;
break;
}
}
#endregion
}
}