代码之家  ›  专栏  ›  技术社区  ›  Brad

检测笔记本电脑盖的关闭和打开

  •  26
  • Brad  · 技术社区  · 14 年前

    是否可以检测笔记本电脑的盖子是打开还是关闭的?从我读到的,这是不可能的,但也帮助了我以前不可能的。

    我唯一发现的可能是正确的方向是 MSDN blog post about IOCTLs needed to report power buttons . 有没有可能在操作系统调用它们时“嗅探”它们?

    我使用的是vb.net,但会接受任何语言的建议。谢谢你的时间和建议。

    编辑 :我的软件将(最终)覆盖在盖子关闭时发生的操作(基于用户偏好),因此监听在盖子关闭时通常发生的挂起和其他操作不是一个选项。

    4 回复  |  直到 10 年前
        1
  •  15
  •   broslav    10 年前

    完成WPF应用程序的工作代码,显示如何监听LID打开/关闭事件:

    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);
                }
            }
        }
    }
    
        2
  •  8
  •   Zabba fl00r    14 年前

    使用wm_powerbroadcast。以下链接可以帮助您: Lid Close Action change notification

        3
  •  5
  •   Icemanind    14 年前

    请记住,大多数笔记本电脑,当盖子关闭时,会按下一个按钮。这个按钮通常只是一个睡眠按钮。wmi类公开了acpi,您最好使用powermanagement类。不幸的是,当操作系统设置为“什么都不做”时,类不会引发事件。唯一的解决方法是使用DDK(驱动程序开发工具包)创建一个过滤器来拦截ioctl_get_sys_button_事件事件。以下是两个帮助您开始的链接:

    http://blogs.msdn.com/b/doronh/archive/2006/09/08/746834.aspx

    http://support.microsoft.com/kb/302092

        4
  •  0
  •   Lukasz Madon    14 年前

    Power Managment

    处理节电事件 目前的重点是在应用程序运行时节省电池寿命。您还应该考虑一个额外的问题:当计算机挂起操作时,应用程序的行为如何。这里需要考虑两个关键场景:

    • 当计算机空闲一段时间后,主动电源方案可能会指定硬件进入待机或休眠模式。
    • 当用户采取使计算机进入挂起操作的操作时,例如 关闭盖子 或者按下电源按钮。

    我希望它能给你一些方向:)