You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何设置WinUI3程序启动时在屏幕中央显示?

WinUI3 程序启动时窗口居中的实现方法

你的代码未生效的核心原因是在窗口激活前获取了appWindow.Size——此时窗口还未完成初始化布局,拿到的尺寸通常是默认值(比如800x600),而非窗口实际渲染后的真实大小,导致计算出的居中位置出现偏差。另外,过早调用Move也可能被系统默认的窗口定位逻辑覆盖。

以下是两种可行的解决方法:

方案一:基于WinUI3原生API调整顺序

将窗口激活操作提前,确保窗口完成初始化后再计算并设置居中位置,也可结合窗口Loaded事件保证尺寸完全确定:

方法1:调整激活顺序直接实现

m_window = new MainWindow();
// 先激活窗口,确保布局完成
m_window.Activate();

var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(m_window);
Microsoft.UI.WindowId windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
Microsoft.UI.Windowing.AppWindow appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);

if (appWindow is not null)
{
    var displayArea = Microsoft.UI.Windowing.DisplayArea.GetFromWindowId(windowId, Microsoft.UI.Windowing.DisplayAreaFallback.Nearest);
    if (displayArea is not null)
    {
        // 如需固定窗口尺寸,可在此显式设置
        // appWindow.Resize(new Windows.Graphics.SizeInt32 { Width = 800, Height = 600 });
        
        var workArea = displayArea.WorkArea;
        var centeredPos = new Windows.Graphics.PointInt32
        {
            X = workArea.X + (workArea.Width - appWindow.Size.Width) / 2,
            Y = workArea.Y + (workArea.Height - appWindow.Size.Height) / 2
        };
        appWindow.Move(centeredPos);
    }
}

方法2:在窗口Loaded事件中执行(更稳妥)

在MainWindow.xaml.cs中添加事件处理:

public MainWindow()
{
    this.InitializeComponent();
    this.Loaded += MainWindow_Loaded;
}

private void MainWindow_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    CenterWindow();
}

private void CenterWindow()
{
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
    var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
    var appWindow = Microsoft.UI.Windowing.AppWindow.GetFromWindowId(windowId);
    
    if (appWindow == null) return;
    
    var displayArea = Microsoft.UI.Windowing.DisplayArea.GetFromWindowId(windowId, Microsoft.UI.Windowing.DisplayAreaFallback.Nearest);
    if (displayArea == null) return;
    
    var workArea = displayArea.WorkArea;
    var centeredPos = new Windows.Graphics.PointInt32
    {
        X = workArea.X + (workArea.Width - appWindow.Size.Width) / 2,
        Y = workArea.Y + (workArea.Height - appWindow.Size.Height) / 2
    };
    appWindow.Move(centeredPos);
}

方案二:使用Win32 API实现(兼容性更强)

如果原生API方式存在场景限制,可直接调用Win32 API实现居中,稳定性更高:

首先添加P/Invoke声明:

using System.Runtime.InteropServices;

public static class Win32Helpers
{
    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetMonitorInfo(IntPtr hMonitor, ref MONITORINFO lpmi);

    [DllImport("user32.dll")]
    public static extern IntPtr MonitorFromWindow(IntPtr hwnd, uint dwFlags);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

    public const uint MONITOR_DEFAULTTONEAREST = 0x00000002;
    public const uint SWP_NOSIZE = 0x0001;
    public const uint SWP_NOZORDER = 0x0004;

    [StructLayout(LayoutKind.Sequential)]
    public struct MONITORINFO
    {
        public uint cbSize;
        public RECT rcMonitor;
        public RECT rcWork;
        public uint dwFlags;
    }

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

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out Win32Helpers.RECT lpRect);

然后在窗口Loaded事件中调用居中方法:

private void MainWindow_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    CenterWindowWithWin32();
}

private void CenterWindowWithWin32()
{
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
    var monitorHandle = Win32Helpers.MonitorFromWindow(hWnd, Win32Helpers.MONITOR_DEFAULTTONEAREST);
    
    Win32Helpers.MONITORINFO monitorInfo = new Win32Helpers.MONITORINFO();
    monitorInfo.cbSize = (uint)Marshal.SizeOf(monitorInfo);
    Win32Helpers.GetMonitorInfo(monitorHandle, ref monitorInfo);
    
    Win32Helpers.RECT windowRect;
    GetWindowRect(hWnd, out windowRect);
    int windowWidth = windowRect.right - windowRect.left;
    int windowHeight = windowRect.bottom - windowRect.top;
    
    int x = monitorInfo.rcWork.left + (monitorInfo.rcWork.right - monitorInfo.rcWork.left - windowWidth) / 2;
    int y = monitorInfo.rcWork.top + (monitorInfo.rcWork.bottom - monitorInfo.rcWork.top - windowHeight) / 2;
    
    Win32Helpers.SetWindowPos(hWnd, IntPtr.Zero, x, y, 0, 0, Win32Helpers.SWP_NOSIZE | Win32Helpers.SWP_NOZORDER);
}

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:05:19