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

WinUI 3中如何设置窗口最小尺寸?UWP对应API返回null如何解决

WinUI 3 设置窗口最小尺寸方案

ApplicationView.GetForCurrentView() 是UWP应用模型下的专属API,WinUI 3基于桌面应用架构设计,不存在UWP的全局应用视图上下文,因此调用该接口返回null是预期行为,无法直接复用UWP的窗口尺寸设置逻辑。

WinUI 3设置窗口最小尺寸的通用实现方式是拦截Win32窗口消息,兼容性覆盖所有WinUI 3版本,具体实现如下:

  • 首先引入所需命名空间
using System.Runtime.InteropServices;
using WinRT.Interop;
using Microsoft.UI.Xaml;
  • 定义Win32 API相关的常量、结构体与P/Invoke签名
private const int WM_GETMINMAXINFO = 0x0024;
private const int GWLP_WNDPROC = -4;

[StructLayout(LayoutKind.Sequential)]
private struct POINT
{
    public int X;
    public int Y;
}

[StructLayout(LayoutKind.Sequential)]
private struct MINMAXINFO
{
    public POINT ptReserved;
    public POINT ptMaxSize;
    public POINT ptMaxPosition;
    public POINT ptMinTrackSize;
    public POINT ptMaxTrackSize;
}

private delegate nint WndProc(nint hWnd, uint msg, nint wParam, nint lParam, out bool handled);

[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern nint SetWindowLongPtr64(nint hWnd, int nIndex, nint dwNewLong);

[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
private static extern nint SetWindowLongPtr32(nint hWnd, int nIndex, nint dwNewLong);

[DllImport("user32.dll")]
private static extern nint CallWindowProc(nint lpPrevWndFunc, nint hWnd, uint msg, nint wParam, nint lParam);

private static nint SetWindowLongPtr(nint hWnd, int nIndex, nint dwNewLong)
{
    return IntPtr.Size == 8 
        ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) 
        : SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
}
  • 在窗口构造函数中添加窗口子类化逻辑,拦截尺寸边界查询消息
// 目标最小尺寸,单位为物理像素
private const int MinWindowWidth = 500;
private const int MinWindowHeight = 500;

private nint _originalWndProc;
private WndProc _customWndProc;

public MainWindow()
{
    InitializeComponent();

    // 获取当前窗口的原生句柄
    nint hWnd = WindowNative.GetWindowHandle(this);
    
    // 替换默认窗口过程
    _customWndProc = ProcessWindowMessage;
    nint customWndProcPtr = Marshal.GetFunctionPointerForDelegate(_customWndProc);
    _originalWndProc = SetWindowLongPtr(hWnd, GWLP_WNDPROC, customWndProcPtr);
}

private nint ProcessWindowMessage(nint hWnd, uint msg, nint wParam, nint lParam, out bool handled)
{
    handled = false;
    if (msg == WM_GETMINMAXINFO)
    {
        MINMAXINFO sizeInfo = Marshal.PtrToStructure<MINMAXINFO>(lParam);
        // 限制窗口最小可拖动尺寸
        sizeInfo.ptMinTrackSize.X = MinWindowWidth;
        sizeInfo.ptMinTrackSize.Y = MinWindowHeight;
        Marshal.StructureToPtr(sizeInfo, lParam, true);
        handled = true;
        return 0;
    }

    // 非尺寸相关消息交给系统默认逻辑处理
    return CallWindowProc(_originalWndProc, hWnd, msg, wParam, lParam);
}

注意:上述代码中使用的尺寸单位是物理像素,如果需要和XAML布局使用的逻辑单位对齐,需要根据当前窗口DPI做换算:物理像素值 = 逻辑单位值 * (当前DPI / 96.0),当前窗口DPI可通过DisplayInformation.GetForCurrentView().LogicalDpi获取。

简化实现(仅支持Windows App SDK 1.3+)

如果项目使用的Windows App SDK版本为1.3或更高,不需要手写P/Invoke,可直接通过框架提供的OverlappedPresenter接口设置最小尺寸:

using Microsoft.UI.Windowing;

public MainWindow()
{
    InitializeComponent();

    nint hWnd = WindowNative.GetWindowHandle(this);
    WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
    AppWindow appWindow = AppWindow.GetFromWindowId(windowId);

    if (appWindow.Presenter is OverlappedPresenter presenter)
    {
        presenter.MinWidth = 500;
        presenter.MinHeight = 500;
    }
}

内容的提问来源于stack exchange,提问作者Hebele Hübele

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:27:14