Определить, видно ли открытое окно WPF на каком-либо мониторе

Есть ли способ определить, видно ли в данный момент открытое окно WPF на любом из мониторов, подключенных к рабочему столу? Под видимым я подразумеваю, что прямоугольник границ окна пересекается с прямоугольником рабочего стола любого из мониторов.

Мне нужна эта функциональность, чтобы определить, нужно ли перемещать окно, потому что конфигурация монитора (ограничивает рабочие области, количество мониторов )изменяется между перезапусками моего приложения (, что сохраняет позиции окон ).

Я придумал приведенный ниже код, и он, кажется, работает, но у него есть несколько проблем.:

  1. Мне нужно сослаться на формы Windows.
  2. Мне нужны настройки DPI рабочего стола и преобразование оконных форм фактических пикселей в виртуальные пиксели WPF.
  3. Мне нужен реальный экземпляр 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*)не работает, поскольку при использовании нескольких мониторов «рабочий стол» не является простым прямоугольником. Это может быть полигон.На виртуальном экране будут слепые зоны, потому что

  1. подключенные экраны могут иметь разное разрешение,
  2. вы можете настроить положение каждого экрана.
7
задан bitbonk 21 December 2016 в 13:44
поделиться