如何确定WPF中的窗口是否实际可见?

12

我试图在系统托盘应用程序中的通知图标点击时切换一个小窗口的显示。这很容易实现,但当小窗口已经被显示并且其他应用程序获得焦点并遮挡在它的前面(z-order)时,我希望切换可以假定该小窗口现在已隐藏,尽管它的可见性仍然设置为可见。否则,即使它已经隐藏在另一个窗口后面,单击该图标也会将窗口的可见性设置为隐藏。我尝试使用激活和反激活方法来捕获/覆盖来跟踪,但是单击通知图标总是会导致先触发反激活事件。使用聚焦/失去聚焦的类似方法也无效,因为即使隐藏在另一个正在使用的应用程序窗口后面,该窗口似乎仍然认为它具有焦点。最终,我不得不使用本地代码和WindowFromPoint方法,如下所示:

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));
}

这个检查方法是确认窗口在给定坐标的中心点处是否匹配该窗口,换句话说,它检查该窗口的中心是否可见。

这种方法似乎有些不够优雅,有没有更好的方式实现相同的结果呢?


+1 非常有趣的问题。我找不到更好的方法,所以我使用了你的方法 :-) - Joon
3
  1. 我支持Joon,好的解决方案。
  2. 有些人可能想查询的不仅仅是中心点(例如窗口的角落)。
  3. 注意不要使用System.Windows.Point,否则会出现一些难看的异常。
- Hertzel Guinness
1个回答

1

您可能不想依赖于窗口是否被遮挡,因为有许多因素可以改变窗口大小、位置等,而所有这些因素都与可访问性功能相关,这会增加更多的复杂性。

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


1
我发现当我检查窗口的焦点属性时,即使它在另一个窗口后面,它也会返回具有焦点的信息。然后我尝试了激活和非激活事件,这个方法是有效的,但是当我点击切换系统托盘图标时,非激活事件会被触发,即使窗口仍然可见。 - LaserJesus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接