How to blur behind classic Win32 or WPF window using WinRT Visual Layer on Windows 10?

vb 286 Reputation points
2020-11-05T15:55:32.133+00:00

As you know, DWM Blur behind was turned off starting with Windows 8....
DOC => DwmEnableBlurBehindWindow => "Beginning with Windows 8, calling this function doesn't result in the blur effect, due to a style change in the way windows are rendered."

So, I am trying to blur behind Desktop window using WinRT Visual Layer instead.
But, I’m having problem to blur behind generic Desktop app window (Win32 window or WPF Framework window) using Visual Layer.

I’m testing this capability on un-managed C++ project that uses WinRT Visual Layer composition classes:

1) First, this is part of the pseudo code where I don’t blur, but, this shows idea...

//host window is created by classic… CreateWindowEx

//visual where I will show blurred window back image...
m_backVisual = m_compositor.CreateSpriteVisual();

//Host Backdrop Brush is brush where compositor will fetch window back image...
m_HostBackdropBrush = m_compositor.CreateHostBackdropBrush();

//apply host back drop brush on Visual...
m_backVisual.Brush(m_HostBackdropBrush);

//insert at root ContainerVisual, root composition visual
root->Children().InsertAtBottom(m_backVisual);

Result: What I receive is BLACK sprite visual... where I should, logically, receive fully "transparent" window, aka... image of what is behind window!?

2) Next, I would apply Gaussian blur effect upon this back host brush...so...

I have added Win2D.uwp (& later Microsoft.VCRTForwarders.140) NuGet packages.

Applied:

cppwinrt -in lib\uap10.0\Microsoft.Graphics.Canvas.winmd -ref sdk ... to create Microsoft.Graphics.Canvas.dll & includes…

Microsoft.Graphics.Canvas.dll holds effects library where is GaussianBlurEffect is...(done, dll, .h,. .winmd are in output place...this is like OK)

in the code...I set...

GaussianBlurEffect blurEffect; => FAILS!!! = 0x80040154L => REGDB_E_CLASSNOTREG
blurEeffct.BlurAmount() ...etc

But, on every possible run I just not get past construction of the GaussianBlurEffect struct ... it fails with code: 0x80040154L aka CLASSNOTREG !?

So, what am I missing?
Is this even possible...or should I say...is this possible only in UWP!??!?

Thanks in advance!
Vladimir

Developer technologies | Windows Presentation Foundation
Windows development | Windows API - Win32
0 comments No comments
{count} votes

Accepted answer
  1. vb 286 Reputation points
    2021-06-28T08:03:36.97+00:00

    OK, I finally have breakthrough. I have successfully blurred behind using Visual Layer @ WPF.

    Tweaking sample...

    https://github.com/Microsoft/Windows.UI.Composition-Win32-Samples/tree/master/dotnet/WPF/AcrylicEffect

    This is screenshot of the application before change... (only added "Button" at top & local:CompositionHostControl back painted reddish semitransparent)

    109812-aimg1.png

    ... where you can clearly see blurred region.

    Now tweaks...

    window.xaml.... at <window> element:

    WindowStyle="None" AllowsTransparency="True" Background="#440000BB"  
    

    for to allow window to become transparent, and add some blueish semitransparent background color.

    Comment Lake.jpg image from xaml:

     <!--Image Source="Assets/Lake.jpg"/-->  
    

    for composition to see what is behind blocking image.

    Result is:
    109833-aimg4.png

    Where you can see Visual Studio code in the background.

    You can see blurred Visual Studio code lines. Yeah!

    Conclusion & comments:

    It looks like CreateBackdropBrush is fine, I do not use CreateHostBackdropBrush.

    CompositionHostControl, where we blur, is hwnd host...meaning, we have created child window on top of a standard WPF window, and there composition stuff is done.

    Xaml controls, positioned as top, after CompositionHostControl ( like "Button" control shown at images ), are also blurred. This is problematic in sense that we must put a window with controls as a child of the window where blur is (swap child and parent, or add new WPF UI-window as top child). If this is true, things will get even more complicated if one intents to blur behind WPF tooltip or context menu (WPF popup windows).

    Now, I must test this on NET 5 custom project to see if it really works... does fresh Win2D is working there?


6 additional answers

