在之前偶然看见一篇实现Windows窗口透明毛玻璃效果的文章,感觉有意思进去看了一下,原理是通过设置窗口样式属性达到透明窗口的目的,在Win10的窗口中仍然存在Win7的Aero效果,但是微软把它藏起来了,实际上我们仍然能设置它。原篇实现语言是C++,我用C#把它实现了,主要使用 FindWindow、GetWindowLong、SetWindowLong、SetWindowCompositionAttribute 这几个WinAPI。
命名空间:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
声明方法&构造体:
public const int GWL_EXSTYLE = -20;
public const int LWA_ALPHA = 0x00000002;
public const int WS_EX_LAYERED = 0x00080000;
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
public static extern int SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);
[StructLayout(LayoutKind.Sequential)]
public struct WindowCompositionAttributeData
{
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
public enum WindowCompositionAttribute
{
WCA_UNDEFINED = 0,
WCA_NCRENDERING_ENABLED = 1,
WCA_NCRENDERING_POLICY = 2,
WCA_TRANSITIONS_FORCEDISABLED = 3,
WCA_ALLOW_NCPAINT = 4,
WCA_CAPTION_BUTTON_BOUNDS = 5,
WCA_NONCLIENT_RTL_LAYOUT = 6,
WCA_FORCE_ICONIC_REPRESENTATION = 7,
WCA_EXTENDED_FRAME_BOUNDS = 8,
WCA_HAS_ICONIC_BITMAP = 9,
WCA_THEME_ATTRIBUTES = 10,
WCA_NCRENDERING_EXILED = 11,
WCA_NCADORNMENTINFO = 12,
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
WCA_VIDEO_OVERLAY_ACTIVE = 14,
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
WCA_DISALLOW_PEEK = 16,
WCA_CLOAK = 17,
WCA_CLOAKED = 18,
WCA_ACCENT_POLICY = 19,
WCA_FREEZE_REPRESENTATION = 20,
WCA_EVER_UNCLOAKED = 21,
WCA_VISUAL_OWNER = 22,
WCA_LAST = 23
}
public enum ACCENT_STATE
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 4,
ACCENT_INVALID_STATE = 5
}
[StructLayout(LayoutKind.Sequential)]
public struct ACCENT_POLICY
{
public ACCENT_STATE AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
[DllImport("user32.dll")]
public static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
功能实现:
窗口透明效果:
//设置窗口透明效果
private void SetWindowTransparent(IntPtr hwnd,int Alpha)
{
//IntPtr hwnd = FindWindow(null,"...");
int OldStyle = GetWindowLong(hwnd,GWL_EXSTYLE);
SetWindowLong(hwnd,GWL_EXSTYLE, OldStyle | WS_EX_LAYERED);
SetLayeredWindowAttributes(hwnd, Color.FromArgb(200, Color.Gray).ToArgb(), Alpha,LWA_ALPHA);
}
窗口模糊效果:
//设置窗口模糊效果
private void SetWindowAero(IntPtr hwnd)
{
//IntPtr hWnd = FindWindow(null,"...");
ACCENT_POLICY accent = new ACCENT_POLICY
{
AccentState = ACCENT_STATE.ACCENT_ENABLE_BLURBEHIND,
AccentFlags = 0,
AnimationId = 0,
GradientColor = 0
};
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
WindowCompositionAttributeData data = new WindowCompositionAttributeData
{
Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
Data = accentPtr,
SizeOfData = accentStructSize
};
SetWindowCompositionAttribute(hwnd, ref data);
Marshal.FreeHGlobal(accentPtr);
}
调用:
//查找窗口句柄
IntPtr hwnd = FindWindow(null,"任务管理器");
//设置窗口透明,不透明度205
SetWindowTransparent(hwnd,205);
//设置窗口模糊
SetWindowAero(hwnd);
有些窗口在设置后会出现各种各样的显示问题,所以不建议所有窗口都设置;另外模糊效果不是很理想,建议只使用透明效果,不透明度测试205最好。