简体   繁体   English

UWP AppWindow 获取正确的监视器/显示区域

[英]UWP AppWindow Get correct monitor/Display region

Idea is very simple open one or more windows in the app, save their size, position and monitor placement when closing the app, and then when they are opened again, every window should open on the same position, size and monitor they were closed on, I was able to do the size and position succesfully but monitor/DisplayRegion is giving me incorrect monitor, even when my secondary window is on 2nd monitor, It returns the first monitor (display region), I just need to figure out at the time of saving the placement data, how can I figure out that my specific secondary AppWindow is on which monitor/DisplayRegion?想法很简单,在应用程序中打开一个或多个窗口,关闭应用程序时保存它们的大小、位置和监视器位置,然后当它们再次打开时,每个窗口都应该在它们关闭时的相同位置、大小和监视器上打开,我能够成功地完成大小位置,但是监视器/DisplayRegion给我的监视器不正确,即使我的辅助窗口在第二个监视器上,它也会返回第一个监视器(显示区域),我只需要当时弄清楚保存放置数据时,如何确定我的特定辅助AppWindow位于哪个监视器/DisplayRegion 上?

Following code runs when app is closing以下代码在应用程序关闭时运行

internal static void UpdateAppWindowsPlacements()
    {
        foreach (var item in AppWindowViewModels)
        {
            ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Show_{item.Key}"] = item.AppWindow != null;
            if (item.AppWindow != null)
            {
                var placement = item.AppWindow.GetPlacement();
                var regions = new List<DisplayRegion>(); 
                foreach (var dr in item.AppWindow.WindowingEnvironment.GetDisplayRegions())
                {
                    regions.Add(dr);// this list is just for testing, it gives me boh monitors/DisplayRegions, but no way to find out where this window resides.
                }
                //Size is full screen size and can be bigger bcz it also includes taskbar etc.
                //Display region excludes taskbar etc
                var displayRegion = placement.DisplayRegion;
                var displayRegionWidth = displayRegion.WorkAreaSize.Width;
                var displayRegionHeight = displayRegion.WorkAreaSize.Height;

                var sizeWidth = placement.Size.Width;
                var sizeHeight = placement.Size.Height;

                ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Width_{item.Key}"] = sizeWidth > displayRegionWidth ? displayRegionWidth : sizeWidth;
                ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Height_{item.Key}"] = sizeHeight > displayRegionHeight ? displayRegionHeight : sizeHeight;

                ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_X_{item.Key}"] = placement.Offset.X;
                ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Y_{item.Key}"] = placement.Offset.Y;
            }
        }
    }

Opening secondary windows and positioning them as per saved position打开辅助窗口并根据保存的位置定位它们

internal static async Task OpenSecondaryWindows(int total)
    {
        for (int i = 0; i < total; i++)
        {
            var appWindowViewModel = new AppWindowViewModel(i.ToString());
            AppWindowViewModels.Add(appWindowViewModel);
            var open = ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Show_{i}"];
            if (open == null)
            {
                ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Show_{i}"] = true;
                open = true;
            }
            if ((bool)open)
            {
                await View(appWindowViewModel);
            }
        }
    }
    private static async Task View(AppWindowViewModel appWindowViewModel)
    {
        if (appWindowViewModel.AppWindow is null)
        {
            appWindowViewModel.AppWindow = await AppWindow.TryCreateAsync();
            var frame = new Frame();
            frame.Navigate(typeof(SecondaryPage), appWindowViewModel.Key);
            ElementCompositionPreview.SetAppWindowContent(appWindowViewModel.AppWindow, frame);

            appWindowViewModel.AppWindow.Closed += delegate
            {
                frame.Content = null;
                appWindowViewModel.AppWindow = null;
            };
        }

        var shown = await appWindowViewModel.AppWindow.TryShowAsync();

        var windowWidth = ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Width_{appWindowViewModel.Key}"];
        var windowHeight = ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Height_{appWindowViewModel.Key}"];
        if (windowWidth is double wWidth && windowHeight is double wHeight)
        {
            appWindowViewModel.AppWindow.RequestSize(new Size(wWidth, wHeight));
        }

        var xposition = ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_X_{appWindowViewModel.Key}"];
        var yposition = ApplicationData.Current.LocalSettings.Values[$"AppWindow_SecondaryView_Y_{appWindowViewModel.Key}"];
        if (xposition is double xpos && yposition is double ypos)
        {
            var placement = appWindowViewModel.AppWindow.GetPlacement();
            appWindowViewModel.AppWindow.RequestMoveRelativeToDisplayRegion(placement.DisplayRegion, new Point(xpos, ypos));
        }
        else
        {
            appWindowViewModel.AppWindow.RequestMoveAdjacentToCurrentView();
        }
    }

