Вот кодНевозможно зарегистрировать для настройки уведомлений питания в WinForms C#
[DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification",
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid, Int32 Flags);
static Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);
private const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
private const int WM_POWERBROADCAST = 0x0218;
const int PBT_POWERSETTINGCHANGE = 0x8013;
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
private bool? _previousLidState = null;
public TrayIcon()
{
RegisterForPowerNotifications();
}
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_POWERBROADCAST:
OnPowerBroadcast(m.WParam, m.LParam);
break;
default:
break;
}
base.WndProc(ref m);
}
private void RegisterForPowerNotifications()
{
IntPtr handle = this.Handle;
Debug.WriteLine("Handle: " + handle.ToString()); //If this line is omitted, then lastError = 1008 which is ERROR_NO_TOKEN, otherwise, lastError = 0
IntPtr hLIDSWITCHSTATECHANGE = RegisterPowerSettingNotification(handle,
ref GUID_LIDSWITCH_STATE_CHANGE,
DEVICE_NOTIFY_WINDOW_HANDLE);
Debug.WriteLine("Registered: " + hLIDSWITCHSTATECHANGE.ToString());
Debug.WriteLine("LastError:" + Marshal.GetLastWin32Error().ToString());
}
private void OnPowerBroadcast(IntPtr wParam, IntPtr lParam)
{
if ((int)wParam == PBT_POWERSETTINGCHANGE)
{
POWERBROADCAST_SETTING ps = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING));
IntPtr pData = (IntPtr)((int)lParam + Marshal.SizeOf(ps));
Int32 iData = (Int32)Marshal.PtrToStructure(pData, typeof(Int32));
if (ps.PowerSetting == GUID_LIDSWITCH_STATE_CHANGE)
{
bool isLidOpen = ps.Data != 0;
if (!isLidOpen == _previousLidState)
{
LidStatusChanged(isLidOpen);
}
_previousLidState = isLidOpen;
}
}
}
private void LidStatusChanged(bool isLidOpen)
{
if (isLidOpen)
{
//Do some action on lid open event
MessageBox.Show("Lid is now open");
}
else
{
//Do some action on lid close event
MessageBox.Show("Lid is now closed");
}
}
}
}
Я понятия не имею, что проблема есть. Я звоню на WndProc
, но ничего не происходит, когда крышка закрыта или открыта. LidStatusChanged
никогда не называется.
Я следил за this post, но это не помогает, поскольку все соответствует.
Я понятия не имею, что, черт возьми, я сделал не так. Вся помощь очень ценится.
Можем ли мы иметь [mcve]? Он становится минимальным, когда вы больше не можете удалять код, демонстрирующий поведение. – IInspectable
@ Необычный, удаленный, что я мог. Все, что я опубликовал, необходимо для того, чтобы показать, что поведение, которое передается в эфир, никогда не отправляется в мое приложение. – Seth
Вы также можете подумать о том, имеет ли смысл перемещать часть этого кода на C++/CLI, чтобы вам не пришлось копировать столько материалов из файлов Windows ** .h **. –