[英]How to create a semi transparent or blurred backcolor in a Windows Form
A WinForms
Form
with a Blur effect applied to it, using:应用了模糊效果的WinForms
Form
,使用:
Windows 7 ⇒ DwmEnableBlurBehindWindow() DWM function. Windows 7 ⇒ DwmEnableBlurBehindWindow() DWM 函数。
Windows 10 ⇒ SetWindowCompositionAttribute()
User32
function (undocumented) Windows 10 ⇒ SetWindowCompositionAttribute()
User32
函数(未记录)
How to apply the Blur Behind effect :如何应用模糊背后效果:
Windows 7 :视窗 7 :
The Window needs to register a rendering policy with DwmSetWindowAttribute() , setting the DWMWINDOWATTRIBUTE enumerator to NCRenderingPolicy
and enable it, setting the DWMNCRENDERINGPOLICY enumerator to Enabled
. Window 需要使用DwmSetWindowAttribute()注册渲染策略,将DWMWINDOWATTRIBUTE枚举器设置为NCRenderingPolicy
并启用它,将DWMNCRENDERINGPOLICY枚举器设置为Enabled
。
You may also want to override a Form's class WndProc
;您可能还想覆盖 Form 的类WndProc
; when a WM_DWMCOMPOSITIONCHANGED message is received (informing of the Aero composition state), to verify whether DWN Composition is enabled.当收到WM_DWMCOMPOSITIONCHANGED消息(通知 Aero 组合状态)时,验证是否启用了 DWN 组合。
Before showing the Window interface, call DwmEnableBlurBehindWindow() , setting its DWM_BLURBEHIND structure relevant fields ( dwFlags
and fEnable
) to 1
.在显示 Window 界面之前,调用DwmEnableBlurBehindWindow() ,将其DWM_BLURBEHIND结构相关字段( dwFlags
和fEnable
)设置为1
。
Here, I'm calling it from the Form's constructor.在这里,我从 Form 的构造函数中调用它。
Windows 10 :视窗 10 :
This code is using the not yet documented SetWindowCompositionAttribute()
function.此代码使用尚未记录的SetWindowCompositionAttribute()
函数。
The User32
function only requires the use of an internal structure, here called WinCompositionAttrData
, where the Attribute
member is set to DWMWINDOWATTRIBUTE.AccentPolicy
and the Data
member is set to the pointer of an internal structure, here called AccentPolicy
, where the AccentState
member is set to DWMACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
User32
函数只需要使用内部结构,此处称为WinCompositionAttrData
,其中Attribute
成员设置为DWMWINDOWATTRIBUTE.AccentPolicy
, Data
成员设置为内部结构的指针,此处称为AccentPolicy
,其中设置了AccentState
成员到DWMACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
DWM Compostion is always enabled. DWM 组合始终处于启用状态。 No need to verify it or override WndProc
to handle a DWM Composition change.无需验证或覆盖WndProc
即可处理 DWM 组合更改。
It's more clear in code:在代码中更清楚:
(As a note, the BlurBehind
effect does not work if the Form has a white background color) (请注意,如果窗体具有白色背景色,则BlurBehind
效果不起作用)
See this other question about a DwmExtendFrameIntoClientArea()
implementation. 请参阅有关DwmExtendFrameIntoClientArea()
实现的其他问题。
public partial class frmBlurBehind : Form
{
WinApi.Dwm.DWMNCRENDERINGPOLICY policy = WinApi.Dwm.DWMNCRENDERINGPOLICY.Enabled;
WinApi.Dwm.WindowSetAttribute(this.Handle, WinApi.Dwm.DWMWINDOWATTRIBUTE.NCRenderingPolicy, (int)policy);
Version osVersion = Environment.OSVersion.Version;
if (DWNCompositionEnabled()) {
if (osVersion.Major > 6)
{
WinApi.Dwm.Windows10EnableBlurBehind(this.Handle);
}
else if(osVersion.Major == 6 && osVersion.Minor == 1)
{
WinApi.Dwm.WindowEnableBlurBehind(this.Handle);
}
}
private bool IsDWNCompositionEnabled() => (Environment.OSVersion.Version.Major >= 6)
? WinApi.Dwm.IsCompositionEnabled()
: false;
//Eventually
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case (int)WinApi.WinMessage.WM_DWMCOMPOSITIONCHANGED:
if (IsDWNCompositionEnabled())
{
WinApi.Dwm.DWMNCRENDERINGPOLICY policy = WinApi.Dwm.DWMNCRENDERINGPOLICY.Enabled;
WinApi.Dwm.WindowSetAttribute(this.Handle, WinApi.Dwm.DWMWINDOWATTRIBUTE.NCRenderingPolicy, (int)policy);
WinApi.Dwm.WindowBorderlessDropShadow(this.Handle, 1);
m.Result = (IntPtr)0;
}
break;
default:
break;
}
base.WndProc(ref m);
}
}
public partial class WinApi
{
public enum WinMessage : int
{
WM_DWMCOMPOSITIONCHANGED = 0x031E, //The system will send a window the WM_DWMCOMPOSITIONCHANGED message to indicate that the availability of desktop composition has changed.
WM_DWMNCRENDERINGCHANGED = 0x031F, //WM_DWMNCRENDERINGCHANGED is called when the non-client area rendering status of a window has changed. Only windows that have set the flag DWM_BLURBEHIND.fTransitionOnMaximized to true will get this message.
WM_DWMCOLORIZATIONCOLORCHANGED = 0x0320, //Sent to all top-level windows when the colorization color has changed.
WM_DWMWINDOWMAXIMIZEDCHANGE = 0x0321 //WM_DWMWINDOWMAXIMIZEDCHANGE will let you know when a DWM composed window is maximized. You also have to register for this message as well. You'd have other windowd go opaque when this message is sent.
}
public class Dwm
public enum DWMWINDOWATTRIBUTE : uint
{
NCRenderingEnabled = 1, //Get only atttribute
NCRenderingPolicy, //Enable or disable non-client rendering
TransitionsForceDisabled,
AllowNCPaint,
CaptionButtonBounds,
NonClientRtlLayout,
ForceIconicRepresentation,
Flip3DPolicy,
ExtendedFrameBounds,
HasIconicBitmap,
DisallowPeek,
ExcludedFromPeek,
Cloak,
Cloaked,
FreezeRepresentation
PlaceHolder1,
PlaceHolder2,
PlaceHolder3,
AccentPolicy = 19
}
public enum DWMNCRENDERINGPOLICY : uint
{
UseWindowStyle, // Enable/disable non-client rendering based on window style
Disabled, // Disabled non-client rendering; window style is ignored
Enabled, // Enabled non-client rendering; window style is ignored
};
// Values designating how Flip3D treats a given window.
enum DWMFLIP3DWINDOWPOLICY : uint
{
Default, // Hide or include the window in Flip3D based on window style and visibility.
ExcludeBelow, // Display the window under Flip3D and disabled.
ExcludeAbove, // Display the window above Flip3D and enabled.
};
[StructLayout(LayoutKind.Sequential)]
public struct DWM_BLURBEHIND
{
public DWM_BB dwFlags;
public int fEnable;
public IntPtr hRgnBlur;
public int fTransitionOnMaximized;
public DWM_BLURBEHIND(bool enabled)
{
dwFlags = DWM_BB.Enable;
fEnable = (enabled) ? 1 : 0;
hRgnBlur = IntPtr.Zero;
fTransitionOnMaximized = 0;
}
[Flags]
public enum DWM_BB
{
Enable = 1,
BlurRegion = 2,
TransitionOnMaximized = 4
}
public enum DWMACCENTSTATE
{
ACCENT_DISABLED = 0,
ACCENT_ENABLE_GRADIENT = 1,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
ACCENT_INVALID_STATE = 4
}
[StructLayout(LayoutKind.Sequential)]
public struct AccentPolicy
{
public DWMACCENTSTATE AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
public AccentPolicy(DWMACCENTSTATE accentState, int accentFlags, int gradientColor, int animationId)
{
AccentState = accentState;
AccentFlags = accentFlags;
GradientColor = gradientColor;
AnimationId = animationId;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct WinCompositionAttrData
{
public DWMWINDOWATTRIBUTE Attribute;
public IntPtr Data; //Will point to an AccentPolicy struct, where Attribute will be DWMWINDOWATTRIBUTE.AccentPolicy
public int SizeOfData;
public WinCompositionAttrData(DWMWINDOWATTRIBUTE attribute, IntPtr data, int sizeOfData)
{
Attribute = attribute;
Data = data;
SizeOfData = sizeOfData;
}
}
public struct MARGINS
{
public int leftWidth;
public int rightWidth;
public int topHeight;
public int bottomHeight;
public MARGINS(int LeftWidth, int RightWidth, int TopHeight, int BottomHeight)
{
leftWidth = LeftWidth;
rightWidth = RightWidth;
topHeight = TopHeight;
bottomHeight = BottomHeight;
}
public void NoMargins()
{
leftWidth = 0;
rightWidth = 0;
topHeight = 0;
bottomHeight = 0;
}
public void SheetOfGlass()
{
leftWidth = -1;
rightWidth = -1;
topHeight = -1;
bottomHeight = -1;
}
}
[SuppressUnmanagedCodeSecurity]
internal static class SafeNativeMethods
{
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa969508(v=vs.85).aspx
[DllImport("dwmapi.dll")]
internal static extern int DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);
//https://msdn.microsoft.com/it-it/library/windows/desktop/aa969512(v=vs.85).aspx
[DllImport("dwmapi.dll")]
internal static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS pMarInset);
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa969515(v=vs.85).aspx
[DllImport("dwmapi.dll")]
internal static extern int DwmGetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attr, ref int attrValue, int attrSize);
//https://msdn.microsoft.com/en-us/library/windows/desktop/aa969524(v=vs.85).aspx
[DllImport("dwmapi.dll")]
internal static extern int DwmSetWindowAttribute(IntPtr hwnd, DWMWINDOWATTRIBUTE attr, ref int attrValue, int attrSize);
[DllImport("User32.dll", SetLastError = true)]
internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WinCompositionAttrData data);
[DllImport("dwmapi.dll")]
internal static extern int DwmIsCompositionEnabled(ref int pfEnabled);
}
public static bool IsCompositionEnabled()
{
int pfEnabled = 0;
int result = SafeNativeMethods.DwmIsCompositionEnabled(ref pfEnabled);
return (pfEnabled == 1) ? true : false;
}
public static bool IsNonClientRenderingEnabled(IntPtr hWnd)
{
int gwaEnabled = 0;
int result = SafeNativeMethods.DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingEnabled, ref gwaEnabled, sizeof(int));
return (gwaEnabled == 1) ? true : false;
}
public static bool WindowSetAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE Attribute, int AttributeValue)
{
int result = SafeNativeMethods.DwmSetWindowAttribute(hWnd, Attribute, ref AttributeValue, sizeof(int));
return (result == 0);
}
public static void Windows10EnableBlurBehind(IntPtr hWnd)
{
AccentPolicy accPolicy = new AccentPolicy() {
AccentState = DWMACCENTSTATE.ACCENT_ENABLE_BLURBEHIND,
};
int accentSize = Marshal.SizeOf(accPolicy);
IntPtr accentPtr = Marshal.AllocHGlobal(accentSize);
Marshal.StructureToPtr(accPolicy, accentPtr, false);
var data = new WinCompositionAttrData(DWMWINDOWATTRIBUTE.AccentPolicy, accentPtr, accentSize);
SafeNativeMethods.SetWindowCompositionAttribute(hWnd, ref data);
Marshal.FreeHGlobal(accentPtr);
}
public static bool WindowEnableBlurBehind(IntPtr hWnd)
{
//Create and populate the Blur Behind structure
DWM_BLURBEHIND Dwm_BB = new DWM_BLURBEHIND(true);
int result = SafeNativeMethods.DwmEnableBlurBehindWindow(hWnd, ref Dwm_BB);
return (result == 0);
}
public static bool WindowExtendIntoClientArea(IntPtr hWnd, WinApi.Dwm.MARGINS Margins)
{
// Extend frame on the bottom of client area
int result = SafeNativeMethods.DwmExtendFrameIntoClientArea(hWnd, ref Margins);
return (result == 0);
}
public static bool WindowBorderlessDropShadow(IntPtr hWnd, int ShadowSize)
{
MARGINS Margins = new MARGINS(0, ShadowSize, 0, ShadowSize);
int result = SafeNativeMethods.DwmExtendFrameIntoClientArea(hWnd, ref Margins);
return (result == 0);
}
public static bool WindowSheetOfGlass(IntPtr hWnd)
{
MARGINS Margins = new MARGINS();
Margins.SheetOfGlass();
//Margins set to All:-1 - Sheet Of Glass effect
int result = SafeNativeMethods.DwmExtendFrameIntoClientArea(hWnd, ref Margins);
return (result == 0);
}
public static bool WindowDisableRendering(IntPtr hWnd)
{
DWMNCRENDERINGPOLICY NCRP = DWMNCRENDERINGPOLICY.Disabled;
int ncrp = (int)NCRP;
// Disable non-client area rendering on the window.
int result = SafeNativeMethods.DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingPolicy, ref ncrp, sizeof(int));
return (result == 0);
}
}
}
This is a sample result with a Form.BackColor
set to MidnightBlue
:这是一个将Form.BackColor
设置为MidnightBlue
的示例结果:
Window Selected Windows Unselected
With some controls on it:对其进行一些控制:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.