I have a sample uwp app : https://github.com/touseefbsb/AppWindowRemember我有一个示例 uwp 应用程序: https ://github.com/touseefbsb/AppWindowRemember

you can clone it and run the MultiAppWindowSample2 project, enter "1" in the text box and press the button Open Secondary Windows .您可以克隆它并运行MultiAppWindowSample2项目,在文本框中输入“1”并按下按钮Open Secondary Windows it will open 1 secondary window alongside the main window as expected, now move the 2nd window to your 2nd monitor and then close your main window it will ask whether you want to save the placement, press Yes .它将按预期在主窗口旁边打开 1 个辅助窗口,现在将第二个窗口移动到您的第二个监视器,然后关闭您的主窗口,它会询问您是否要保存放置,按Yes

Now run the app again, and enter "1" in textbox and press button again, notice the secondary window opens on your first monitor/display.现在再次运行应用程序,在文本框中输入“1”并再次按下按钮,注意第二个窗口在您的第一个监视器/显示器上打开。 While the aim is to open it on the 2nd monitor as it was closed the last time.虽然目的是在上次关闭时在第二台显示器上打开它。

UWP AppWindow Get correct monitor/Display region UWP AppWindow 获取正确的监视器/显示区域

The problem is the DisplayRegion of current AppWindow is always the first monitor even if you have moved the AppWindow into the second monitor.问题是当前AppWindowDisplayRegion始终是第一个监视器,即使您已将AppWindow移动到第二个监视器。 I will report this problem.我会报告这个问题。 and currently there is work around is show AppWindow in the second monitor at first and record the second monitor's id into local setting.目前有一个解决方法是首先在第二个监视器中显示AppWindow并将第二个监视器的 id 记录到本地设置中。

During the testing ApplicationView.GetForCurrentView().GetDisplayRegions()[0] could return correct DisplayRegion for current main app window (does not return correct value when move current into other monitor).在测试期间ApplicationView.GetForCurrentView().GetDisplayRegions()[0]可以为当前主应用程序窗口返回正确的DisplayRegion (将当前移动到其他监视器时不返回正确的值)。 you can use it to direct which is second monitor.您可以使用它来指示哪个是第二个显示器。

private DisplayRegion GetOtherDisplayRegion(DisplayRegion currentAppDisplayRegion)
{
    // Get the list of all DisplayRegions defined for the WindowingEnvironment that our application is currently in
    IReadOnlyList<DisplayRegion> displayRegions = ApplicationView.GetForCurrentView().WindowingEnvironment.GetDisplayRegions();
    foreach (DisplayRegion displayRegion in displayRegions)
    {
        if (displayRegion != currentAppDisplayRegion && displayRegion.IsVisible)
        {
            return displayRegion;
        }
    }

    return null;
}

For more please refer to official code sample .更多请参考官方代码示例

该bug只出现在Windows 11上,设备id不对但偏移量是对的,所以我们可以使用正确的窗口偏移量和设备偏移量来计算正确的设备。

First, you must save the DisplayRegion.DisplayMonitorDeviceId (or something to recover on reload).首先,您必须保存 DisplayRegion.DisplayMonitorDeviceId(或在重新加载时恢复的内容)。 I successfully used the ID.我成功使用了这个ID。

Then you can get a list of DisplayRegions availible through either the AppWindow.WindowingEnvironment.GetDisplayRegions() or Windows.UI.WindowManagement.WindowingEnvironment.GetDisplayRegions().然后,您可以通过 AppWindow.WindowingEnvironment.GetDisplayRegions() 或 Windows.UI.WindowManagement.WindowingEnvironment.GetDisplayRegions() 获取可用的 DisplayRegions 列表。 This list is not debug viewable, but does work with foreach.此列表无法调试查看,但可以与 foreach 一起使用。

Walk the list and find the matching device, then RequestMoveRelativeToDisplayRegion.遍历列表并找到匹配的设备,然后是 RequestMoveRelativeToDisplayRegion。 The ids in the struct require recasting to "string" to compare correctly.结构中的 id 需要重新转换为“字符串”才能正确比较。

The coordinates passed are relative to the DisplayRegion [monitor] and will be offset from 0,0 even if the monitor is positioned in negative space from the main monitor.传递的坐标是相对于 DisplayRegion [监视器] 的,即使监视器位于主监视器的负空间中,也会从 0,0 偏移。

I just found this sample yesterday and figured out the solution.我昨天刚刚找到了这个样本并找到了解决方案。 I need to offer an update to the original article and github sample, but I didn't bring the link home.我需要提供对原始文章和 github 示例的更新,但我没有将链接带回家。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM