我正在编写一个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
对于不可见的窗口,这些是否重要? (我想不是。)
答案 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,您可能会忽略它。当上下文菜单拒绝关闭时,您会注意到。