我如何在无边框窗体上绘制平滑模糊的玻璃效果?我已经尝试了C和GDI+图像处理入门页面上列出的代码,但我确定这不是我应该使用的。无论我怎么摆弄它,都没有产生我想要的任何结果。
基本上,这就是我想要实现的效果:
基本上,这就是我想要实现的效果:
使用像DwmEnableBlurBehindWindow这样的Win API
[DllImport("gdi32")]
private static extern IntPtr CreateEllipticRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("dwmapi")]
private static extern int DwmEnableBlurBehindWindow(IntPtr hWnd, ref DwmBlurbehind pBlurBehind);
public struct DwmBlurbehind
{
public int DwFlags;
public bool FEnable;
public IntPtr HRgnBlur;
public bool FTransitionOnMaximized;
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var hr = CreateEllipticRgn(0, 0, Width, Height);
var dbb = new DwmBlurbehind {FEnable = true, DwFlags = 1, HRgnBlur = hr, FTransitionOnMaximized = false};
DwmEnableBlurBehindWindow(Handle, ref dbb);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.FillRectangle(new SolidBrush(Color.Black), new Rectangle(0, 0, Width, Height));
}
示例2:您可以更改画笔颜色(例如:DarkRed)以获得良好的效果
注意的是,您可以选择适用于的区域,并且可以有多个。
您可以使用 相同的方法。
Wpf 对着色器有更好的支持,您可以添加像模糊之类的效果,但它们的性能较重。此外,您的图像很可能来自由 WPF 和 Blend 创建的程序。
如果我记得正确,您无法在纯色画刷上使用模糊等着色器。 因此,以下不会产生相同的效果。设置背景 50% 透明度(Window 属性 AllowsTransparency="True" 和 WindowStyle="None")
<Window.Background>
<SolidColorBrush Opacity="0.5" Color="White"/>
</Window.Background>
WPF支持已在此处描述:http://www.paulrohde.com/native-glass-with-wpf/
我使用稍微不同的方法得到了以下结果:
// Code was burrowed from:
// https://dev59.com/jGIj5IYBdhLWcg3wzIFo
// http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/CommonUI/System/Drawing/NativeMethods@cs/1305376/NativeMethods@cs
// https://dev59.com/5mw05IYBdhLWcg3wXAiF
// https://dev59.com/aEfRa4cB1Zd3GeqP8mAa */
public static class WinAPI
{
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
};
public enum GW
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[DllImport("User32.dll")]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("User32.dll", CharSet = CharSet.Unicode)]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("User32.dll")]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern bool IsIconic(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, ref RECT lpRect);
[DllImport("User32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[DllImport("User32.dll")]
public static extern IntPtr GetDesktopWindow();
[DllImport("User32.dll")]
public static extern IntPtr GetTopWindow(IntPtr hWnd);
public static IntPtr GetNextWindow(IntPtr hWnd, GW wCmd)
{
return GetWindow(hWnd, wCmd);
}
public static IntPtr GetWindow(IntPtr hWnd, GW wCmd)
{
return GetWindow(hWnd, (uint)wCmd);
}
[DllImport("User32.dll")]
private static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd);
[DllImport("User32.dll")]
public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, uint nFlags);
[DllImport("User32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("Gdi32.dll")]
public static extern bool DeleteDC(IntPtr hdc);
[DllImport("User32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("User32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hdc);
[DllImport("User32.dll")]
public static extern int GetWindowRgn(IntPtr hWnd, IntPtr hRgn);
[DllImport("Gdi32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hWnd);
[DllImport("Gdi32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height);
[DllImport("Gdi32.dll")]
public static extern IntPtr CreateBitmap(int width, int height, uint cPlanes, uint cBitsPerPel, IntPtr lpvBits);
[DllImport("Gdi32.dll")]
public static extern bool DeleteObject(IntPtr hGdiObj);
[DllImport("Gdi32.dll")]
public static extern bool SelectObject(IntPtr hdc, IntPtr hGdiObj);
[DllImport("Gdi32.dll")]
public static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
public static StringBuilder GetWindowText(IntPtr hWnd)
{
int length = GetWindowTextLength(hWnd);
// Add another place to allow null terminator
StringBuilder text = new StringBuilder(length + 1);
GetWindowText(hWnd, text, length + 1);
return text;
}
public static bool IsWindowReallyVisible(IntPtr hWnd)
{
if (!IsWindowVisible(hWnd) || IsIconic(hWnd))
return false;
RECT area = new RECT();
if (!GetWindowRect(hWnd, ref area))
return true;
if (area.left == area.right || area.bottom == area.top)
return false;
return true;
}
public enum RegionFlags
{
ERROR = 0,
NULLREGION = 1,
SIMPLEREGION = 2,
COMPLEXREGION = 3,
}
}
public class ScreenShot
{
public static List<IntPtr> GetAllWindows(Func<IntPtr, bool> filter, Func<IntPtr, bool> stop)
{
List<IntPtr> result = new List<IntPtr>();
WinAPI.EnumWindows((wnd, param) =>
{
bool relevant = filter(wnd);
if (relevant)
result.Add(wnd);
bool shouldStop = stop(wnd);
if (shouldStop)
Console.WriteLine("Stop");
return !shouldStop;
}, IntPtr.Zero);
return result;
}
public static IEnumerable<IntPtr> GetWindowsByOrder(Func<IntPtr, bool> filter)
{
List<IntPtr> skip = new List<IntPtr>();
List<IntPtr> result = new List<IntPtr>();
IntPtr desktop = WinAPI.GetDesktopWindow();
for (IntPtr wnd = WinAPI.GetTopWindow(IntPtr.Zero); wnd != IntPtr.Zero; wnd = WinAPI.GetNextWindow(wnd, WinAPI.GW.GW_HWNDNEXT))
{
if (result.Contains(wnd) || skip.Contains(wnd))
break;
else if (filter(wnd))
result.Add(wnd);
else
skip.Add(wnd);
}
result.Add(desktop);
return result;
}
public static Image GetScreenshot(IntPtr hWnd)
{
IntPtr hdcScreen = WinAPI.GetDC(hWnd);
IntPtr hdc = WinAPI.CreateCompatibleDC(hdcScreen);
WinAPI.RECT area = new WinAPI.RECT();
WinAPI.GetWindowRect(hWnd, ref area);
IntPtr hBitmap = WinAPI.CreateCompatibleBitmap(hdcScreen, area.right - area.left, area.bottom - area.top);
WinAPI.SelectObject(hdc, hBitmap);
WinAPI.PrintWindow(hWnd, hdc, 0);
Image resultOpaque = Image.FromHbitmap(hBitmap);
WinAPI.DeleteObject(hBitmap);
WinAPI.DeleteDC(hdc);
IntPtr hRegion = WinAPI.CreateRectRgn(0, 0, 0, 0);
WinAPI.RegionFlags f = (WinAPI.RegionFlags) WinAPI.GetWindowRgn(hWnd, hRegion);
Region region = Region.FromHrgn(hRegion);
WinAPI.DeleteObject(hRegion);
Bitmap result = new Bitmap(resultOpaque.Width, resultOpaque.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Graphics g = Graphics.FromImage(result);
g.Clear(Color.Transparent);
if (f != WinAPI.RegionFlags.ERROR)
g.SetClip(region, System.Drawing.Drawing2D.CombineMode.Replace);
if (f != WinAPI.RegionFlags.NULLREGION)
g.DrawImageUnscaled(resultOpaque, 0, 0);
g.Dispose();
region.Dispose();
resultOpaque.Dispose();
return result;
}
/* And now for the actual code of getting screenshots of windows */
var windows = ScreenShot.GetWindowsByOrder(this.WindowFilter).Intersect(ScreenShot.GetAllWindows(this.WindowFilter, (wnd) => false)).ToList();
int index = windows.IndexOf((IntPtr)this.Handle); /* Remove all the windows behind your windows */
if (index != -1)
windows.RemoveRange(index, windows.Count - index + 1);
windows.Reverse();
/* Get the images of all the windows */
for (int i = 0; i < windows.Count; ++i )
{
var window = windows[i];
using (var img = ScreenShot.GetScreenshot(window))
{
// Get the actual position of the window
// Draw it's image overlayed on the other windows 9have an accumulating image)
}
}
这个测试套件在Windows 8.1上还存在哪些漏洞?