Works
This commit is contained in:
parent
b258630e07
commit
ce6d776257
8 changed files with 1 additions and 779 deletions
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Strong privacy colour effect: desaturated + darkened.
|
|
||||||
/// Not a geometric blur, but kills readability hard.
|
|
||||||
/// </summary>
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -47,22 +47,10 @@
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AcrylicOverlay.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="BlurHelper.cs" />
|
|
||||||
<Compile Include="BlurOverlay.cs">
|
<Compile Include="BlurOverlay.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="GaussianBlur.cs" />
|
|
||||||
<Compile Include="HotkeyFilter.cs" />
|
<Compile Include="HotkeyFilter.cs" />
|
||||||
<Compile Include="MagnifyOverlay.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Native.cs" />
|
|
||||||
<Compile Include="OverlayWindow.cs">
|
|
||||||
<SubType>Form</SubType>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Program.cs" />
|
<Compile Include="Program.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="TrayApp.cs" />
|
<Compile Include="TrayApp.cs" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
using PrivacyGlass.PrivacyGlass;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
@ -75,24 +74,6 @@ namespace PrivacyGlass
|
||||||
return menu;
|
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()
|
private void CreateOverlays()
|
||||||
{
|
{
|
||||||
foreach (var screen in Screen.AllScreens)
|
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() =>
|
private void Toggle() =>
|
||||||
overlays.ForEach(o => o.Toggle());
|
overlays.ForEach(o => o.Toggle());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue