0

I know this question have been answered with several ways but I am making this separate question in order to avoid potential queue of comments under initial question and its answers with which I am facing an "issue"(?).


What I am trying to achieve (in my case) is to apply what is called the Windows Blur Effect to a borderless WinForm.

I found this answer by György Kőszeg to a similar question and I adapted his code to my project like this:

First I made this BlurEffect class:

internal class BlurEffect
{
    internal enum AccentState
    {
        ACCENT_DISABLED = 0,
        ACCENT_ENABLE_GRADIENT = 1,
        ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
        ACCENT_ENABLE_BLURBEHIND = 3,
        ACCENT_INVALID_STATE = 4
    }

    internal enum WindowCompositionAttribute
    {
        WCA_ACCENT_POLICY = 19
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct AccentPolicy
    {
        public AccentState AccentState;
        public int AccentFlags;
        public int GradientColor;
        public int AnimationId;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct WindowCompositionAttributeData
    {
        public WindowCompositionAttribute Attribute;
        public IntPtr Data;
        public int SizeOfData;
    }

    internal static class User32
    {
        [DllImport("user32.dll")]
        internal static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref WindowCompositionAttributeData data);
    }

    internal static void Apply(Form form, bool enable)
    {
        var accent = new AccentPolicy { AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND };
        if (!enable)
            accent = new AccentPolicy { AccentState = AccentState.ACCENT_DISABLED };
        var accentStructSize = Marshal.SizeOf(accent);
        var accentPtr = Marshal.AllocHGlobal(accentStructSize);

        Marshal.StructureToPtr(accent, accentPtr, false);

        var data = new WindowCompositionAttributeData
        {
            Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
            SizeOfData = accentStructSize,
            Data = accentPtr
        };

        User32.SetWindowCompositionAttribute(form.Handle, ref data);
        Marshal.FreeHGlobal(accentPtr);
    }
}

And then, into my test Form, I added a property and a button so to enable or disable the Blur Effect:

public partial class MyForm : Form
{
    private bool blur_effect = false;
    [Category("• MyForm")]
    [DisplayName("• BlurEffect")]
    [Description("Enables or disables the [Blur] effect.")]
    public bool BlurEffect
    {
        get => this.blur_effect;
        set
        {
            this.blur_effect = value;
            BlurEffect.Apply(this, value);
            base.Invalidate();
        }
    }

    public MyForm()
    {
        InitializeComponent();
    }

    private void BlurEffect_Button_Click(object sender, EventArgs e)
    {
        this.BlurEffect = !this.BlurEffect;
    }
}

As you can see on the image below, it "worked" but I had this "issue"(?). Along with the form, the Βlur Effect is applied to the controls as well. Is that normal? Is there something I can do so the Blur Effect applies on the form only?

Note: Form's shadow comes from another class!!!

enter image description here

Simos Sigma
  • 958
  • 7
  • 29
  • As [mentioned elsewhere](https://stackoverflow.com/a/51580871/7444103), the *effect* you can achieve with blur-behind in this Platform is not state-of-the-art. The drop-shadow of a border-less Form is also not perfect, because of the transparent / invisible borders applied to a Window (a drop shadow of 2 pixels is however *tolerable*) -- A simple patch is a *sandwich* of two Forms, overlaying your blurred Form to a border-less one which has its Opacity set to, e.g. 35~50 % and move it as your Form moves. Then child Controls are not translucent anymore. Must be positioned perfectly... – Jimi Jan 07 '23 at 15:35
  • ... considering the transparent borders (or the drop-shadow borders you have specified), otherwise you'll see sort of a phantom of the external sides of the border-less Form behind your blurred Form – Jimi Jan 07 '23 at 15:40
  • 2
    This is a normal "issue" when you use Winforms controls. Text rendering in Winforms is done by GDI, fundamentally a 24bpp api. You need a 32bpp api to avoid this artifact, DirectWrite is the usual choice. Problem is, once you fixed all the controls to use it, you'd have basically reinvented Winforms. WPF uses a 32bpp api, best way to get ahead. – Hans Passant Jan 07 '23 at 15:50

0 Answers0