2015-02-06 69 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