2015-02-06 59 views
3

我正在編寫一個WPF應用程序,它將在系統托盤中放置一個圖標,作爲練習,我希望在不依賴於System.Windows.Forms並使用其NotifyIconNativeWindow類的情況下執行此操作。僅用於消息循環的WPF窗口句柄

這相當簡單 - Shell_NotifyIcon不難從C#調用 - 而且,事實上,我成功地完成了我的任務。

作爲這項工作的一部分,我必須創建一個窗口句柄,以便從系統托盤接收消息。我創建了原生窗口如下:

// Create a 'Native' window 
_hwndSource = new HwndSource(0, 0, 0, 0, 0, 0, 0, null, parentHandle); 
_hwndSource.AddHook(WndProc); 

消息循環掛在AddHook()和消息在看起來像這樣的函數處理:

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
{ 
    // Handle windows messages in this... 
} 

最後,當談到時間摧毀的東西,我關閉窗口發佈WM_CLOSE消息和處置HwndSource

if (null != _hwndSource) 
{ 
    UnsafeNativeMethods.PostMessage(_hwndSource.Handle, WindowMessage.WM_CLOSE, 0, 0); 
    _hwndSource.Dispose(); 
    _hwndSource = null; 
} 

我的問題是這樣的:前三個參數的HwndSource構造函數是類風格,風格和本地的Win32窗口的擴展風格,分別。對於只能用作窗口消息目標的不可見窗口,它們應該是什麼?

我的爲零,零和......呃..零違約做的工作,但我已經使用間諜++檢查什麼Windows.Forms.NotifyIcon不和似乎NativeWindow它創建具備以下條件:

Class Style:  <zero> 
Styles:   WS_CAPTION, WS_CLIPSIBLINGS, 
       WS_OVERLAPPED 
Extended Styles: WS_EX_LEFT, WS_EX_LTRREADING, 
       WS_EX_RIGHTSCROLLBAR, WS_EX_WINDOWEDGE 

對於不可見的窗口來說,這些都很重要嗎? (我認爲不是。)

回答

4

Windows風格標誌的日期從1986年開始,當時Windows v1.0發佈。在過去的29年和10個主要版本中,appcompat黑客已有批次,當應用程序指定不合適時,Windows會默默覆蓋樣式標誌。然而,關於這一點沒什麼特別的,請注意WS_OVERLAPPED樣式標誌的值是0.要求一個普通的窗口,你會自動爲這樣一個窗口獲得適當的樣式標誌。

您的HwndSource窗口具有完全相同的樣式標誌,也許您在Spy ++中找不到正確的樣式標誌。所以你沒有問題。不,當窗口不可見時,它們並不重要。

請注意您的代碼中存在一個錯誤,因爲您在調用PostMessage()後立即銷燬窗口,您發佈的WM_CLOSE消息從未實際處理過。只要刪除它,在很好地問窗口沒有意義,它不會反對。但是,您必須使用NIM_DELETE調用Shell_NotifyIcon()以刪除托盤圖標。如果不這樣做,會留下一個「鬼」圖標,只有在將鼠標移到該圖標上時纔會消失。

請注意,NotifyIcon並不像您認爲的那樣微不足道,它有一個non-obvious bug workaround,您可能會忽略。當上下文菜單拒絕關閉時,您會注意到。

+1

在本地Windows API編程中,您將在此場景中使用[message-only window](https://msdn.microsoft.com/en-us/library/windows/desktop/ms632599.aspx#message_only) 。這可以用[Hw​​ndSource](https://msdn.microsoft.com/en-us/library/vstudio/system.windows.interop.hwndsource。aspx)呢? [源代碼](http://referencesource.microsoft.com/#PresentationCore/Core/CSharp/System/Windows/Interop/HwndSource.cs,ee020061aa75cef1)對我來說並不是非常有啓發性。 – IInspectable 2015-02-06 15:40:19

+0

是的,HwndSource不反對。使用'新的IntPtr(-3)'而不是* parentHandle * – 2015-02-06 15:46:22

+0

謝謝,所有。這些正是我所要求的事實。我忘記了HWND_MESSAGE - 這可能對父HWWD更正確。事實上,我確實知道「非顯而易見的錯誤解決方法」,不過謝謝,無論如何 - 我確信它會對這個問題的其他讀者有所幫助,NIM_DELETE信息也是我的代碼的一部分,但我不認爲它與這個問題有關。另外,如果你說我不需要發佈WM_CLOSE,因爲我正在處理HwndSource,那麼我會把它(post-message)拿出來。 (WinForms的NativeWindow發佈WM_CLOSE記錄。) – Xharlie 2015-02-09 12:58:34