Skip to content

Instantly share code, notes, and snippets.

@elibroftw
Created April 1, 2026 20:22
Show Gist options
  • Select an option

  • Save elibroftw/a92c5cb5c1c22459399f34f2f6c3beaa to your computer and use it in GitHub Desktop.

Select an option

Save elibroftw/a92c5cb5c1c22459399f34f2f6c3beaa to your computer and use it in GitHub Desktop.
A reference for what to do if WinUIEx isn't enough. Just install CsWin32, add the dpi method to NativeMethods.txt
using Microsoft.UI.Xaml;
using System;
using System.Runtime.InteropServices;
internal partial class Win32WindowHelper
{
private static WinProc? newWndProc = null;
private static nint oldWndProc = nint.Zero;
private POINT? minWindowSize = null;
private POINT? maxWindowSize = null;
private readonly Window window;
public Win32WindowHelper(Window window)
{
this.window = window;
}
public void SetWindowMinMaxSize(POINT? minWindowSize = null, POINT? maxWindowSize = null)
{
this.minWindowSize = minWindowSize;
this.maxWindowSize = maxWindowSize;
var hwnd = GetWindowHandleForCurrentWindow(window);
newWndProc = new WinProc(WndProc);
oldWndProc = SetWindowLongPtr(hwnd, WindowLongIndexFlags.GWL_WNDPROC, newWndProc);
}
private static nint GetWindowHandleForCurrentWindow(object target) =>
WinRT.Interop.WindowNative.GetWindowHandle(target);
private nint WndProc(nint hWnd, WindowMessage Msg, nint wParam, nint lParam)
{
switch (Msg)
{
case WindowMessage.WM_GETMINMAXINFO:
var dpi = Windows.Win32.PInvoke.GetDpiForWindow(new Windows.Win32.Foundation.HWND(hWnd));
var scalingFactor = (float)dpi / 96;
var minMaxInfo = Marshal.PtrToStructure<MINMAXINFO>(lParam);
if (minWindowSize != null)
{
minMaxInfo.ptMinTrackSize.x = (int)(minWindowSize.Value.x * scalingFactor);
minMaxInfo.ptMinTrackSize.y = (int)(minWindowSize.Value.y * scalingFactor);
}
if (maxWindowSize != null)
{
minMaxInfo.ptMaxTrackSize.x = (int)(maxWindowSize.Value.x * scalingFactor);
minMaxInfo.ptMaxTrackSize.y = (int)(maxWindowSize.Value.y * scalingFactor);
}
Marshal.StructureToPtr(minMaxInfo, lParam, true);
break;
}
return CallWindowProc(oldWndProc, hWnd, Msg, wParam, lParam);
}
private nint SetWindowLongPtr(nint hWnd, WindowLongIndexFlags nIndex, WinProc newProc)
{
nint funcPtr = Marshal.GetFunctionPointerForDelegate(newProc);
if (nint.Size == 8)
return SetWindowLongPtr64(hWnd, nIndex, funcPtr);
else
return new nint(SetWindowLong32(hWnd, nIndex, funcPtr));
}
internal 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;
}
internal enum WindowMessage : int
{
WM_GETMINMAXINFO = 0x0024,
}
[Flags]
internal enum WindowLongIndexFlags : int
{
GWL_WNDPROC = -4,
}
[DllImport("user32.dll")]
internal static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
internal static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLongIndexFlags nIndex, IntPtr newProc);
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
internal static extern int SetWindowLong32(IntPtr hWnd, WindowLongIndexFlags nIndex, IntPtr newProc);
internal delegate IntPtr WinProc(IntPtr hWnd, WindowMessage Msg, IntPtr wParam, IntPtr lParam);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment