You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

WinUI3应用最大化禁用恢复按钮后,最小化重开UI下移原因排查

WinUI3应用最小化恢复后UI偏移问题解决

我开发了一个包含两个页面的WinUI 3应用,主页面设有按钮可导航至第二页。导航至第二页时,需将窗口设置为最大化状态并禁用恢复按钮,但当应用被最小化后重新打开,UI会出现向下偏移的问题。

相关代码

主窗口代码

XAML

<Window
    x:Class="App1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="App1">

    <Window.SystemBackdrop>
        <MicaBackdrop />
    </Window.SystemBackdrop>

    <Frame x:Name="ContentFrame" />
</Window>

C#

using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;

namespace App1
{
    public sealed partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ContentFrame.Navigated += ContentFrame_Navigated;
            ContentFrame.Navigate(typeof(MainPage), this);
            Activated += MainWindow_Activated;
        }

        private void MainWindow_Activated(object sender, WindowActivatedEventArgs args)
        {
            if (args.WindowActivationState != WindowActivationState.Deactivated)
            {
                ContentFrame.UpdateLayout();
                this.UpdateLayout();
            }
        }

        private void ContentFrame_Navigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e)
        {
            var appWindow = GetAppWindowForCurrentWindow();
            if (appWindow != null && appWindow.Presenter is OverlappedPresenter presenter)
            {
                if (e.SourcePageType == typeof(SecondPage))
                {
                    presenter.IsMaximizable = false;
                    presenter.IsResizable = false;
                    presenter.Maximize();
                }
                else
                {
                    presenter.IsMaximizable = true;
                    presenter.IsResizable = true;
                    if (presenter.State == OverlappedPresenterState.Maximized)
                    {
                        presenter.Restore();
                    }
                }
            }
        }

        public void NavigateToSecondPage()
        {
            ContentFrame.Navigate(typeof(SecondPage));
        }

        public AppWindow? GetAppWindowForCurrentWindow()
        {
            var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
            var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
            return AppWindow.GetFromWindowId(windowId);
        }
    }
}

第一页代码

XAML

<Page x:Class="App1.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App1"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d">

    <Button x:Name="OpenSecondPageBtn"
            Content="Open Second Screen"
            Click="OpenSecondPageBtn_Click"
            Width="200" />
</Page>

C#

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        private MainWindow? _mainWindow;

        public MainPage()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if (e.Parameter is MainWindow mainWindow)
            {
                _mainWindow = mainWindow;
            }
        }

        private void OpenSecondPageBtn_Click(object sender, RoutedEventArgs e)
        {
            _mainWindow?.NavigateToSecondPage();
        }
    }
}

第二页代码

XAML

<Page
    x:Class="App1.SecondPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Spacing="20">
        <TextBlock Text="Second Screen"
                   FontSize="32"
                   FontWeight="Bold"
                   HorizontalAlignment="Center" />
        <TextBlock Text="Window is maximized and cannot be resized"
                   FontSize="16"
                   HorizontalAlignment="Center"
                   Foreground="{ThemeResource SystemFillColorAttentionBrush}" />
        <Button x:Name="BackBtn"
                Content="Back to Main Screen"
                Click="BackBtn_Click"
                Width="200"
                HorizontalAlignment="Center"
                Margin="0,20,0,0" />
    </StackPanel>
</Page>

C#

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace App1
{
    public sealed partial class SecondPage : Page
    {
        public SecondPage()
        {
            InitializeComponent();
        }

        private void BackBtn_Click(object sender, RoutedEventArgs e)
        {
            if (Frame.CanGoBack)
            {
                Frame.GoBack();
            }
        }
    }
}

问题截图

  • 问题发生前:
    问题发生前
  • 应用最小化后重新打开:
    应用最小化后重新打开

问题原因及解决说明

原因

原代码先执行Maximize()再禁用窗口最大化和调整大小功能,导致WinUI窗口布局计算异常。窗口从最小化恢复时,系统未正确重新计算工作区与UI元素的位置关系,引发偏移。

解决要点

  1. 调整窗口状态设置顺序:先禁用窗口最大化和调整大小属性,再调用Maximize(),确保状态变更时布局逻辑正确触发。
  2. 监听窗口激活事件:在窗口从最小化恢复激活时,强制刷新UI布局,重新计算元素位置。

内容的提问来源于stack exchange,提问作者AkritiCodes

火山引擎 最新活动