RegisterPowerSettingsNotification C#pinvoke

RegisterPowerSettingsNotification C#pinvoke

问题描述:

我正在尝试检测笔记本电脑机盖何时打开和关闭,应该非常简单.看来我可以正确注册该事件,但是关闭笔记本电脑窗口时却没有收到通知.

I am trying to detect when the laptop lid opens and closes, should be real simple. I can register that event properly it seems, but then I don't get notification when I close my laptop window.

这是DLL导入

(DLL代码: http://www.pinvoke.net/default. aspx/user32/registerpowersettingnotification.html ) (GUID_LIDCLOSE_ACTION: http://social.msdn.microsoft.com/Forums/zh-CN/tabletandtouch/thread/0bbf90be-9322-47fb-bfa4-016b57211b3a )

(DLL code: http://www.pinvoke.net/default.aspx/user32/registerpowersettingnotification.html ) (GUID_LIDCLOSE_ACTION: http://social.msdn.microsoft.com/Forums/en-US/tabletandtouch/thread/0bbf90be-9322-47fb-bfa4-016b57211b3a )

[DllImport(@"User32", SetLastError = true, 
  EntryPoint = "RegisterPowerSettingNotification",
  CallingConvention = CallingConvention.StdCall)]

private static extern IntPtr RegisterPowerSettingNotification(
    IntPtr hRecipient,
    ref Guid PowerSettingGuid,
    Int32 Flags);

static Guid GUID_LIDCLOSE_ACTION =
    new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 
             0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);

private const int WM_POWERBROADCAST = 0x0218;
private const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
const int PBT_POWERSETTINGCHANGE = 0x8013; // DPPE

[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct POWERBROADCAST_SETTING
{
    public Guid PowerSetting;
    public uint DataLength;
    public byte Data;
}

然后这是我注册GUID_LIDCLOSE_ACTION事件的方式:

And then here is how I am registering the GUID_LIDCLOSE_ACTION event:

private void registerLidClosedNotification()
{
    IntPtr hWnd = this.Handle;
    IntPtr ret = RegisterPowerSettingNotification(hWnd, 
                           ref GUID_LIDCLOSE_ACTION,
                           DEVICE_NOTIFY_WINDOW_HANDLE);

    Debug.WriteLine("Registered: " + ret.ToString());
    Debug.WriteLIne("LastError:" + Marshal.GetLastWin32Error().ToString());
}

这是输出:

注册:6867560

Registered: 6867560

LastError:0

LastError:0

对我很好.

然后我应该在哪里接收消息:

Then where I'm supposed to recieve the message:

private static IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {

            Debug.WriteLine("Entered: WndProc");  // we never make it even this far!

因此,如果注册了WndProc函数,为什么不将其添加到WndProc函数:[

So why isn't it making it to the WndProc function if it is registered :[

我认为您对RegisterPowerSettingNotification所做的操作是导致Windows将WM_POWERBROADCAST的消息包含到WndProc的原因,但实际上您仍然需要同时挂接WndProc

I think what you've done with the RegisterPowerSettingNotification is cause Windows to include messages for WM_POWERBROADCAST to your WndProc, but you still need to actually hook the WndProc as well.

您似乎正在使用WinForms(因为您的示例具有"this.Handle"),在这种情况下,您可以在窗体上覆盖受保护的WndProc方法.

It looks like you're using WinForms (because your sample has "this.Handle"), in which case you can just override the protected WndProc method on your Form.

如果您使用的是WPF,则可以通过获取根Window的HwndSource然后调用AddHook来实现.

If you're using WPF, then you can do this by getting an HwndSource for the root Window and then calling AddHook.

您将需要阅读有关WinForms中WndProc的文档(http://msdn.microsoft.com/zh-cn/library/system.windows.forms.form.wndproc.aspx).它会被称为 lot ,因此您只想在您关心的消息上运行代码,而无条件调用base.WndProc.

You'll want to read up on the documentation about the WndProc in WinForms (http://msdn.microsoft.com/en-us/library/system.windows.forms.form.wndproc.aspx). It will get called a lot, so you'll want to only run your code when it's the message you care about, and unconditionally call base.WndProc.