Since WinUI 3 currently has no function to set the minimum size, I have to use WM_GETMINMAXINFO
.
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!
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,
}
}