是否可以检测笔记本电脑的盖子何时打开或关闭?从我所读到的,这是不可能的,但是SO已经帮助我完成了不可能的事情。
我发现的唯一可能是正确方向的是MSDN blog post about IOCTLs needed to report power buttons。是否有可能在操作系统调用它们时“嗅探”这些?
我正在使用VB.NET,但会接受任何语言的建议。感谢您的时间和建议。
编辑:我的软件将(最终)覆盖盖子关闭时发生的操作(基于用户偏好),因此会监听挂盖和盖子时通常会发生的其他操作关闭不是一种选择。
答案 0 :(得分:15)
WPF应用程序的完整工作C#代码,显示如何收听盖子打开/关闭事件:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
[DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification",
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid,
Int32 Flags);
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);
const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
const int WM_POWERBROADCAST = 0x0218;
const int PBT_POWERSETTINGCHANGE = 0x8013;
private bool? _previousLidState = null;
public MainWindow()
{
InitializeComponent();
this.SourceInitialized += MainWindow_SourceInitialized;
}
void MainWindow_SourceInitialized(object sender, EventArgs e)
{
RegisterForPowerNotifications();
IntPtr hwnd = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
}
private void RegisterForPowerNotifications()
{
IntPtr handle = new WindowInteropHelper(Application.Current.Windows[0]).Handle;
IntPtr hLIDSWITCHSTATECHANGE = RegisterPowerSettingNotification(handle,
ref GUID_LIDSWITCH_STATE_CHANGE,
DEVICE_NOTIFY_WINDOW_HANDLE);
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_POWERBROADCAST:
OnPowerBroadcast(wParam, lParam);
break;
default:
break;
}
return IntPtr.Zero;
}
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
Debug.WriteLine("{0}: Lid opened!", DateTime.Now);
}
else
{
//Do some action on lid close event
Debug.WriteLine("{0}: Lid closed!", DateTime.Now);
}
}
}
}
答案 1 :(得分:8)
使用WM_POWERBROADCAST。这是一个可以帮助您的链接:Lid Close Action change notification
答案 2 :(得分:5)
请记住,大多数笔记本电脑,当盖子关闭时,它会按下一个按钮。这个按钮通常只是一个睡眠按钮。 WMI类公开ACPI,您理想地希望使用PowerManagement类。不幸的是,当操作系统设置为“什么都不做”时,该类不会引发事件。解决这个问题的唯一方法是使用DDK(驱动程序开发工具包)创建一个拦截IOCTL_GET_SYS_BUTTON_EVENT事件的过滤器。以下是两个可帮助您入门的链接:
http://blogs.msdn.com/b/doronh/archive/2006/09/08/746834.aspx
和
答案 3 :(得分:1)
这是一个解决方案;
https://www.codeproject.com/Tips/480049/Shut-Down-Restart-Log-off-or-Lock-your-computer-in
我做了;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
[DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterPowerSettingNotification",
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterPowerSettingNotification(IntPtr hRecipient, ref Guid PowerSettingGuid,
Int32 Flags);
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);
const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
const int WM_POWERBROADCAST = 0x0218;
const int PBT_POWERSETTINGCHANGE = 0x8013;
private bool? _previousLidState = null;
public MainWindow()
{
InitializeComponent();
this.SourceInitialized += MainWindow_SourceInitialized;
}
void MainWindow_SourceInitialized(object sender, EventArgs e)
{
RegisterForPowerNotifications();
IntPtr hwnd = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
}
private void RegisterForPowerNotifications()
{
IntPtr handle = new WindowInteropHelper(Application.Current.Windows[0]).Handle;
IntPtr hLIDSWITCHSTATECHANGE = RegisterPowerSettingNotification(handle,
ref GUID_LIDSWITCH_STATE_CHANGE,
DEVICE_NOTIFY_WINDOW_HANDLE);
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_POWERBROADCAST:
OnPowerBroadcast(wParam, lParam);
break;
default:
break;
}
return IntPtr.Zero;
}
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
Debug.WriteLine("{0}: Lid opened!", DateTime.Now);
}
else
{
//Do some action on lid close event
Debug.WriteLine("{0}: Lid closed!", DateTime.Now);
}
}
}
}
当您合上盖子时,它是锁定屏幕。
答案 4 :(得分:0)
处理省电事件 到目前为止,重点一直是在应用程序运行时节省电池寿命。您还应该考虑以下因素:计算机暂停操作时应用程序的行为方式。这里有两个关键方案需要考虑:
我希望它给你一些方向:)