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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AcrylicOverlay.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="BlurHelper.cs" />
|
||||
<Compile Include="BlurOverlay.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="GaussianBlur.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="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="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());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue