1

Problem

Since WinUI 3 currently has no function to set the minimum size, I have to use WM_GETMINMAXINFO.

Question

How can I specify WM_GETMINMAXINFO minimum or maximum window size with C# in a WinUI 3 project?

Do I need to set it in the App class or MainWindow class?

Thanks in advance!

3
  • 1
    It's related to the window github.com/microsoft/microsoft-ui-xaml/issues/2945 Commented Jul 1, 2022 at 7:39
  • Hey, thanks for this suggestion. I already saw this answer, this solution seems to have problems with my project. Is there not another possibility? Commented Jul 1, 2022 at 8:10
  • You should expose what you did and explain what are your issues Commented Jul 1, 2022 at 8:54

3 Answers 3

4

Check out this example on GitHub.

Here is a full example of a WinUI 3 window with a specified min and max width and height:

public sealed partial class MainWindow: Window
{
    private static WinProc newWndProc = null;
    private static IntPtr oldWndProc = IntPtr.Zero;
    private delegate IntPtr WinProc(IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);

    [DllImport("User32.dll")]
    internal static extern int GetDpiForWindow(IntPtr hwnd);

    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    private static extern int SetWindowLong32(IntPtr hWnd, WindowLongIndexFlags nIndex, WinProc newProc);

    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
    private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLongIndexFlags nIndex, WinProc newProc);

    [DllImport("user32.dll")]
    private static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);

    public static int MinWindowWidth { get; set; } = 900;
    public static int MaxWindowWidth { get; set; } = 1800;
    public static int MinWindowHeight { get; set; } = 600;
    public static int MaxWindowHeight { get; set; } = 1600;

    public MainWindow()
    {
        this.InitializeComponent();
        RegisterWindowMinMax(this);
    }

    private static void RegisterWindowMinMax(Window window)
    {
        var hwnd = GetWindowHandleForCurrentWindow(window);

        newWndProc = new WinProc(WndProc);
        oldWndProc = SetWindowLongPtr(hwnd, WindowLongIndexFlags.GWL_WNDPROC, newWndProc);
    }

    private static IntPtr GetWindowHandleForCurrentWindow(object target) =>
        WinRT.Interop.WindowNative.GetWindowHandle(target);

    private static IntPtr WndProc(IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam)
    {
        switch (Msg)
        {
            case WindowMessage.WM_GETMINMAXINFO:
                var dpi = GetDpiForWindow(hWnd);
                var scalingFactor = (float)dpi / 96;

                var minMaxInfo = Marshal.PtrToStructure<MINMAXINFO>(lParam);
                minMaxInfo.ptMinTrackSize.x = (int)(MinWindowWidth * scalingFactor);
                minMaxInfo.ptMaxTrackSize.x = (int)(MaxWindowWidth * scalingFactor);
                minMaxInfo.ptMinTrackSize.y = (int)(MinWindowHeight * scalingFactor);
                minMaxInfo.ptMaxTrackSize.y = (int)(MaxWindowHeight * scalingFactor);

                Marshal.StructureToPtr(minMaxInfo, lParam, true);
                break;

        }
        return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam);
    }

    private static IntPtr SetWindowLongPtr(IntPtr hWnd, WindowLongIndexFlags nIndex, WinProc newProc)
    {
        if (IntPtr.Size == 8)
            return SetWindowLongPtr64(hWnd, nIndex, newProc);
        else
            return new IntPtr(SetWindowLong32(hWnd, nIndex, newProc));
    }

    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;
    }

    [Flags]
    private enum WindowLongIndexFlags : int
    {
        GWL_WNDPROC = -4,
    }

    private enum WindowMessage : int
    {
        WM_GETMINMAXINFO = 0x0024,
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

How can I specify WM_GETMINMAXINFO minimum or maximum window size with C# in a WinUI 3 project?

There is a way that detect current appwindow's real time size in Changed method, and if the size is small or large then specific size you could call Resize method to set avaiable size. And here is documet that how to get appwindow.

Comments

0

Based on an example from the WinUI3 Gallery, it can be done in the following way:

public sealed partial class SampleWindow4 : Window
{
    public SampleWindow4(int MinWidth, int MinHeight, int MaxWidth, int MaxHeight)
    {
        this.InitializeComponent();

        AppWindow.Resize(new Windows.Graphics.SizeInt32(800, 500));
        AppWindow.SetIcon("Assets/Tiles/GalleryIcon.ico");
        AppWindow.TitleBar.PreferredTheme = TitleBarTheme.UseDefaultAppMode;

        OverlappedPresenter presenter = OverlappedPresenter.Create();
        presenter.PreferredMinimumWidth = MinWidth;
        presenter.PreferredMinimumHeight = MinHeight;
        presenter.PreferredMaximumWidth = MaxWidth;
        presenter.PreferredMaximumHeight = MaxHeight;
        presenter.IsMaximizable = false;

        AppWindow.SetPresenter(presenter);
    }

...

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.