admin管理员组

文章数量:1287598

I have problem with a WelcomeScreen developed in WinUI 3. In resolution (1920 * 1080), Scale (125%), the controls on the window are displayed correctly, but they are invisible when in resolution (1920 * 1080), Scale (150%). Is there any way I can get the needed size of the window after scaling and adjust the windows size dynamically? Thanks.

// this window size works with scaling 125% but not work with 150%
this.AppWindow.MoveAndResize(new Windows.Graphics.RectInt32(0, 0, 1200, 665));

WelcomeScreen.xaml:

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Name="WelcomeScreenWindow"
    x:Class="Views.WelcomeScreen.WelcomeScreen"
    xmlns=";
    xmlns:x=";
    xmlns:local="using:Views.WelcomeScreen"
    xmlns:d=";
    xmlns:mc=";
    mc:Ignorable="d"
    Title="">

    <Grid ColumnDefinitions="*,*,*" RowDefinitions="*" >
        <StackPanel Grid.Column="0" Grid.ColumnSpan="3" Orientation="Vertical"  >
            <local:WelcomeScreenPage1 x:Name="WelcomeScreenPage1"/>
            <local:WelcomeScreenPage2 x:Name="WelcomeScreenPage2"/>
            <local:WelcomeScreenPage3 x:Name="WelcomeScreenPage3"/>
            <Line Stroke="LightGray" X1="0" Y1="0" X2="1200" Y2="0" StrokeThickness="2" Margin="12,0,12,0"/>
            <RelativePanel>
                <CheckBox x:Name="DoNotShowAaginCheckBox" x:Uid="DoNotShowThisAgain" FontFamily="{StaticResource VeneerFont}" IsChecked="{x:Bind WelcomeScreenPageViewModel.IsDisplayAgain, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="12,12,0,0"  VerticalContentAlignment="Center" />
                <Button x:Name="BackButton" Width="100" Style="{StaticResource AccentButtonStyle}" FontFamily="{StaticResource VeneerFont}" Command="{x:Bind WelcomeScreenPageViewModel.BackCommand}" RelativePanel.LeftOf="PipsPager" Content="{x:Bind WelcomeScreenPageViewModel.BackButtonText, Mode=OneWay}" Margin="12,12,12,0"/>
                <PipsPager x:Name="PipsPager" Margin="0,15,0,0" NumberOfPages="3" SelectedPageIndex="{x:Bind WelcomeScreenPageViewModel.CurrentPageIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" RelativePanel.AlignHorizontalCenterWithPanel="True" />
                <Button x:Name="NextButton" Width="100" Style="{StaticResource AccentButtonStyle}" FontFamily="{StaticResource VeneerFont}" Command="{x:Bind WelcomeScreenPageViewModel.NextCommand}" Content="{x:Bind WelcomeScreenPageViewModel.NextButtonText,Mode=OneWay}" RelativePanel.RightOf="PipsPager" Margin="12,12,12,0"/>
            </RelativePanel>
        </StackPanel>
    </Grid>
</Window>

WelcomeScreen.xaml.cs:

using Microsoft.UI.Windowing;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using ViewModels.WelcomeScreen;

using System.ComponentModel;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: .

namespace Views.WelcomeScreen
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class WelcomeScreen : Window
    {
        public WelcomeScreenPageViewModel WelcomeScreenPageViewModel { get; }

        public void GetAppWindowAndPresenter()
        {
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
            WindowId myWndId = Win32Interop.GetWindowIdFromWindow(hWnd);
            _apw = AppWindow.GetFromWindowId(myWndId);
            _presenter = _apw.Presenter as OverlappedPresenter;
        }

        private AppWindow _apw;
        private OverlappedPresenter _presenter;

        private void InitializeControls()
        {
            GetAppWindowAndPresenter();
            _presenter.IsResizable = false;
            _presenter.IsMaximizable = false;
            _presenter.IsMinimizable = false;
            _apw.TitleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;
            _apw.SetIcon("Assets/Apple.ico");
        }

        public WelcomeScreen(WelcomeScreenPageViewModel welcomeScreenPageViewModel)
        {
            this.InitializeComponent();
            this.InitializeControls();

            // this window size works with scaling 125% but not work with 150%
            this.AppWindow.MoveAndResize(new Windows.Graphics.RectInt32(0, 0, 1200, 665));

            WelcomeScreenPageViewModel = welcomeScreenPageViewModel;
         
            UpdateNavigationFrame(0);

            WelcomeScreenPageViewModel.PropertyChanged += ProcessPropertyChanged;

            WelcomeScreenPageViewModel.ClosingRequest += (sender, e) => this.Close();
        }

        private void ProcessPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == (nameof(WelcomeScreenPageViewModel.CurrentPageIndex)))
                UpdateNavigationFrame(WelcomeScreenPageViewModel.CurrentPageIndex);
        }

        private void UpdateNavigationFrame(int index)
        {
            WelcomeScreenPage1.Visibility = Visibility.Collapsed;
            WelcomeScreenPage2.Visibility = Visibility.Collapsed;
            WelcomeScreenPage3.Visibility = Visibility.Collapsed;

            if (index == 0)
                WelcomeScreenPage1.Visibility = Visibility.Visible;

            if (index == 1)
                WelcomeScreenPage2.Visibility = Visibility.Visible;

            if (index == 2)
                WelcomeScreenPage3.Visibility = Visibility.Visible;
        }
    }
}

