Home > Enterprise >  WM_GETMINMAXINFO in WinUI 3 with C#?
WM_GETMINMAXINFO in WinUI 3 with C#?

Time:07-02

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!

CodePudding user response:

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

CodePudding user response:

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.

  • Related