Sort by: Most helpful
  1. Castorix31 90,686 Reputation points
    2020-11-05T16:36:34.21+00:00

    > Is this even possible...or should I say...is this possible only in UWP!??!?

    A simple way is with SetWindowCompositionAttribute
    (you can find plenty of samples on Google...)

    1 person found this answer helpful.
    0 comments No comments

  2. vb 286 Reputation points
    2020-11-05T16:49:50.137+00:00

    Sorry, but no... :-)

    First... SetWindowCompositionAttribute is UNDOCUMENTED API. It is a hack... Very risky to use in a production!

    Second, when you use SetWindowCompositionAttribute, than forget simple do it window shadow for WPF Framework window. It just apply blur all over. It is very rudimentary "API".

    Third, you can't apply blur attributes...like position of a blur rectangle, Blur-Amount, you can't do color mixing and all possible composition stuff.

    0 comments No comments

  3. Selastin George 1 Reputation point
    2021-06-21T09:16:14.773+00:00

    I was also having same issue with the WinRT Acrylic Effect Just Set WindowCompositionAttribute to ENABLE_BLUR_BEHIND, by doing so the HostBackdropBrush() will work fine.

    typedef enum _WINDOWCOMPOSITIONATTRIB
    {
        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_HOLOGRAPHIC = 23,
        WCA_EXCLUDED_FROM_DDA = 24,
        WCA_PASSIVEUPDATEMODE = 25,
        WCA_LAST = 26
    } WINDOWCOMPOSITIONATTRIB;
    
    typedef struct _WINDOWCOMPOSITIONATTRIBDATA
    {
        WINDOWCOMPOSITIONATTRIB Attrib;
        PVOID pvData;
        SIZE_T cbData;
    } WINDOWCOMPOSITIONATTRIBDATA;
    
    typedef enum _ACCENT_STATE
    {
        ACCENT_DISABLED = 0,
        ACCENT_ENABLE_GRADIENT = 1,
        ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
        ACCENT_ENABLE_BLURBEHIND = 3,
        ACCENT_ENABLE_ACRYLICBLURBEHIND = 4, // RS4 1803
        ACCENT_ENABLE_HOSTBACKDROP = 5, // RS5 1809
        ACCENT_INVALID_STATE = 6
    } ACCENT_STATE;
    
    typedef struct _ACCENT_POLICY
    {
        ACCENT_STATE AccentState;
        DWORD AccentFlags;
        DWORD GradientColor;
        DWORD AnimationId;
    } ACCENT_POLICY;
    
    
    typedef BOOL(WINAPI* SetWindowCompositionAttribute)(
        IN HWND hwnd,
        IN WINDOWCOMPOSITIONATTRIBDATA* pwcad);
    
    SetWindowCompositionAttribute lSetWindowCompositionAttribute;
    
    bool InitPrivateUser32APIs()
    {
        auto user32Lib = LoadLibrary(L"user32.dll");
    
        if (!user32Lib)
            return false;
    
        lSetWindowCompositionAttribute = (SetWindowCompositionAttribute)GetProcAddress(user32Lib, "SetWindowCompositionAttribute");
    
        if (!lSetWindowCompositionAttribute)
            return false;
    
        return true;
    }
    
    
    //Call this part before creating Host Backdrop Brush
    InitPrivateUser32APIs();
    
    if (lSetWindowCompositionAttribute)
        {
            ACCENT_POLICY accent = { ACCENT_ENABLE_BLURBEHIND, 0, 0, 0 };
            WINDOWCOMPOSITIONATTRIBDATA data;
            data.Attrib = WCA_ACCENT_POLICY;
            data.pvData = &accent;
            data.cbData = sizeof(accent);
            lSetWindowCompositionAttribute(window.m_window, &data);
        }
    

  4. Drake Wu - MSFT 996 Reputation points
    2020-11-06T06:59:46.19+00:00

    Hi, @vb Have you tried the code in the following document: Gaussian blur effect?

    You can use this sample to apply Gaussian blur effect to your window.

    In addition, if you want to use custom effects, please refer to this document: Custom effects

    REGDB_E_CLASSNOTREG indicates that your class is not registered, make sure you have installed and registered (via Regsvr32.exe) the COM component.


    If the answer is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.