如何设置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
相关产品推荐
相关产品推荐

