仅用于消息循环的WPF窗口句柄

时间:2015-02-06 11:17:03

标签: c# wpf windows winapi

我正在编写一个WPF应用程序,它会在系统托盘中放置一个图标,作为练习,我希望这样做而不依赖于System.Windows.Forms并使用其NotifyIcon或{{1} } class。

这很容易 - NativeWindow从C#调用起来并不困难 - 事实上,我已经成功完成了我的任务。

作为这项工作的一部分,我不得不创建一个窗口句柄,其唯一目的是从系统托盘接收消息。我按如下方式创建本机窗口:

Shell_NotifyIcon

消息循环挂钩在// 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; } 的构造函数的前三个参数分别是本机Win32窗口的类样式,样式和扩展样式。对于仅用作窗口消息目标的不可见窗口,它们应该是什么?

我的默认值为零,零和...... er ..零可以正常工作,但是我使用Spy ++来检查HwndSource的作用,看来它创建的Windows.Forms.NotifyIcon具有以下内容: / p>

NativeWindow

对于不可见的窗口,这些是否重要? (我想不是。)

1 个答案:

答案 0 :(得分:5)

Windows样式标志的日期是1986年,当时Windows v1.0发布。在过去的29年里,有很多appcompat黑客的很多和10个主要版本,当应用程序指定了不同的版本时,Windows会默默地覆盖样式标记。然而,没有什么比这更糟糕的,请注意WS_OVERLAPPED样式标志的值为0.这要求一个普通窗口,您自动为这样的窗口获取适当的样式标志。

您的HwndSource窗口具有完全相同的样式标志,也许您在Spy ++中找不到正确的样式标志。所以你没有问题。不,当窗口永远不可见时,它们无关紧要。

请注意代码中的错误,因为您在调用PostMessage()后立即销毁窗口,所以您发布的WM_CLOSE消息实际上从未被处理过。只是删除它,没有必要很好地询问窗口,它不会反对。但是,您必须使用NIM_DELETE调用Shell_NotifyIcon()来删除托盘图标。如果不这样做会留下一个“幽灵”图标,只有当你将鼠标移到它上面时它才会消失。

请注意,NotifyIcon并不像您想象的那样微不足道,它有一个non-obvious bug workaround,您可能会忽略它。当上下文菜单拒绝关闭时,您会注意到。