有没有办法确定一个打开的WPF窗口当前是否在任何连接的显示器上可见?通过“可见”,我的意思是窗口的边界矩形与任何一个监视器的桌面矩形相交。我需要这个功能来确定一个窗口是否需要重新定位,因为应用程序重启(保存窗口位置)之间的监视器配置(工作区边界,监视器数量)已更改。我想出了下面的代码,它似乎有效,但有几个问题:
- 我需要引用Windows Forms。
- 我需要桌面的DPI设置,并将Windows Forms实际像素转换为WPF虚拟像素。
- 我需要一个已经呈现过的Visual实例执行转换。
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
internal static class Desktop
{
private static Size dpiFactor = new Size(1.0, 1.0);
private static bool isInitialized;
public static IEnumerable<Rect> WorkingAreas
{
get
{
return
Screen.AllScreens.Select(
screen =>
new Rect(
screen.WorkingArea.Left * dpiFactor.Width,
screen.WorkingArea.Top * dpiFactor.Height,
screen.WorkingArea.Width * dpiFactor.Width,
screen.WorkingArea.Height * dpiFactor.Height));
}
}
public static void TryInitialize(Visual visual)
{
if (isInitialized)
{
return;
}
var ps = PresentationSource.FromVisual(visual);
if (ps == null)
{
return;
}
var ct = ps.CompositionTarget;
if (ct == null)
{
return;
}
var m = ct.TransformToDevice;
dpiFactor = new Size(m.M11, m.M22);
isInitialized = true;
}
}
使用已初始化的Desktop
类:
private bool IsLocationValid(Rect windowRectangle)
{
foreach (var workingArea in Desktop.WorkingAreas)
{
var intersection = Rect.Intersect(windowRectangle, workingArea);
var minVisible = new Size(10.0, 10.0);
if (intersection.Width >= minVisible.Width &&
intersection.Height >= minVisible.Height)
{
return true;
}
}
return false;
}
更新
使用虚拟屏幕(SystemParameters.VirtualScreen*
)无法正常工作,因为在使用多个监视器时,“桌面”不是一个简单的矩形,而可能是一个多边形。由于:
- 已连接的屏幕可能具有不同的分辨率。
- 您可以配置每个屏幕的位置。
虚拟屏幕中会有盲区。