In resolution (1920*1080), Scale (125%):

In resolution (1920*1080), Scale (150%):

Scaling settings:

I have problem with a WelcomeScreen developed in WinUI 3. In resolution (1920 * 1080), Scale (125%), the controls on the window are displayed correctly, but they are invisible when in resolution (1920 * 1080), Scale (150%). Is there any way I can get the needed size of the window after scaling and adjust the windows size dynamically? Thanks.

// this window size works with scaling 125% but not work with 150%
this.AppWindow.MoveAndResize(new Windows.Graphics.RectInt32(0, 0, 1200, 665));

WelcomeScreen.xaml:

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Name="WelcomeScreenWindow"
    x:Class="Views.WelcomeScreen.WelcomeScreen"
    xmlns="http://schemas.microsoft/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft/winfx/2006/xaml"
    xmlns:local="using:Views.WelcomeScreen"
    xmlns:d="http://schemas.microsoft/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats./markup-compatibility/2006"
    mc:Ignorable="d"
    Title="">

    <Grid ColumnDefinitions="*,*,*" RowDefinitions="*" >
        <StackPanel Grid.Column="0" Grid.ColumnSpan="3" Orientation="Vertical"  >
            <local:WelcomeScreenPage1 x:Name="WelcomeScreenPage1"/>
            <local:WelcomeScreenPage2 x:Name="WelcomeScreenPage2"/>
            <local:WelcomeScreenPage3 x:Name="WelcomeScreenPage3"/>
            <Line Stroke="LightGray" X1="0" Y1="0" X2="1200" Y2="0" StrokeThickness="2" Margin="12,0,12,0"/>
            <RelativePanel>
                <CheckBox x:Name="DoNotShowAaginCheckBox" x:Uid="DoNotShowThisAgain" FontFamily="{StaticResource VeneerFont}" IsChecked="{x:Bind WelcomeScreenPageViewModel.IsDisplayAgain, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="12,12,0,0"  VerticalContentAlignment="Center" />
                <Button x:Name="BackButton" Width="100" Style="{StaticResource AccentButtonStyle}" FontFamily="{StaticResource VeneerFont}" Command="{x:Bind WelcomeScreenPageViewModel.BackCommand}" RelativePanel.LeftOf="PipsPager" Content="{x:Bind WelcomeScreenPageViewModel.BackButtonText, Mode=OneWay}" Margin="12,12,12,0"/>
                <PipsPager x:Name="PipsPager" Margin="0,15,0,0" NumberOfPages="3" SelectedPageIndex="{x:Bind WelcomeScreenPageViewModel.CurrentPageIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" RelativePanel.AlignHorizontalCenterWithPanel="True" />
                <Button x:Name="NextButton" Width="100" Style="{StaticResource AccentButtonStyle}" FontFamily="{StaticResource VeneerFont}" Command="{x:Bind WelcomeScreenPageViewModel.NextCommand}" Content="{x:Bind WelcomeScreenPageViewModel.NextButtonText,Mode=OneWay}" RelativePanel.RightOf="PipsPager" Margin="12,12,12,0"/>
            </RelativePanel>
        </StackPanel>
    </Grid>
</Window>

WelcomeScreen.xaml.cs:

using Microsoft.UI.Windowing;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using ViewModels.WelcomeScreen;

using System.ComponentModel;

// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.

namespace Views.WelcomeScreen
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class WelcomeScreen : Window
    {
        public WelcomeScreenPageViewModel WelcomeScreenPageViewModel { get; }

        public void GetAppWindowAndPresenter()
        {
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
            WindowId myWndId = Win32Interop.GetWindowIdFromWindow(hWnd);
            _apw = AppWindow.GetFromWindowId(myWndId);
            _presenter = _apw.Presenter as OverlappedPresenter;
        }

        private AppWindow _apw;
        private OverlappedPresenter _presenter;

        private void InitializeControls()
        {
            GetAppWindowAndPresenter();
            _presenter.IsResizable = false;
            _presenter.IsMaximizable = false;
            _presenter.IsMinimizable = false;
            _apw.TitleBar.IconShowOptions = IconShowOptions.HideIconAndSystemMenu;
            _apw.SetIcon("Assets/Apple.ico");
        }

        public WelcomeScreen(WelcomeScreenPageViewModel welcomeScreenPageViewModel)
        {
            this.InitializeComponent();
            this.InitializeControls();

            // this window size works with scaling 125% but not work with 150%
            this.AppWindow.MoveAndResize(new Windows.Graphics.RectInt32(0, 0, 1200, 665));

            WelcomeScreenPageViewModel = welcomeScreenPageViewModel;
         
            UpdateNavigationFrame(0);

            WelcomeScreenPageViewModel.PropertyChanged += ProcessPropertyChanged;

            WelcomeScreenPageViewModel.ClosingRequest += (sender, e) => this.Close();
        }

        private void ProcessPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == (nameof(WelcomeScreenPageViewModel.CurrentPageIndex)))
                UpdateNavigationFrame(WelcomeScreenPageViewModel.CurrentPageIndex);
        }

        private void UpdateNavigationFrame(int index)
        {
            WelcomeScreenPage1.Visibility = Visibility.Collapsed;
            WelcomeScreenPage2.Visibility = Visibility.Collapsed;
            WelcomeScreenPage3.Visibility = Visibility.Collapsed;

            if (index == 0)
                WelcomeScreenPage1.Visibility = Visibility.Visible;

            if (index == 1)
                WelcomeScreenPage2.Visibility = Visibility.Visible;

            if (index == 2)
                WelcomeScreenPage3.Visibility = Visibility.Visible;
        }
    }
}

In resolution (1920*1080), Scale (125%):

In resolution (1920*1080), Scale (150%):

Scaling settings:

Share Improve this question edited Feb 25 at 6:03 marc_s 755k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 25 at 2:10 MingMing 5371 gold badge7 silver badges25 bronze badges 2
  • Did I understand you right? You want to change system settings, screen size in pixels and scaling, while the application is running and want the application to adjust right away, right? – Sergey A Kryukov Commented Feb 25 at 2:21
  • @SergeyAKryukov Thanks. Actually when the welcome screen is running and the application adjusts right away, the problem is when shut it down and restart the welcome screen, the controls become invisible. – Ming Commented Feb 25 at 7:27
Add a comment  | 

1 Answer 1

Reset to default 1

You can get notified when the DPI changes. Instead of implementing all by yourself, I recommend using the WinUIEx NuGet package.

  1. Install the WinUIEx NuGet package.
  2. Replace Window with WindowEx:
    using WinUIEx;
    
    namespace WinUIDemoApp;
    
    public sealed partial class MainWindow : WindowEx
     {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
    
    <winex:WindowEx
        xmlns:winex="using:WinUIEx"
        x:Class="WinUIDemoApp.MainWindow"
        xmlns="http://schemas.microsoft/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft/expression/blend/2008"
        xmlns:local="using:WinUIDemoApp"
        xmlns:mc="http://schemas.openxmlformats./markup-compatibility/2006"
        mc:Ignorable="d">
        ...
    </winex:WindowEx>
    
  3. Then in App.xaml.cs, listen to WM_DPICHANGED:
    private WindowEx? Window { get; set; }
    
    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        Window = new MainWindow();
        var windowManager = WindowManager.Get(Window);
        windowManager.WindowMessageReceived += WindowManager_WindowMessageReceived;
        Window.Activate();
    }
    
    private void WindowManager_WindowMessageReceived(object? sender, WinUIEx.Messaging.WindowMessageEventArgs e)
    {
        if (e.Message.MessageId != 0x02E0)  // WM_DPICHANGED
        {
            return;
        }
    
        var dpi = Window.GetDpiForWindow();
        System.Diagnostics.Debug.WriteLine($"DPI: {dpi}");
        // Resize your window here...
    }
    

本文标签: cHow to dynamically adjust window size according to the screen scaling in WinUI 3Stack Overflow