我正在WPF中实现Windows 7 / Vista样式的通知区域(“系统托盘”)弹出应用程序。到目前为止,我已经写过我的工作here(确定通知图标的位置,禁用调整大小等)。
然而,有一个问题我还没有完全解决,当第二次点击通知图标时隐藏窗口。如果单击(例如)Vista / 7中的音量图标以显示音量控制,请注意在第二次单击该图标时它会再次隐藏。
我处理窗口的Deactivated事件以隐藏窗口,并且在单击通知图标时确实停用了窗口。但是,单击通知图标当然会显示并激活窗口,因此最终发生的事情是鼠标停止时窗口消失,释放鼠标时重新出现(完成鼠标点击事件)。
我的第一个想法是我可能会使用通知图标的MouseDown事件(我正在使用System.Windows.Forms.NotifyIcon)并检查窗口是否在那时可见 - 如果是,我可以将其解释为用户再次单击通知图标以隐藏窗口。不幸的是,在实际点击鼠标之前,MouseDown事件似乎不会触发(换句话说,它与MouseClick事件的工作方式相同),此时窗口已经被停用并因此被隐藏。这似乎排除了这个解决方案。
我的下一个想法(以及我最终使用的方法)是在停用窗口时获取光标位置(GetCursorPos)并检查该点是否在通知图标的边界内。同时,我还使用GetForegroundWindow来查找当前活动的窗口 - 如果确实要单击通知图标,它应该是任务栏(具有类名称Shell_TrayWnd的顶级窗口)或通知区域飞出(顶级窗口,类名为NotifyIconOverflowWindow;仅限Windows 7+)。简而言之,如果光标位于通知图标上并且通知区域处于活动状态,我假设用户将通知图标鼠标按下以隐藏窗口。如果这些条件为真,则以下MouseClick事件将不会导致窗口显示/激活。
此解决方案至少存在一个问题:如果光标悬停在通知图标上并且用户按下Windows键以打开开始菜单(或使用Windows键+数字快捷方式打开应用程序),程序将错误地将其解释为鼠标按下通知图标(因为任务栏由这些键盘快捷键激活)。这意味着下次用户实际点击通知图标时,将不会显示该窗口。 (再次单击通知图标将显示它。)
我希望我写的东西有道理;如果没有,我很乐意尝试进一步澄清情况。
我很想知道是否有人对如何解决这个问题有任何其他想法。
我怀疑它可能不可能:在我看来,本机Windows 7通知区域弹出应用程序本身使用简单的计时器实现。当音量控制打开时,单击(例如)音量图标将仅在窗口取消激活和鼠标单击之间的时间小于约2秒时关闭音量控制。将鼠标按住图标一段较长时间然后释放将再次显示音量控制,即使它在鼠标按下之前打开也是如此。
答案 0 :(得分:1)
这不是音量控制窗口的工作方式。当您单击任何地方时,它会消失,包括通知图标。图标无关紧要。这是一个标准的Win32技巧,它捕获鼠标,以便它可以看到窗口外的点击。
WPF中的Mouse.Capture。这并不容易,因为它需要一个IInputElement而不是一个窗口句柄。