Files
2025-08-23 21:39:21 +08:00

170 lines
7.6 KiB
C#

using OSVersionExtension;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using Ink_Canvas.Helpers;
using Vanara.PInvoke;
namespace Ink_Canvas {
public partial class MainWindow : PerformanceTransparentWin {
public IntPtr MagnificationWinHandle;
public IntPtr MagnificationHostWindowHandle;
public bool isFreezeFrameLoaded = false;
[DllImport("user32.dll")]
static extern bool UpdateWindow(IntPtr hWnd);
/// <summary>
/// 初始化画面定格窗口
/// </summary>
/// <param name="hwndsList"></param>
public void InitFreezeWindow(HWND[] hwndsList) {
isFreezeFrameLoaded = false;
if (OSVersion.GetOperatingSystem() < OSVersionExtension.OperatingSystem.Windows81) return;
if (!Magnification.MagInitialize()) return;
// 註冊宿主窗體類名
var wndClassEx = new WNDCLASSEX {
cbSize = (uint)Marshal.SizeOf<WNDCLASSEX>(), style = CS_HREDRAW | CS_VREDRAW,
lpfnWndProc = StaticWndProcDelegate, hInstance = IntPtr.Zero,
hCursor = LoadCursor(IntPtr.Zero, IDC_ARROW), hbrBackground = (IntPtr)(1 + COLOR_BTNFACE),
lpszClassName = "ICCMagnifierWindowHostForFreezeFrame",
hIcon = IntPtr.Zero, hIconSm = IntPtr.Zero
};
RegisterClassEx(ref wndClassEx);
// 創建宿主窗體
var windowHostHandle = CreateWindowEx(
WS_EX_TOPMOST | WS_EX_LAYERED, "ICCMagnifierWindowHostForFreezeFrame", "ICCMagnifierWindowHostWindowForFreezeFrame",
WS_SIZEBOX | WS_SYSMENU | WS_CLIPCHILDREN | WS_CAPTION | WS_MAXIMIZEBOX, 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero);
// 設定分層窗體
SetLayeredWindowAttributes(windowHostHandle, 0, 0, LWA_ALPHA);
// 創建放大鏡窗體
var hwndMag = CreateWindowEx(
0, Magnification.WC_MAGNIFIER, "ICCMagnifierWindowForFreezeFrame", WS_CHILD | WS_VISIBLE | MS_CLIPAROUNDCURSOR, 0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height, windowHostHandle,
IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
// 設定窗體樣式和排布
int style = GetWindowLong(windowHostHandle, GWL_STYLE);
style &= ~WS_CAPTION; // 隐藏标题栏
style &= ~WS_THICKFRAME; // 禁止窗口拉伸
SetWindowLong(windowHostHandle, GWL_STYLE, style);
SetWindowPos(windowHostHandle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOSIZE | SWP_FRAMECHANGED);
// 設定額外樣式
int exStyle = GetWindowLong(windowHostHandle, GWL_EXSTYLE);
exStyle |= WS_EX_TOOLWINDOW; /* <- 隐藏任务栏图标 */
exStyle &= ~WS_EX_APPWINDOW;
SetWindowLong(windowHostHandle, GWL_EXSTYLE, exStyle);
// 导出成员
MagnificationWinHandle = hwndMag;
MagnificationHostWindowHandle = windowHostHandle;
// 設定放大鏡工廠
Magnification.MAGTRANSFORM matrix = new Magnification.MAGTRANSFORM();
matrix[0, 0] = 1.0f;
matrix[0, 1] = 0.0f;
matrix[0, 2] = 0.0f;
matrix[1, 0] = 0.0f;
matrix[1, 1] = 1.0f;
matrix[1, 2] = 0.0f;
matrix[2, 0] = 1.0f;
matrix[2, 1] = 0.0f;
matrix[2, 2] = 0.0f;
if (!Magnification.MagSetWindowTransform(hwndMag, matrix)) return;
// 設定放大鏡轉化矩乘陣列
Magnification.MAGCOLOREFFECT magEffect = new Magnification.MAGCOLOREFFECT();
magEffect[0, 0] = 1.0f;
magEffect[0, 1] = 0.0f;
magEffect[0, 2] = 0.0f;
magEffect[0, 3] = 0.0f;
magEffect[0, 4] = 0.0f;
magEffect[1, 0] = 0.0f;
magEffect[1, 1] = 1.0f;
magEffect[1, 2] = 0.0f;
magEffect[1, 3] = 0.0f;
magEffect[1, 4] = 0.0f;
magEffect[2, 0] = 0.0f;
magEffect[2, 1] = 0.0f;
magEffect[2, 2] = 1.0f;
magEffect[2, 3] = 0.0f;
magEffect[2, 4] = 0.0f;
magEffect[3, 0] = 0.0f;
magEffect[3, 1] = 0.0f;
magEffect[3, 2] = 0.0f;
magEffect[3, 3] = 1.0f;
magEffect[3, 4] = 0.0f;
magEffect[4, 0] = 0.0f;
magEffect[4, 1] = 0.0f;
magEffect[4, 2] = 0.0f;
magEffect[4, 3] = 0.0f;
magEffect[4, 4] = 1.0f;
if (!Magnification.MagSetColorEffect(hwndMag, magEffect)) return;
// 顯示窗體
ShowWindow(windowHostHandle, SW_SHOW);
// 过滤窗口
var hwnds = new List<HWND> { hwndMag };
hwnds.AddRange(hwndsList);
if (!Magnification.MagSetWindowFilterList(hwndMag, Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE,
hwnds.Count, hwnds.ToArray())) return;
// 设置窗口 Source
if (!Magnification.MagSetWindowSource(hwndMag, new RECT(0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return;
InvalidateRect(hwndMag, IntPtr.Zero, true);
isFreezeFrameLoaded = true;
}
public async Task<bool> InitFreezeWindowAsync(HWND[] hwndsList) {
return await Task.Run(() => {
InitFreezeWindow(hwndsList);
return true;
});
}
public void DisposeFreezeFrame() {
// 反注册宿主窗口
UnregisterClass("ICCMagnifierWindowHostForFreezeFrame", IntPtr.Zero);
// 销毁宿主窗口
Magnification.MagUninitialize();
DestroyWindow(MagnificationHostWindowHandle);
}
public void SetFreezeFrameWindowsFilterList(HWND[] hwndsList) {
if (!isFreezeFrameLoaded) return;
var hwnds = new List<HWND> { MagnificationWinHandle };
hwnds.AddRange(hwndsList);
if (!Magnification.MagSetWindowFilterList(MagnificationWinHandle, Magnification.MW_FILTERMODE.MW_FILTERMODE_EXCLUDE,
hwnds.Count, hwnds.ToArray())) return;
}
public Bitmap GetFreezedFrame() {
if (!isFreezeFrameLoaded) return new Bitmap(1,1);
if (!Magnification.MagSetWindowSource(MagnificationWinHandle, new RECT(0, 0,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width,
System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height))) return new Bitmap(1,1);
InvalidateRect(MagnificationWinHandle, IntPtr.Zero, true);
UpdateWindow(MagnificationHostWindowHandle);
RECT rect;
GetWindowRect(MagnificationWinHandle, out rect);
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
Graphics memoryGraphics = Graphics.FromImage(bmp);
PrintWindow(MagnificationWinHandle, memoryGraphics.GetHdc(), PW_RENDERFULLCONTENT);
memoryGraphics.ReleaseHdc();
return bmp;
}
public async Task<Bitmap> GetFreezedFrameAsync() {
if (!isFreezeFrameLoaded) return null;
var result = await Task.Run(GetFreezedFrame);
return result;
}
}
}