确定窗口在WPF中是否实际可见的最佳方法是什么

问题描述:

我正在尝试根据系统任务栏应用程序中的通知图标单击来切换小窗口的显示.这很容易实现,但是当显示小窗口并且另一个应用程序获得焦点并因此移到它的前面(z顺序)时,我希望切换开关假定小窗口现在已隐藏,即使它的可见性是仍设置为可见.否则,单击图标会将窗口可见性设置为隐藏,即使该窗口已经隐藏在另一个图标之后.我尝试捕获/覆盖激活和停用方法以保持跟踪,但是单击通知图标将始终导致停用事件首先触发.一种类似的使用焦点/失去焦点的方法也不起作用,因为该窗口似乎认为它仍然具有焦点,即使该窗口隐藏在活跃使用中的另一个应用程序窗口后面.最后,我不得不诉诸于本机代码和WindowFromPoint方法,如下所示:

I'm trying to toggle the display of a small window based on the click of a notify icon in a system tray app. This is simple enough to implement, however when the small window is displayed and another application takes focus and therefore moves in front of it (z-order) I want the toggle to assume that the small window is now hidden, even though it's visibility is still set to visible. Otherwise, clicking the icon would set the windows visiblity to hidden even though it is already hidden behind another. I've tried catching / overriding the activate and deactive methods to keep track but clicking the notify icon will always cause the deactive event to fire first. A similar approach using focus / lost focus didn't work either as the window seemed to think it still had focus even when hidden behind another applications window in active use. In the end I had to resort to native code and the WindowFromPoint method as follows:

using System.Windows.Interop;
using System.Runtime.InteropServices;
using System.Drawing;

[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(Point lpPoint);

public static bool IsWindowVisible(System.Windows.Window window) {
    WindowInteropHelper win = new WindowInteropHelper(window);
    int x = (int)(window.Left + (window.Width / 2));
    int y = (int)(window.Top + (window.Height / 2));
    Point p = new Point(x, y);
    return (win.Handle == WindowFromPoint(p));
}

这检查返回的窗口是否在所讨论的窗口的中心坐标处.即相关窗口的中心可见.

This checks if the window returned at the coordinates of the centre of the window in question matches said window. i.e. the centre of the window in question is visible.

这似乎有点不客气,有没有更好的方法来达到相同的结果?

This seems a little hacky, is there a nicer way to achieve the same result?

您可能不想依赖于窗口是否被阻塞,因为有许多因素可以改变窗口的大小,位置等,并且所有这些因素都可以相互关联可访问性功能变得更加复杂.

You may not want to rely on whether a window is obstructed as there are many factors that can change the window size, positing, etc. and all of them tie into accessibility features which add even more complexities.

相反,您可能要检查窗口是否具有焦点.这就是MSN Messenger知道是否在任务栏中闪烁橙色的方式.它会触发通知,如果没有焦点,任务栏会闪烁.

Instead, you may want to check whether or not the window has focus. This is how MSN Messenger knows whether or not to flash orange in the taskbar; it fires a notification and if it doesn't have focus, the taskbar flashes.