Winui 3 открывает новое окно на дополнительном мониторе

У меня есть приложение Winui 3. Мне нужно открыть новое окно на дополнительном мониторе, как только пользователь нажмет кнопку. Я нашел сообщение ниже, которое работает для UWP. Открыть новое окно на дополнительном мониторе в UWP Однако этот код не работает в Winui 3.

private async void NewWindow()
{
    var myview = CoreApplication.CreateNewView();
    int newid = 0;
    await myview.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        Frame newframe = new Frame();
        newframe.Navigate(typeof(Newpage), null);

        Window.Current.Content = newframe;
        Window.Current.Activate();
        ApplicationView.GetForCurrentView().Title = "Z";

        newid = ApplicationView.GetForCurrentView().Id;
    });

    await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newid, ViewSizePreference.UseMinimum);

}

Я получаю сообщение об ошибке «System.InvalidOperationException: метод был вызван в неожиданное время». в var myview = CoreApplication.CreateNewView(); строке.

Я провел много исследований, но не смог найти ничего, связанного с отображением окна на дополнительном мониторе для Winui 3. Пожалуйста, помогите мне с отображением окна на другом мониторе с Winui 3.

Создать новое окно очень просто: stackoverflow.com/a/69235394/403671 и вы можете переместить это окно с помощью window.AppWindow.Move, т.е.: window.AppWindow.Move(new Windows.Graphics.PointInt32(3000, 3000));

Simon Mourier 21.05.2023 18:23

@SimonMourier Спасибо за комментарий. На самом деле я изо всех сил пытаюсь выяснить положение вторичного монитора. Не могли бы вы помочь мне с этим?

Chamal 21.05.2023 19:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Приложения UWP имеют только одно окно, а WinUI3 может создавать новые. Как открыть новое окно в WinUI3 с помощью WinRT/C++?.

Теперь, чтобы переместить окно на другой экран, теоретически вы должны иметь возможность использовать класс WinUI3 DisplayArea.

Но проблема в том, что его метод FindAll не работает (уже некоторое время...), как сообщается здесь; Итератор Microsoft.UI.Windowing.DisplayArea.FindAll выдает «Invalid Cast

Также есть DisplayManager, DisplayTarget и т. д. WinRT. но они не очень просты в использовании... И мы не можем использовать класс Winforms Screen...

Итак, еще одно решение — использовать «классическое» взаимодействие .NET, например:

var window = new Window();
window.Content = new TextBlock() { Text = "Hello" };
window.Activate();

var monitors = Monitor.All.ToArray();
if (monitors.Length > 1)
{
    var thisMonitor = Monitor.FromWindow(WinRT.Interop.WindowNative.GetWindowHandle(this));
    var otherMonitor = monitors.First(m => m.DeviceName != thisMonitor.DeviceName);
    // move to second display's upper left corner
    window.AppWindow.Move(new PointInt32(otherMonitor.WorkingArea.X, otherMonitor.WorkingArea.Y));
}

С этим Monitor классом:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Windows.Graphics;

public sealed class Monitor
{
    private Monitor(IntPtr handle)
    {
        Handle = handle;
        var mi = new MONITORINFOEX();
        mi.cbSize = Marshal.SizeOf(mi);
        if (!GetMonitorInfo(handle, ref mi))
            throw new Win32Exception(Marshal.GetLastWin32Error());

        DeviceName = mi.szDevice.ToString();
        Bounds = new RectInt32(mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top);
        WorkingArea = new RectInt32(mi.rcWork.left, mi.rcWork.top, mi.rcWork.right - mi.rcWork.left, mi.rcWork.bottom - mi.rcWork.top);
        IsPrimary = mi.dwFlags.HasFlag(MONITORINFOF.MONITORINFOF_PRIMARY);
    }

    public IntPtr Handle { get; }
    public bool IsPrimary { get; }
    public RectInt32 WorkingArea { get; }
    public RectInt32 Bounds { get; }
    public string DeviceName { get; }

    public static IEnumerable<Monitor> All
    {
        get
        {
            var all = new List<Monitor>();
            EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, (m, h, rc, p) =>
            {
                all.Add(new Monitor(m));
                return true;
            }, IntPtr.Zero);
            return all;
        }
    }

    public override string ToString() => DeviceName;
    public static IntPtr GetNearestFromWindow(IntPtr hwnd) => MonitorFromWindow(hwnd, MFW.MONITOR_DEFAULTTONEAREST);
    public static IntPtr GetDesktopMonitorHandle() => GetNearestFromWindow(GetDesktopWindow());
    public static IntPtr GetShellMonitorHandle() => GetNearestFromWindow(GetShellWindow());
    public static Monitor FromWindow(IntPtr hwnd, MFW flags = MFW.MONITOR_DEFAULTTONULL)
    {
        var h = MonitorFromWindow(hwnd, flags);
        return h != IntPtr.Zero ? new Monitor(h) : null;
    }

    [Flags]
    public enum MFW
    {
        MONITOR_DEFAULTTONULL = 0x00000000,
        MONITOR_DEFAULTTOPRIMARY = 0x00000001,
        MONITOR_DEFAULTTONEAREST = 0x00000002,
    }

    [Flags]
    public enum MONITORINFOF
    {
        MONITORINFOF_NONE = 0x00000000,
        MONITORINFOF_PRIMARY = 0x00000001,
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    private struct MONITORINFOEX
    {
        public int cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public MONITORINFOF dwFlags;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szDevice;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }

    private delegate bool MonitorEnumProc(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);

    [DllImport("user32")]
    private static extern IntPtr GetDesktopWindow();

    [DllImport("user32")]
    private static extern IntPtr GetShellWindow();

    [DllImport("user32")]
    private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);

    [DllImport("user32")]
    private static extern IntPtr MonitorFromWindow(IntPtr hwnd, MFW flags);

    [DllImport("user32", CharSet = CharSet.Unicode)]
    private static extern bool GetMonitorInfo(IntPtr hmonitor, ref MONITORINFOEX info);
}

Большое спасибо !!. Это решило мои проблемы. Однако мне пришлось сделать одну модификацию. AppWindow напрямую не доступен для окна (window.AppWindow не работает). Мне пришлось использовать Interop, чтобы получить окно приложения, как показано ниже. IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(окно); WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd); var appWindow = AppWindow.GetFromWindowId(windowId);

Chamal 22.05.2023 06:43

Свойство @Chamal AppWindow доступно в последних версиях WinAppSDK (learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt‌​/… ). Убедитесь, что вы обновили соответствующие пакеты nuget.

Simon Mourier 22.05.2023 08:31

Другие вопросы по теме