Created
April 1, 2026 20:22
-
-
Save elibroftw/27241461dc32d53e7dd8f592aa5a779b to your computer and use it in GitHub Desktop.
Just install CsWin32, add the dpi method to NativeMethods.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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