From ce6d776257f8bf89c19261416f21a7dcda0d8b54 Mon Sep 17 00:00:00 2001 From: Trevor Hall Date: Tue, 9 Dec 2025 21:47:37 -0500 Subject: [PATCH] Works --- PrivacyGlass/AcrylicOverlay.cs | 124 -------------------- PrivacyGlass/BlurHelper.cs | 41 ------- PrivacyGlass/GaussianBlur.cs | 78 ------------- PrivacyGlass/MagnifyOverlay.cs | 189 ------------------------------- PrivacyGlass/Native.cs | 158 -------------------------- PrivacyGlass/OverlayWindow.cs | 149 ------------------------ PrivacyGlass/PrivacyGlass.csproj | 12 -- PrivacyGlass/TrayApp.cs | 29 +---- 8 files changed, 1 insertion(+), 779 deletions(-) delete mode 100644 PrivacyGlass/AcrylicOverlay.cs delete mode 100644 PrivacyGlass/BlurHelper.cs delete mode 100644 PrivacyGlass/GaussianBlur.cs delete mode 100644 PrivacyGlass/MagnifyOverlay.cs delete mode 100644 PrivacyGlass/Native.cs delete mode 100644 PrivacyGlass/OverlayWindow.cs diff --git a/PrivacyGlass/AcrylicOverlay.cs b/PrivacyGlass/AcrylicOverlay.cs deleted file mode 100644 index 81adda5..0000000 --- a/PrivacyGlass/AcrylicOverlay.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Drawing; -using System.Runtime.InteropServices; -using System.Windows.Forms; - -namespace PrivacyGlass -{ - public class AcrylicOverlay : Form - { - private int _tintOpacity = 70; - private Color _tintColor = Color.Green; - private bool _isEnabled = false; - - public int TintOpacity - { - get { return _tintOpacity; } - set { _tintOpacity = value; } - } - - public Color TintColor - { - get { return _tintColor; } - set { _tintColor = value; } - } - - public AcrylicOverlay(Rectangle bounds) - { - FormBorderStyle = FormBorderStyle.None; - StartPosition = FormStartPosition.Manual; - Bounds = bounds; - ShowInTaskbar = false; - TopMost = true; - } - - public void Toggle() - { - if (_isEnabled) - { - _isEnabled = false; - Hide(); - } - else - { - _isEnabled = true; - Show(); - EnableAcrylic(); - } - } - - protected override bool ShowWithoutActivation - { - get { return true; } - } - - protected override void OnPaint(PaintEventArgs e) - { - using (SolidBrush brush = new SolidBrush(Color.FromArgb(_tintOpacity, _tintColor))) - { - e.Graphics.FillRectangle(brush, this.ClientRectangle); - } - } - - private void EnableAcrylic() - { - ACCENT_POLICY accent = new ACCENT_POLICY(); - accent.AccentState = (int)AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND; - accent.AccentFlags = 2; // simplest, most compatible - accent.Color = (_tintOpacity << 24) | - (_tintColor.R << 16) | - (_tintColor.G << 8) | - _tintColor.B; - - int size = Marshal.SizeOf(typeof(ACCENT_POLICY)); - IntPtr accentPtr = Marshal.AllocHGlobal(size); - Marshal.StructureToPtr(accent, accentPtr, false); - - WINDOWCOMPOSITIONATTRIBDATA data = new WINDOWCOMPOSITIONATTRIBDATA(); - data.Attribute = (int)WindowCompositionAttribute.WCA_ACCENT_POLICY; - data.Data = accentPtr; - data.SizeOfData = size; - - SetWindowCompositionAttribute(this.Handle, ref data); - Marshal.FreeHGlobal(accentPtr); - } - - // ---------------------------------------------------- - // Native - // ---------------------------------------------------- - - private enum AccentState - { - ACCENT_DISABLED = 0, - ACCENT_ENABLE_BLURBEHIND = 3, - ACCENT_ENABLE_ACRYLICBLURBEHIND = 4 - } - - private enum WindowCompositionAttribute - { - WCA_ACCENT_POLICY = 19 - } - - [StructLayout(LayoutKind.Sequential)] - private struct ACCENT_POLICY - { - public int AccentState; - public int AccentFlags; - public int Color; - public int AnimationId; - } - - [StructLayout(LayoutKind.Sequential)] - private struct WINDOWCOMPOSITIONATTRIBDATA - { - public int Attribute; - public IntPtr Data; - public int SizeOfData; - } - - [DllImport("user32.dll")] - private static extern int SetWindowCompositionAttribute( - IntPtr hwnd, - ref WINDOWCOMPOSITIONATTRIBDATA data); - } -} diff --git a/PrivacyGlass/BlurHelper.cs b/PrivacyGlass/BlurHelper.cs deleted file mode 100644 index 3580033..0000000 --- a/PrivacyGlass/BlurHelper.cs +++ /dev/null @@ -1,41 +0,0 @@ - -using System.Drawing; -using System.Drawing.Drawing2D; - -namespace PrivacyGlass -{ - - public static class BlurHelper - { - // factor 4–12 is good; higher = more blurry - public static Bitmap DownscaleBlur(Bitmap source, int factor = 8) - { - if (factor < 2) factor = 2; - - int w = source.Width / factor; - int h = source.Height / factor; - if (w < 1) w = 1; - if (h < 1) h = 1; - - // downscale - var small = new Bitmap(w, h); - using (var g = Graphics.FromImage(small)) - { - g.InterpolationMode = InterpolationMode.HighQualityBilinear; - g.DrawImage(source, new Rectangle(0, 0, w, h)); - } - - // upscale back - var blurred = new Bitmap(source.Width, source.Height); - using (var g = Graphics.FromImage(blurred)) - { - g.InterpolationMode = InterpolationMode.HighQualityBilinear; - g.DrawImage(small, new Rectangle(0, 0, blurred.Width, blurred.Height)); - } - - small.Dispose(); - return blurred; - } - } - -} diff --git a/PrivacyGlass/GaussianBlur.cs b/PrivacyGlass/GaussianBlur.cs deleted file mode 100644 index d777f4a..0000000 --- a/PrivacyGlass/GaussianBlur.cs +++ /dev/null @@ -1,78 +0,0 @@ - -using System; -using System.Drawing; -using System.Drawing.Imaging; - -namespace PrivacyGlass -{ - - public static class GaussianBlur - { - // 5x5 gaussian kernel (sigma ~1.0) - private static readonly double[,] kernel = - { - { 1, 4, 7, 4, 1 }, - { 4, 16, 26, 16, 4 }, - { 7, 26, 41, 26, 7 }, - { 4, 16, 26, 16, 4 }, - { 1, 4, 7, 4, 1 } - }; - - private const double kernelSum = 273; - - public static unsafe Bitmap Blur(Bitmap image) - { - int w = image.Width; - int h = image.Height; - Bitmap blurred = new Bitmap(w, h, PixelFormat.Format32bppArgb); - - BitmapData srcData = - image.LockBits(new Rectangle(0, 0, w, h), - ImageLockMode.ReadOnly, - PixelFormat.Format32bppArgb); - - BitmapData dstData = - blurred.LockBits(new Rectangle(0, 0, w, h), - ImageLockMode.WriteOnly, - PixelFormat.Format32bppArgb); - - int stride = srcData.Stride; - - byte* src = (byte*)srcData.Scan0; - byte* dst = (byte*)dstData.Scan0; - - for (int y = 2; y < h - 2; y++) - { - for (int x = 2; x < w - 2; x++) - { - double b = 0, g = 0, r = 0; - - // apply kernel - for (int ky = -2; ky <= 2; ky++) - { - for (int kx = -2; kx <= 2; kx++) - { - byte* p = src + ((y + ky) * stride) + ((x + kx) * 4); - double wgt = kernel[ky + 2, kx + 2]; - - b += p[0] * wgt; - g += p[1] * wgt; - r += p[2] * wgt; - } - } - - byte* o = dst + (y * stride) + (x * 4); - o[0] = (byte)(b / kernelSum); - o[1] = (byte)(g / kernelSum); - o[2] = (byte)(r / kernelSum); - o[3] = 255; - } - } - - image.UnlockBits(srcData); - blurred.UnlockBits(dstData); - return blurred; - } - } - -} diff --git a/PrivacyGlass/MagnifyOverlay.cs b/PrivacyGlass/MagnifyOverlay.cs deleted file mode 100644 index 5749c9d..0000000 --- a/PrivacyGlass/MagnifyOverlay.cs +++ /dev/null @@ -1,189 +0,0 @@ - -using System; -using System.Drawing; -using System.Windows.Forms; - -namespace PrivacyGlass -{ - - namespace PrivacyGlass - { - public class MagnifyOverlay : Form - { - private static bool _magInitialized; - private readonly Rectangle _screenBounds; - private IntPtr _magWindow = IntPtr.Zero; - - public bool Blackout { get; set; } = false; // set true if you want pure black instead - public int Darken = 80; // optional extra dark tint 0–100 - public double blurScale = 0.5; - - public MagnifyOverlay(Rectangle bounds) - { - _screenBounds = bounds; - - FormBorderStyle = FormBorderStyle.None; - StartPosition = FormStartPosition.Manual; - Bounds = bounds; - ShowInTaskbar = false; - TopMost = true; - DoubleBuffered = true; - BackColor = Color.Black; - Opacity = 1.0; - Visible = false; - } - private void ApplyBlurTransform() - { - // scale down slightly -> blur when drawn full size - float scale = 0.1f; // 0.7 is lighter blur, 0.3 is heavy blur - - var m = new Native.MAGTRANSFORM - { - v = new float[9] - }; - - m.v[0] = scale; // scale X - m.v[4] = scale; // scale Y - m.v[8] = 1.0f; // w - - Native.MagSetWindowTransform(_magWindow, ref m); - } - private void RefreshSource() - { - if (_magWindow == IntPtr.Zero) - return; - - // full screen size - int fullW = _screenBounds.Width; - int fullH = _screenBounds.Height; - - // reduced sampling size - int sampleW = (int)(fullW * blurScale); - int sampleH = (int)(fullH * blurScale); - - // center the sampling rect - int left = _screenBounds.Left + (fullW - sampleW) / 2; - int top = _screenBounds.Top + (fullH - sampleH) / 2; - int right = left + sampleW; - int bottom = top + sampleH; - - var srcRect = new Native.RECT - { - left = left, - top = top, - right = right, - bottom = bottom - }; - - Native.MagSetWindowSource(_magWindow, srcRect); - } - - protected override void OnHandleCreated(EventArgs e) - { - base.OnHandleCreated(e); - - if (!_magInitialized) - { - // Magnification API: initialize once per process - _magInitialized = Native.MagInitialize(); - } - - // Make the host window layered & topmost (we keep it opaque for now) - int ex = (int)Native.GetWindowLong(Handle, Native.GWL_EXSTYLE); - ex |= Native.WS_EX_TOPMOST | Native.WS_EX_LAYERED; - Native.SetWindowLong(Handle, Native.GWL_EXSTYLE, (IntPtr)ex); - - if (_magInitialized && !Blackout) - { - // Create the magnifier control as a child of this form - _magWindow = Native.CreateWindowEx( - 0, - "Magnifier", // WC_MAGNIFIER class - null, - Native.WS_CHILD | Native.WS_VISIBLE, - 0, - 0, - Width, - Height, - this.Handle, - IntPtr.Zero, - IntPtr.Zero, - IntPtr.Zero); - - if (_magWindow != IntPtr.Zero) - { - RefreshMagnifierSource(); - var fx = Native.CreatePrivacyEffect(); - Native.MagSetColorEffect(_magWindow, ref fx); - - Native.SetWindowPos( - _magWindow, - IntPtr.Zero, - 0, - 0, - Width, - Height, - 0); - RefreshSource(); - } - } - } - - private void RefreshMagnifierSource() - { - if (_magWindow == IntPtr.Zero) return; - - var src = new Native.RECT - { - left = _screenBounds.Left, - top = _screenBounds.Top, - right = _screenBounds.Right, - bottom = _screenBounds.Bottom - }; - - Native.MagSetWindowSource(_magWindow, src); - } - - public void Toggle() - { - if (Visible) - { - Hide(); - } - else - { - if (!Blackout && _magWindow != IntPtr.Zero) - { - RefreshMagnifierSource(); - } - - Show(); - } - } - - protected override void OnPaint(PaintEventArgs e) - { - base.OnPaint(e); - - // Extra dark tint over whatever Magnifier is doing - if (Darken > 0) - { - int alpha = Math.Max(0, Math.Min(255, (int)(Darken * 2.55))); - using (SolidBrush brush = new SolidBrush(Color.FromArgb(alpha, 0, 0, 0))) - { - e.Graphics.FillRectangle(brush, ClientRectangle); - } - } - } - - protected override bool ShowWithoutActivation => true; - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - // We let the process exit clean up MagUninitialize; multiple overlays share the runtime. - } - } - } - -} diff --git a/PrivacyGlass/Native.cs b/PrivacyGlass/Native.cs deleted file mode 100644 index 5f8e537..0000000 --- a/PrivacyGlass/Native.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace PrivacyGlass -{ - internal static class Native - { - [Flags] - private enum DwmBlurBehindFlags : uint - { - DWM_BB_ENABLE = 0x00000001, - DWM_BB_BLURREGION = 0x00000002, - DWM_BB_TRANSITIONONMAXIMIZED = 0x00000004 - } - - [StructLayout(LayoutKind.Sequential)] - private struct DWM_BLURBEHIND - { - public DwmBlurBehindFlags dwFlags; - public bool fEnable; - public IntPtr hRgnBlur; - public bool fTransitionOnMaximized; - } - - [DllImport("dwmapi.dll")] - private static extern int DwmEnableBlurBehindWindow( - IntPtr hWnd, - ref DWM_BLURBEHIND pBlurBehind); - - - // Window styles - public const int WS_CHILD = 0x40000000; - public const int WS_VISIBLE = 0x10000000; - - // Extended styles - public const int WS_EX_TOPMOST = 0x00000008; - public const int WS_EX_LAYERED = 0x00080000; - public const int WS_EX_TRANSPARENT = 0x00000020; - - public const int GWL_EXSTYLE = -20; - - // ----- Magnification API ----- - - [DllImport("Magnification.dll", SetLastError = true)] - internal static extern bool MagInitialize(); - - [DllImport("Magnification.dll", SetLastError = true)] - internal static extern bool MagUninitialize(); - - [DllImport("Magnification.dll", SetLastError = true)] - internal static extern bool MagSetWindowSource(IntPtr hwnd, RECT rect); - - [DllImport("Magnification.dll", SetLastError = true)] - internal static extern bool MagSetColorEffect(IntPtr hwnd, ref MAGCOLOREFFECT effect); - - // ----- User32 stuff ----- - - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern IntPtr CreateWindowEx( - int dwExStyle, - string lpClassName, - string lpWindowName, - int dwStyle, - int x, int y, - int nWidth, int nHeight, - IntPtr hWndParent, - IntPtr hMenu, - IntPtr hInstance, - IntPtr lpParam); - - [DllImport("user32.dll")] - internal static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex); - - [DllImport("user32.dll")] - internal static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong); - - [DllImport("user32.dll")] - internal static extern bool SetWindowPos( - IntPtr hWnd, - IntPtr hWndInsertAfter, - int X, int Y, - int cx, int cy, - uint uFlags); - - // structures - - [StructLayout(LayoutKind.Sequential)] - internal struct RECT - { - public int left; - public int top; - public int right; - public int bottom; - } - - [StructLayout(LayoutKind.Sequential)] - internal struct MAGCOLOREFFECT - { - // 5x5 color matrix (row-major) - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 25)] - public float[] transform; - } - - /// - /// Strong privacy colour effect: desaturated + darkened. - /// Not a geometric blur, but kills readability hard. - /// - internal static MAGCOLOREFFECT CreatePrivacyEffect() - { - var fx = new MAGCOLOREFFECT - { - transform = new float[25] - }; - - // We’ll map R,G,B all to the same gray value and darken it. - // Gray = (R+G+B)/3 * factor - float factor = 0.25f; // 0..1, lower = darker - float g = factor / 3f; - - // Row 0: R' - fx.transform[0] = g; // R - fx.transform[1] = g; // G - fx.transform[2] = g; // B - - // Row 1: G' - fx.transform[5] = g; - fx.transform[6] = g; - fx.transform[7] = g; - - // Row 2: B' - fx.transform[10] = g; - fx.transform[11] = g; - fx.transform[12] = g; - - // Row 3: A' = A - fx.transform[18] = 1.0f; - - // Row 4: w' (bias) – leave as identity - fx.transform[24] = 1.0f; - - return fx; - } - [DllImport("Magnification.dll", SetLastError = true)] - internal static extern bool MagSetWindowTransform( - IntPtr hwnd, - ref MAGTRANSFORM pTransform); - - [StructLayout(LayoutKind.Sequential)] - internal struct MAGTRANSFORM - { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 9)] - public float[] v; // 3x3 matrix - } - - } - - -} diff --git a/PrivacyGlass/OverlayWindow.cs b/PrivacyGlass/OverlayWindow.cs deleted file mode 100644 index 25b72e8..0000000 --- a/PrivacyGlass/OverlayWindow.cs +++ /dev/null @@ -1,149 +0,0 @@ - -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.Windows.Forms; - -namespace PrivacyGlass -{ - - public class OverlayWindow : Form - { - private Rectangle _screenBounds; - private Bitmap _blurred; - - // === Customizable settings === - public int Darken = 20; // 0 = no dark, 100 = full black - public bool BlurEnabled = true; // toggle blur (fast blackout vs frosted) - - public OverlayWindow(Rectangle bounds) - { - _screenBounds = bounds; - - FormBorderStyle = FormBorderStyle.None; - Bounds = bounds; - StartPosition = FormStartPosition.Manual; - TopMost = true; - ShowInTaskbar = false; - - DoubleBuffered = true; - BackgroundImageLayout = ImageLayout.Stretch; - BackColor = Color.Black; // fallback - Opacity = 1.0; - Visible = false; - } - - public void Toggle() - { - if (Visible) - { - Hide(); - } - else - { - RenderOverlay(); - Show(); - } - } - - private void RenderOverlay() - { - // === FULL BLACKOUT === - if (Darken >= 100) - { - // pure blackout, no screenshots - if (_blurred != null) { _blurred.Dispose(); _blurred = null; } - BackgroundImage = null; - return; - } - - // === otherwise capture the screen === - var bmp = new Bitmap(_screenBounds.Width, _screenBounds.Height, PixelFormat.Format32bppArgb); - using (var g = Graphics.FromImage(bmp)) - { - g.CopyFromScreen( - _screenBounds.X, - _screenBounds.Y, - 0, - 0, - _screenBounds.Size, - CopyPixelOperation.SourceCopy); - } - - // === BLUR if enabled === - if (BlurEnabled) - { - // dispose old - if (_blurred != null) { _blurred.Dispose(); _blurred = null; } - - // simple downscale blur - _blurred = DownscaleBlur(bmp, 8); - - bmp.Dispose(); - BackgroundImage = _blurred; - } - else - { - // NO BLUR — just display as-is - BackgroundImage = bmp; - } - } - - // Cheap fake blur (downscale → upscale) - private Bitmap DownscaleBlur(Bitmap source, int factor) - { - int w = Math.Max(1, source.Width / factor); - int h = Math.Max(1, source.Height / factor); - - var small = new Bitmap(w, h); - using (var g = Graphics.FromImage(small)) - { - g.InterpolationMode = InterpolationMode.HighQualityBilinear; - g.DrawImage(source, new Rectangle(0, 0, w, h)); - } - - var blurred = new Bitmap(source.Width, source.Height); - using (var g = Graphics.FromImage(blurred)) - { - g.InterpolationMode = InterpolationMode.HighQualityBilinear; - g.DrawImage(small, new Rectangle(0, 0, blurred.Width, blurred.Height)); - } - - small.Dispose(); - source.Dispose(); - return blurred; - } - - protected override void OnPaint(PaintEventArgs e) - { - base.OnPaint(e); - - // === DARKEN OVERLAY === - if (Darken > 0) - { - // convert 0-100 -> 0-255 alpha - int alpha = (int)(Darken * 2.55); - alpha = Math.Max(0, Math.Min(255, alpha)); - - using (var brush = new SolidBrush(Color.FromArgb(alpha, 0, 0, 0))) - { - e.Graphics.FillRectangle(brush, ClientRectangle); - } - } - } - - protected override bool ShowWithoutActivation => true; - - protected override void Dispose(bool disposing) - { - if (disposing && _blurred != null) - { - _blurred.Dispose(); - _blurred = null; - } - base.Dispose(disposing); - } - } - -} diff --git a/PrivacyGlass/PrivacyGlass.csproj b/PrivacyGlass/PrivacyGlass.csproj index 8a2ec5b..01903c9 100644 --- a/PrivacyGlass/PrivacyGlass.csproj +++ b/PrivacyGlass/PrivacyGlass.csproj @@ -47,22 +47,10 @@ - - Form - - Form - - - Form - - - - Form - diff --git a/PrivacyGlass/TrayApp.cs b/PrivacyGlass/TrayApp.cs index 772b89d..adcbdc2 100644 --- a/PrivacyGlass/TrayApp.cs +++ b/PrivacyGlass/TrayApp.cs @@ -1,5 +1,4 @@ -using PrivacyGlass.PrivacyGlass; -using System; +using System; using System.Collections.Generic; using System.Drawing; using System.IO; @@ -75,24 +74,6 @@ namespace PrivacyGlass return menu; } - //private void CreateOverlays() - //{ - // foreach (var scr in Screen.AllScreens) - // overlays.Add(new MagnifyOverlay(scr.Bounds)); - //} - //private void CreateOverlays() - //{ - // foreach (var screen in Screen.AllScreens) - // { - // var ov = new MagnifyOverlay(screen.Bounds) - // { - // Blackout = false, // or true if you want pure black on this screen - // Darken = 50 // tweak tint strength - // }; - - // overlays.Add(ov); - // } - //} private void CreateOverlays() { foreach (var screen in Screen.AllScreens) @@ -105,14 +86,6 @@ namespace PrivacyGlass } } - - private void Register() - { - // CTRL+ALT+B - RegisterHotKey(IntPtr.Zero, (int)HOTKEY_ID, 0x2 | 0x4, (uint)Keys.B); - Application.AddMessageFilter(new HotkeyFilter(Toggle)); - } - private void Toggle() => overlays.ForEach(o => o.Toggle());