[C#] 纯文本查看 复制代码
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace AutoScalingDLL
{
public class AutoScaler
{
[DllImport("user32.dll")]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId();
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
private const int WH_CALLWNDPROC = 4;
private const int WM_SIZE = 0x0005;
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
private struct CWPSTRUCT
{
public IntPtr lParam;
public IntPtr wParam;
public int message;
public IntPtr hwnd;
}
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
private static IntPtr _hookHandle = IntPtr.Zero;
private static HookProc _hookProc;
private static IntPtr _mainWindowHandle;
private static Dictionary<IntPtr, ControlInfo> _controls = new Dictionary<IntPtr, ControlInfo>();
private static RECT _originalWindowRect;
private class ControlInfo
{
public float LeftRatio;
public float TopRatio;
public float WidthRatio;
public float HeightRatio;
}
[DllExport("InitializeAutoScaling", CallingConvention = CallingConvention.StdCall)]
public static bool InitializeAutoScaling(IntPtr hWnd)
{
if (_hookHandle != IntPtr.Zero)
{
return false; // Already initialized
}
_mainWindowHandle = hWnd;
GetWindowRect(_mainWindowHandle, out _originalWindowRect);
_hookProc = new HookProc(WindowProc);
_hookHandle = SetWindowsHookEx(WH_CALLWNDPROC, _hookProc, IntPtr.Zero, GetCurrentThreadId());
return _hookHandle != IntPtr.Zero;
}
[DllExport("AddControlToAutoScale", CallingConvention = CallingConvention.StdCall)]
public static bool AddControlToAutoScale(IntPtr hWnd)
{
if (_hookHandle == IntPtr.Zero || _controls.ContainsKey(hWnd))
{
return false;
}
RECT controlRect;
GetWindowRect(hWnd, out controlRect);
int windowWidth = _originalWindowRect.Right - _originalWindowRect.Left;
int windowHeight = _originalWindowRect.Bottom - _originalWindowRect.Top;
ControlInfo info = new ControlInfo
{
LeftRatio = (float)(controlRect.Left - _originalWindowRect.Left) / windowWidth,
TopRatio = (float)(controlRect.Top - _originalWindowRect.Top) / windowHeight,
WidthRatio = (float)(controlRect.Right - controlRect.Left) / windowWidth,
HeightRatio = (float)(controlRect.Bottom - controlRect.Top) / windowHeight
};
_controls.Add(hWnd, info);
return true;
}
private static IntPtr WindowProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0)
{
CWPSTRUCT cwp = (CWPSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPSTRUCT));
if (cwp.message == WM_SIZE && cwp.hwnd == _mainWindowHandle)
{
RECT newRect;
GetWindowRect(_mainWindowHandle, out newRect);
int newWidth = newRect.Right - newRect.Left;
int newHeight = newRect.Bottom - newRect.Top;
foreach (var kvp in _controls)
{
IntPtr controlHandle = kvp.Key;
ControlInfo info = kvp.Value;
int newLeft = (int)(info.LeftRatio * newWidth);
int newTop = (int)(info.TopRatio * newHeight);
int newControlWidth = (int)(info.WidthRatio * newWidth);
int newControlHeight = (int)(info.HeightRatio * newHeight);
MoveWindow(controlHandle, newLeft, newTop, newControlWidth, newControlHeight, true);
}
}
}
return CallNextHookEx(_hookHandle, nCode, wParam, lParam);
}
[DllExport("FinalizeAutoScaling", CallingConvention = CallingConvention.StdCall)]
public static void FinalizeAutoScaling()
{
if (_hookHandle != IntPtr.Zero)
{
UnhookWindowsHookEx(_hookHandle);
_hookHandle = IntPtr.Zero;
}
_controls.Clear();
}
}
}