diff --git a/Source/NETworkManager.Utilities/NativeMethods.cs b/Source/NETworkManager.Utilities/NativeMethods.cs
index 7b5e08ba08..999edcc642 100644
--- a/Source/NETworkManager.Utilities/NativeMethods.cs
+++ b/Source/NETworkManager.Utilities/NativeMethods.cs
@@ -16,6 +16,9 @@ public class NativeMethods
public const long WS_POPUP = 0x80000000L;
public const long WS_CAPTION = 0x00C00000L;
+ /// The value returned by CreateFile on failure.
+ public static readonly IntPtr INVALID_HANDLE_VALUE = new(-1);
+
#endregion
#region Enum
@@ -44,11 +47,37 @@ public enum WM : uint
#endregion
- #region Pinvoke/Win32 Methods
+ #region Structs
- [DllImport("user32.dll")]
- public static extern IntPtr GetForegroundWindow();
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RECT
+ {
+ public int left, top, right, bottom;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct COORD
+ {
+ public short X;
+ public short Y;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ public struct CONSOLE_FONT_INFOEX
+ {
+ public uint cbSize;
+ public uint nFont;
+ public COORD dwFontSize;
+ public uint FontFamily;
+ public uint FontWeight;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string FaceName;
+ }
+ #endregion
+
+ #region Pinvoke/Win32 Methods
+
[DllImport("user32.dll", SetLastError = true)]
public static extern long SetParent(IntPtr hWndChild, IntPtr hWndParent);
@@ -76,14 +105,129 @@ public static extern IntPtr SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, in
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
- [DllImport("user32.dll", SetLastError = true)]
- public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
-
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
+ ///
+ /// Returns the DPI (dots per inch) value for the monitor that contains the specified window.
+ /// Returns 0 if the window handle is invalid. Available on Windows 10 version 1607+.
+ ///
+ [DllImport("user32.dll")]
+ public static extern uint GetDpiForWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool AttachConsole(uint dwProcessId);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool FreeConsole();
+
+ [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
+ private static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode,
+ IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern bool CloseHandle(IntPtr hObject);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern bool GetCurrentConsoleFontEx(IntPtr hConsoleOutput, bool bMaximumWindow,
+ ref CONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+ private static extern bool SetCurrentConsoleFontEx(IntPtr hConsoleOutput, bool bMaximumWindow,
+ ref CONSOLE_FONT_INFOEX lpConsoleCurrentFontEx);
+
+ #endregion
+
+ #region Helpers
+
+ ///
+ /// Attaches to 's console and rescales its current font
+ /// by using SetCurrentConsoleFontEx.
+ /// This is a cross-process-safe approach that bypasses WM_DPICHANGED message passing
+ /// entirely. Works for any conhost-based console (PowerShell, cmd, etc.).
+ ///
+ public static void TryRescaleConsoleFont(uint processId, double scaleFactor)
+ {
+ if (Math.Abs(scaleFactor - 1.0) < 0.01)
+ return;
+
+ if (!AttachConsole(processId))
+ return;
+
+ const uint GENERIC_READ_WRITE = 0xC0000000u;
+ const uint FILE_SHARE_READ_WRITE = 3u;
+ const uint OPEN_EXISTING = 3u;
+
+ var hOut = CreateFile("CONOUT$", GENERIC_READ_WRITE, FILE_SHARE_READ_WRITE,
+ IntPtr.Zero, OPEN_EXISTING, 0u, IntPtr.Zero);
+
+ try
+ {
+ if (hOut == INVALID_HANDLE_VALUE)
+ return;
+
+ try
+ {
+ var fi = new CONSOLE_FONT_INFOEX { cbSize = (uint)Marshal.SizeOf() };
+ if (GetCurrentConsoleFontEx(hOut, false, ref fi))
+ {
+ fi.dwFontSize.Y = (short)Math.Max(1, (int)Math.Round(fi.dwFontSize.Y * scaleFactor));
+ fi.cbSize = (uint)Marshal.SizeOf();
+ SetCurrentConsoleFontEx(hOut, false, ref fi);
+ }
+ }
+ finally
+ {
+ CloseHandle(hOut);
+ }
+ }
+ finally
+ {
+ FreeConsole();
+ }
+ }
+
+ ///
+ /// Sends a WM_DPICHANGED message to a GUI window (e.g. PuTTY) so it can
+ /// rescale its fonts and layout internally. This is necessary because
+ /// WM_DPICHANGED is not reliably forwarded to cross-process child windows
+ /// embedded via SetParent. Requires PuTTY 0.75+ to take effect.
+ ///
+ public static void TrySendDpiChangedMessage(IntPtr hWnd, double oldDpi, double newDpi)
+ {
+ if (hWnd == IntPtr.Zero)
+ return;
+
+ if (Math.Abs(newDpi - oldDpi) < 0.01)
+ return;
+
+ const uint WM_DPICHANGED = 0x02E0;
+
+ var newDpiInt = (int)Math.Round(newDpi);
+ var wParam = (IntPtr)((newDpiInt << 16) | newDpiInt); // HIWORD = Y DPI, LOWORD = X DPI
+
+ // Build the suggested new rect from the current window position.
+ var rect = new RECT();
+ GetWindowRect(hWnd, ref rect);
+
+ // lParam must point to a RECT with the suggested new size/position.
+ var lParam = Marshal.AllocHGlobal(Marshal.SizeOf());
+ try
+ {
+ Marshal.StructureToPtr(rect, lParam, false);
+ SendMessage(hWnd, WM_DPICHANGED, wParam, lParam);
+ }
+ finally
+ {
+ Marshal.FreeHGlobal(lParam);
+ }
+ }
+
#endregion
}
\ No newline at end of file
diff --git a/Source/NETworkManager/Controls/PowerShellControl.xaml b/Source/NETworkManager/Controls/PowerShellControl.xaml
index 051baa2312..7730f87c68 100644
--- a/Source/NETworkManager/Controls/PowerShellControl.xaml
+++ b/Source/NETworkManager/Controls/PowerShellControl.xaml
@@ -19,7 +19,8 @@
-
+