2012-06-11 2 views
2

Я пытаюсь обнаружить, когда крышка ноутбука открывается и закрывается, должна быть реальной. Я могу правильно зарегистрировать это событие, но потом я не получаю уведомление, когда закрываю окно ноутбука.RegisterPowerSettingsNotification C# pinvoke

Вот DLL Импорт

(код DLL: 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:

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()); 
} 

Вот вывод из этого:

Registered: 6867560

LastError:0

Выглядит хорошо для меня.

Тогда где я должен Получать сообщение:

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, если он зарегистрирован: [

+0

Вы не разместили ни одного кода, предлагающего вам зарегистрировать свой WndProc с HWND. Это просто отсутствует в образце? В противном случае это может быть вашей проблемой ... –

+0

Ой не понимал, что это был шаг? – y2k

+0

Ах, тогда я отвечу. Минуточку. –

ответ

2

Я думаю, что вы имеете сделанное с помощью RegisterPowerSettingNotification, приводит к тому, что Windows включает в себя сообщения для WM_POWERBROADCAST для вашего WndProc, но вам все равно необходимо на самом деле подключить WndProc.

Похоже, вы используете WinForms (потому что ваш образец имеет «this.Handle»), и в этом случае вы можете просто переопределить защищенный метод WndProc в своей форме.

Если вы используете WPF, вы можете сделать это, получив HwndSource для корневого окна, а затем вызвав AddHook.

Вы хотите прочитать документацию о WndProc в WinForms (http://msdn.microsoft.com/en-us/library/system.windows.forms.form.wndproc.aspx). Он будет называться лот, поэтому вам нужно будет запускать свой код только в том случае, если это сообщение вам очень важно, и безоговорочно вызвать base.WndProc.

+0

yes winform, просто приложение в системном трее. спасибо за то, что он понял это так быстро и дал мне знать, что я должен был подключить это дополнительно. – y2k

+0

Рад, что это помогло. Если вы просто делаете системный лоток в WinForms, и вы уже используете p/invoking для других вещей, вы можете посмотреть в p/invoke Shell_NotifyIcon, а не на использование API-интерфейсов WinForms для этих функций. IIRC для API WinForms было много, потому что оно все еще поддерживало Win2K и с тех пор не сильно возросло. Вероятно, вы можете получить лучшее уведомление с новыми флагами, и это не так много работает. –