2017-02-16 5 views
0

の電力通知設定を登録することはできません、私は問題が何であるか見当がつかないコードは、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に従っていますが、それはすべてが一致するのを助けません。

私が間違っていたことは分かりません。すべての援助は非常に高く評価されます。

+1

[mcve]を使用できますか?それは、もはや動作を示すコードを削除することができなくなると、最小限に抑えられます。 – IInspectable

+0

@IInspectable、私ができることを削除しました。私が投稿したものはすべて、パワーブロードキャストのものが私のアプリに送信されることはないという動作を示すために必要です。 – Seth

+0

また、Windows **。h **ファイルから多くのものをコピーする必要がないように、このコードの一部をC++/CLIに移動することが理にかなっているかどうかを検討することもできます。 –

答えて

3
ShowInTaskbar = Visible = false; 

スニペットにバグが表示されなくなりました。この問題を引き起こしたのはShowInTaskbarプロパティの割り当てです。これは "難しい"プロパティで、CreateWindowEx()に渡されるスタイルフラグでのみ指定できます。そのため、Winformsは現在のウィンドウを破棄して新しいウィンドウを作成しますが、現在は別のハンドル値を取得します。これ以上の通知はありません。

おそらく、ウィンドウを見えないようにしようとすると、この問題が発生している可能性があります。それを行うための適切な方法は次のとおりです。

protected override void SetVisibleCore(bool value) { 
    if (!IsHandleCreated) { 
     this.CreateHandle(); 
     value = false; 
    } 
    base.SetVisibleCore(value); 
} 

削除のOnLoad()、ウィンドウが実際に見えるようになるまで、もはや必要ではないと呼ばれます。何らかの理由でハンドル値が変更されたとしても(いくつかの「難しい」プロパティがあります)、それでも通知が得られるようにしたいとします。コンストラクタからコードを削除して実行するもの:

protected override void OnHandleCreated(EventArgs e) { 
    base.OnHandleCreated(e); 
    RegisterForPowerNotifications(); 
} 
+0

Aha。私は問題であると感じました.. 'ShowInTaskbar = Visible = false;'行をコメントアウトしたときにうまくいきました。しかし、希望の効果を得る方法を知らなかった。本当にありがとう!それが美しく動作するようにソリューションとしてマーク! 'SetVisibleCore'についての新しい情報をありがとう!私はそれを大いに感謝します! – Seth

関連する問題