Vivado-Dark-Mode-Windows-demo/Magnifier.cs
2024-10-05 03:05:33 +08:00

203 lines
6.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Karna.Magnification
{
public class Magnifier : IDisposable
{
private Form form;
private IntPtr hwndMag;
private float magnification;
private bool initialized;
private RECT magWindowRect = new RECT();
private System.Windows.Forms.Timer timer;
public nint afterHwnd;
public Magnifier(Form form)
{
if (form == null)
throw new ArgumentNullException("form");
magnification = 1.0f;
this.form = form;
this.form.Resize += new EventHandler(form_Resize);
this.form.FormClosing += new FormClosingEventHandler(form_FormClosing);
timer = new System.Windows.Forms.Timer();
timer.Tick += new EventHandler(timer_Tick);
initialized = NativeMethods.MagInitialize();
if (initialized)
{
SetupMagnifier();
timer.Interval = NativeMethods.USER_TIMER_MINIMUM;
timer.Enabled = true;
}
}
void form_FormClosing(object sender, FormClosingEventArgs e)
{
timer.Enabled = false;
}
void timer_Tick(object sender, EventArgs e)
{
UpdateMaginifier();
}
void form_Resize(object sender, EventArgs e)
{
ResizeMagnifier();
}
~Magnifier()
{
Dispose(false);
}
public virtual void ResizeMagnifier()
{
if ( initialized && (hwndMag != IntPtr.Zero))
{
NativeMethods.GetClientRect(form.Handle, ref magWindowRect);
// Resize the control to fill the window.
NativeMethods.SetWindowPos(hwndMag, IntPtr.Zero,
magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom, 0);
}
}
public virtual void UpdateMaginifier()
{
if ((!initialized) || (hwndMag == IntPtr.Zero))
return;
RECT sourceRect = new RECT();
sourceRect.left = form.Left;
sourceRect.right = form.Right;
sourceRect.top = form.Top;
sourceRect.bottom = form.Bottom;
if (this.form == null || this.form.IsDisposed)
{
timer.Enabled = false;
return;
}
// 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(hwndMag, form.Handle, 0, 0, 0, 0,
// (int)SetWindowPosFlags.SWP_NOACTIVATE | (int)SetWindowPosFlags.SWP_NOMOVE | (int)SetWindowPosFlags.SWP_NOSIZE);
// Force redraw.
redraw();
}
public virtual void redraw()
{
NativeMethods.InvalidateRect(hwndMag, IntPtr.Zero, true);
}
public float Magnification
{
get { return magnification; }
set
{
if (magnification != value)
{
magnification = value;
// Set the magnification factor.
Transformation matrix = new Transformation(magnification);
NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
}
}
}
protected void SetupMagnifier()
{
if (!initialized)
return;
IntPtr hInst;
hInst = NativeMethods.GetModuleHandle(null);
// Make the window opaque.
form.AllowTransparency = true;
form.TransparencyKey = Color.Empty;
form.Opacity = 255;
// Create a magnifier control that fills the client area.
NativeMethods.GetClientRect(form.Handle, ref magWindowRect);
hwndMag = NativeMethods.CreateWindow(
(int)ExtendedWindowStyles.WS_EX_TRANSPARENT | (int)ExtendedWindowStyles.WS_EX_NOACTIVATE,
NativeMethods.WC_MAGNIFIER,
"MagnifierWindow",
(int)WindowStyles.WS_CHILD | (int)MagnifierStyle.MS_INVERTCOLORS |
(int)WindowStyles.WS_VISIBLE,
magWindowRect.left, magWindowRect.top, magWindowRect.right, magWindowRect.bottom,
form.Handle, IntPtr.Zero, hInst, IntPtr.Zero
);
if (hwndMag == IntPtr.Zero)
{
return;
}
// Set the magnification factor.
Transformation matrix = new Transformation(magnification);
NativeMethods.MagSetWindowTransform(hwndMag, ref matrix);
}
public bool SetFilter(nint hwnd)
{
bool res = true;
//IntPtr filterHandle = Marshal.AllocHGlobal(sizeof(int));
//try
//{
// Marshal.WriteInt64(filterHandle, (nint)hwnd); // Store the integer value
// res &= NativeMethods.MagSetWindowFilterList(hwndMag, (int)FilterMode.MW_FILTERMODE_INCLUDE, 1, filterHandle);
// res &= NativeMethods.MagGetWindowFilterList(hwndMag, filterHandle, 0, filterHandle) == 1;
//}
//finally
//{
// // Free the allocated unmanaged memory to prevent memory leaks
// Marshal.FreeHGlobal(filterHandle);
//}
return res;
}
protected void RemoveMagnifier()
{
if (initialized)
NativeMethods.MagUninitialize();
}
protected virtual void Dispose(bool disposing)
{
timer.Enabled = false;
if (disposing)
timer.Dispose();
timer = null;
form.Resize -= form_Resize;
RemoveMagnifier();
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}