Last active
January 28, 2023 06:48
-
-
Save luojunyuan/d7cee85b8535547f8625a3f6d61eea3d to your computer and use it in GitHub Desktop.
This file contains 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 System.Windows.Threading; | |
using System.Windows; | |
using System.Windows.Interop; | |
namespace MagnifierWpf; | |
public class MagWindow : Window | |
{ | |
private float magnification; | |
private int _sourceWidth = 400; | |
private int _sourceHeight = 50; | |
private static double StableScreenWidth = NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN); | |
private static double StableScreenHeight = NativeMethods.GetSystemMetrics(NativeMethods.SM_CYSCREEN); | |
public MagWindow() | |
{ | |
// DPI に関わる | |
var dpi = 2; | |
var screenWidth = StableScreenWidth / dpi; | |
var screenHeight = StableScreenHeight / dpi; | |
magnification = screenWidth / _sourceWidth; | |
Console.WriteLine($"Scale x{magnification}"); | |
Left = 0; | |
Width = screenWidth; | |
Height = _sourceHeight * magnification; | |
Top = screenHeight - Height; | |
AllowsTransparency = true; | |
WindowStyle = WindowStyle.None; | |
Background = System.Windows.Media.Brushes.Transparent; | |
Loaded += MagWindowOnLoaded; | |
Closed += MagWindowOnClosed; | |
} | |
private RECT _magWindowRect = new RECT(); | |
private nint _handle; | |
private DispatcherTimer _timer = new(); | |
private nint _hwndMag; | |
private void MagWindowOnLoaded(object? sender, RoutedEventArgs e) | |
{ | |
// 順番 initialize -> Setuo -> Start timer | |
var initialized = NativeMethods.MagInitialize(); | |
if (initialized) | |
{ | |
// Just like a fill parameter | |
var hInst = NativeMethods.GetModuleHandle(null); | |
_handle = new WindowInteropHelper(this).Handle; | |
// Create a magnifier control that fills the client area. | |
NativeMethods.GetClientRect(_handle, ref _magWindowRect); // _magWindowRect get the window height width | |
_hwndMag = NativeMethods.CreateWindow( | |
(int)ExtendedWindowStyles.WS_EX_CLIENTEDGE, | |
NativeMethods.WC_MAGNIFIER, | |
"MagnifierWindow", | |
(int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_SHOWMAGNIFIEDCURSOR | (int)WindowStyles.WS_VISIBLE, | |
_magWindowRect.left, _magWindowRect.top, _magWindowRect.right, _magWindowRect.bottom, | |
_handle, // this parameter bind to wpf window | |
IntPtr.Zero, hInst, IntPtr.Zero); | |
if (_hwndMag == IntPtr.Zero) | |
{ | |
throw new ArgumentNullException(); | |
} | |
// var isSmoothingActive = NativeMethods.MagSetLensUseBitmapSmoothing(_hwndMag, true); | |
// Set the magnification factor. | |
Transformation matrix = new Transformation(magnification); | |
NativeMethods.MagSetWindowTransform(_hwndMag, ref matrix); | |
_timer.Tick += UpdateMaginifier; | |
_timer.Interval = TimeSpan.FromMilliseconds(NativeMethods.USER_TIMER_MINIMUM); | |
_timer.Start(); | |
} | |
} | |
private void UpdateMaginifier(object? sender, EventArgs e) | |
{ | |
// NativeMethods.GetSystemMetrics(NativeMethods.SM_CXSCREEN) | |
RECT sourceRect = new RECT(); | |
sourceRect.left = 0; | |
sourceRect.top = 0; | |
sourceRect.right = sourceRect.left + _sourceWidth; | |
sourceRect.bottom = sourceRect.top + _sourceHeight; | |
// Set the source rectangle for the magnifier control. | |
NativeMethods.MagSetWindowSource(_hwndMag, sourceRect); | |
// Reclaim topmost status, to prevent unmagnified menus from remaining in view. | |
NativeMethods.SetWindowPos( | |
_handle, | |
NativeMethods.HWND_TOPMOST, 0, 0, 0, 0, | |
(int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE); | |
// Force redraw. | |
NativeMethods.InvalidateRect(_hwndMag, IntPtr.Zero, true); | |
} | |
private void MagWindowOnClosed(object? sender, EventArgs e) | |
{ | |
_timer.Stop(); | |
NativeMethods.MagUninitialize(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment