Skip to content

Commit 98f6172

Browse files
CopilotBornToBeRoot
andcommitted
Fix cross-process DPI scaling: send WM_DPICHANGED with explicit DPI to embedded window
Co-authored-by: BornToBeRoot <16019165+BornToBeRoot@users.noreply.github.com>
1 parent 90bd9b4 commit 98f6172

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

Source/NETworkManager.Utilities/NativeMethods.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public enum WindowShowStyle : uint
4040
public enum WM : uint
4141
{
4242
SYSCOMMAND = 0x0112,
43-
DPICHANGED_AFTERPARENT = 0x02E3
43+
DPICHANGED = 0x02E0
4444
}
4545

4646
#endregion
@@ -77,6 +77,9 @@ public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, in
7777
[DllImport("user32.dll", CharSet = CharSet.Auto)]
7878
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
7979

80+
[DllImport("user32.dll", CharSet = CharSet.Auto)]
81+
public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
82+
8083
[DllImport("user32.dll", SetLastError = true)]
8184
public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
8285

Source/NETworkManager/Controls/PowerShellControl.xaml.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,19 @@ private void WindowGrid_SizeChanged(object sender, SizeChangedEventArgs e)
2323

2424
private void WindowsFormsHost_DpiChanged(object sender, DpiChangedEventArgs e)
2525
{
26-
if (IsConnected && _appWin != IntPtr.Zero)
27-
NativeMethods.SendMessage(_appWin, (uint)NativeMethods.WM.DPICHANGED_AFTERPARENT, IntPtr.Zero,
28-
IntPtr.Zero);
29-
26+
// Resize first so the embedded window is physically on the new monitor,
27+
// then post WM_DPICHANGED with the explicit new DPI in wParam so the
28+
// embedded process rescales its fonts without relying on a cross-process
29+
// GetDpiForWindow() call (which is unreliable after SetParent across processes).
3030
ResizeEmbeddedWindow();
31+
32+
if (IsConnected && _appWin != IntPtr.Zero)
33+
{
34+
var dpiX = (int)e.NewDpi.PixelsPerInchX;
35+
var dpiY = (int)e.NewDpi.PixelsPerInchY;
36+
var wParam = new IntPtr(unchecked((int)(uint)((dpiX & 0xFFFF) | ((dpiY & 0xFFFF) << 16))));
37+
NativeMethods.PostMessage(_appWin, (uint)NativeMethods.WM.DPICHANGED, wParam, IntPtr.Zero);
38+
}
3139
}
3240

3341
#endregion

Source/NETworkManager/Controls/PuTTYControl.xaml.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,19 @@ private void WindowGrid_SizeChanged(object sender, SizeChangedEventArgs e)
2424

2525
private void WindowsFormsHost_DpiChanged(object sender, DpiChangedEventArgs e)
2626
{
27-
if (IsConnected && _appWin != IntPtr.Zero)
28-
NativeMethods.SendMessage(_appWin, (uint)NativeMethods.WM.DPICHANGED_AFTERPARENT, IntPtr.Zero,
29-
IntPtr.Zero);
30-
27+
// Resize first so the embedded window is physically on the new monitor,
28+
// then post WM_DPICHANGED with the explicit new DPI in wParam so the
29+
// embedded process rescales its fonts without relying on a cross-process
30+
// GetDpiForWindow() call (which is unreliable after SetParent across processes).
3131
ResizeEmbeddedWindow();
32+
33+
if (IsConnected && _appWin != IntPtr.Zero)
34+
{
35+
var dpiX = (int)e.NewDpi.PixelsPerInchX;
36+
var dpiY = (int)e.NewDpi.PixelsPerInchY;
37+
var wParam = new IntPtr(unchecked((int)(uint)((dpiX & 0xFFFF) | ((dpiY & 0xFFFF) << 16))));
38+
NativeMethods.PostMessage(_appWin, (uint)NativeMethods.WM.DPICHANGED, wParam, IntPtr.Zero);
39+
}
3240
}
3341

3442
#endregion

0 commit comments

Comments
 (0)