winforms 如何在Windows窗体中创建半透明或模糊的背景色

gkn4icbw  于 2023-01-09  发布在  Windows
关注(0)|答案(1)|浏览(185)

我正在创建一个测速仪来测量我的互联网速度,并停留在每个应用程序的顶部,然后我如何使其背景半透明或模糊这样的东西。

p1iqtdky

p1iqtdky1#

应用了模糊效果的WinFormsForm,使用:
Windows 7 ⇒ DwmEnableBlurBehindWindow()显示工作站功能。
Windows 10 / 11 ⇒**SetWindowCompositionAttribute()**User32功能(未记录)

如何应用“背景模糊”效果
Windows 7操作系统

Windows需要向DwmSetWindowAttribute()注册呈现策略,将DWMWINDOWATTRIBUTE枚举器设置为NCRenderingPolicy并启用它,将DWMNCRENDERINGPOLICY枚举器设置为Enabled
您可能还希望重写窗体的类WndProc;收到WM_DWMCOMPOSITIONCHANGED消息(通知Aero合成状态)时,验证DWM合成是否启用。
在显示Window界面之前,调用DwmEnableBlurBehindWindow(),将其DWM_BLURBEHIND结构相关字段(dwFlagsfEnable)设置为1
在这里,我从窗体的构造函数调用它。

Windows 10Windows 11

此代码使用了尚未记录的**SetWindowCompositionAttribute()函数。
User32函数仅需要使用内部结构,这里称为
WinCompositionAttrData,其中Attribute成员被设置为DWMWINDOWATTRIBUTE.AccentPolicy,并且Data成员被设置为内部结构的指针,这里称为AccentPolicy,其中AccentState成员被设置为DWMACCENTSTATE.ACCENT_ENABLE_BLURBEHIND**
“DWM合成”始终处于启用状态。无需验证或替代WndProc即可处理DWM合成更改。
在代码中更清楚:
(As注意,如果窗体的背景色为白色,则BlurBehind效果不起作用)
请参阅关于DwmExtendFrameIntoClientArea()实现的另一个问题。

public partial class frmBlurBehind : Form
{
    public frmBlurBehind()
    {
        InitializeComponent();

        // Remove the border if this is meant to be a border-less Form
        // FormBorderStyle = FormBorderStyle.None;

        if (IsDWMCompositionEnabled()) {
            if (Environment.OSVersion.Version.Major > 6) {
                Dwm.Windows10EnableBlurBehind(Handle);
            }
            else {
                Dwm.WindowEnableBlurBehind(Handle);
            }
            // Set Drop shadow of a border-less Form
            if (FormBorderStyle == FormBorderStyle.None) {
                Dwm.WindowBorderlessDropShadow(Handle, 2);
            }
        }
    }

    private bool IsDWMCompositionEnabled() => 
        Environment.OSVersion.Version.Major >= 6 && Dwm.IsCompositionEnabled();

    // Eventually, if this is a border-less Form, reapply the attribute if DWM Composition changes
    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg) {
            case Dwm.WM_DWMCOMPOSITIONCHANGED:
                if (IsDWMCompositionEnabled()) {
                    Dwm.DWMNCRENDERINGPOLICY policy = Dwm.DWMNCRENDERINGPOLICY.Enabled;
                    Dwm.WindowSetAttribute(Handle, Dwm.DWMWINDOWATTRIBUTE.NCRenderingPolicy, (int)policy);
                    Dwm.WindowBorderlessDropShadow(Handle, 2);
                    m.Result = IntPtr.Zero;
                }
                break;
            default:
                break;
        }
    }
}

Dwm类包含上面使用的所有互操作函数和结构,以及在此上下文中可能有用的一系列其他方法

[SuppressUnmanagedCodeSecurity]
public class Dwm {
    public const int WM_DWMCOMPOSITIONCHANGED = 0x031E;

    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;
        }
    }

    [Flags]
    public enum DWM_BB {
        Enable = 1,
        BlurRegion = 2,
        TransitionOnMaximized = 4
    }

    // https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute
    public enum DWMWINDOWATTRIBUTE : uint {
        NCRenderingEnabled = 1,       //Get atttribute
        NCRenderingPolicy,            //Enable or disable non-client rendering
        TransitionsForceDisabled,
        AllowNCPaint,
        CaptionButtonBounds,          //Get atttribute
        NonClientRtlLayout,
        ForceIconicRepresentation,
        Flip3DPolicy,
        ExtendedFrameBounds,          //Get atttribute
        HasIconicBitmap,
        DisallowPeek,
        ExcludedFromPeek,
        Cloak,
        Cloaked,                      //Get atttribute. Returns a DWMCLOACKEDREASON
        FreezeRepresentation,
        PassiveUpdateMode,
        UseHostBackDropBrush,
        AccentPolicy = 19,            // Win 10 (undocumented)
        ImmersiveDarkMode = 20,       // Win 11 22000
        WindowCornerPreference = 33,  // Win 11 22000
        BorderColor,                  // Win 11 22000
        CaptionColor,                 // Win 11 22000
        TextColor,                    // Win 11 22000
        VisibleFrameBorderThickness,  // Win 11 22000
        SystemBackdropType            // Win 11 22621
    }

    public enum DWMCLOACKEDREASON : uint {
        DWM_CLOAKED_APP = 0x0000001,       //cloaked by its owner application.
        DWM_CLOAKED_SHELL = 0x0000002,     //cloaked by the Shell.
        DWM_CLOAKED_INHERITED = 0x0000004  //inherited from its owner window.
    }

    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
    };

    public enum DWMACCENTSTATE {
        ACCENT_DISABLED = 0,
        ACCENT_ENABLE_GRADIENT = 1,
        ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
        ACCENT_ENABLE_BLURBEHIND = 3,
        ACCENT_INVALID_STATE = 4
    }

    [Flags]
    public enum CompositionAction : uint {
        DWM_EC_DISABLECOMPOSITION = 0,
        DWM_EC_ENABLECOMPOSITION = 1
    }

    // 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.
    };

    public enum ThumbProperties_dwFlags : uint {
        RectDestination = 0x00000001,
        RectSource = 0x00000002,
        Opacity = 0x00000004,
        Visible = 0x00000008,
        SourceClientAreaOnly = 0x00000010
    }

    [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 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;
        }

        public Region Region => Region.FromHrgn(hRgnBlur);

        public bool TransitionOnMaximized {
            get => fTransitionOnMaximized > 0;
            set {
                fTransitionOnMaximized = (value) ? 1 : 0;
                dwFlags |= DWM_BB.TransitionOnMaximized;
            }
        }

        public void SetRegion(Graphics graphics, Region region)
        {
            hRgnBlur = region.GetHrgn(graphics);
            dwFlags |= DWM_BB.BlurRegion;
        }
    }

    [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;
        }
    }

    private static int GetBlurBehindPolicyAccentFlags()
    {
        int drawLeftBorder = 20;
        int drawTopBorder = 40;
        int drawRightBorder = 80;
        int drawBottomBorder = 100;
        return (drawLeftBorder | drawTopBorder | drawRightBorder | drawBottomBorder);
    }

    //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);

    [DllImport("dwmapi.dll", PreserveSig = false)]
    public static extern void DwmEnableComposition(CompositionAction uCompositionAction);

    //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 = DwmIsCompositionEnabled(ref pfEnabled);
        return (pfEnabled == 1) ? true : false;
    }

    public static bool IsNonClientRenderingEnabled(IntPtr hWnd)
    {
        int gwaEnabled = 0;
        int result = DwmGetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingEnabled, ref gwaEnabled, sizeof(int));
        return gwaEnabled == 1;
    }

    public static bool WindowSetAttribute(IntPtr hWnd, DWMWINDOWATTRIBUTE attribute, int attributeValue)
    {
        int result = DwmSetWindowAttribute(hWnd, attribute, ref attributeValue, sizeof(int));
        return (result == 0);
    }

    public static void Windows10EnableBlurBehind(IntPtr hWnd)
    {
        DWMNCRENDERINGPOLICY policy = DWMNCRENDERINGPOLICY.Enabled;
        WindowSetAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingPolicy, (int)policy);

        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);

        SetWindowCompositionAttribute(hWnd, ref data);
        Marshal.FreeHGlobal(accentPtr);
    }

    public static bool WindowEnableBlurBehind(IntPtr hWnd)
    {
        DWMNCRENDERINGPOLICY policy = DWMNCRENDERINGPOLICY.Enabled;
        WindowSetAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingPolicy, (int)policy);

        DWM_BLURBEHIND dwm_BB = new DWM_BLURBEHIND(true);
        int result = DwmEnableBlurBehindWindow(hWnd, ref dwm_BB);
        return result == 0;
    }

    public static bool WindowExtendIntoClientArea(IntPtr hWnd, MARGINS margins)
    {
        // Extend frame on the bottom of client area
        int result = 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 = DwmExtendFrameIntoClientArea(hWnd, ref margins);
        return result == 0;
    }

    public static bool WindowSheetOfGlass(IntPtr hWnd)
    {
        MARGINS margins = new MARGINS();

        //Margins set to All:-1 - Sheet Of Glass effect
        margins.SheetOfGlass();
        int result = DwmExtendFrameIntoClientArea(hWnd, ref margins);
        return result == 0;
    }

    public static bool WindowDisableRendering(IntPtr hWnd)
    {
        int ncrp = (int)DWMNCRENDERINGPOLICY.Disabled;
        // Disable non-client area rendering on the window.
        int result = DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.NCRenderingPolicy, ref ncrp, sizeof(int));
        return result == 0;
    }
}   //DWM

这是Form.BackColor设置为MidnightBlue的示例结果:

Window Selected                              Windows Unselected

上面有一些控件:

相关问题