I want to blur a window, and I have used DwmEnableBlurBehindWindow()
, DwmExtendFrameIntoClientArea()
and DwmSetWindowAttribute()
(to enable the client area rendering). However, it fails to blur, and instead makes the client area white.
Minimum reproducible code:
#include <dwmapi.h>
#include <gdiplus.h>
#include <stdio.h>
#include <windows.h>
HWND hwnd;
HRESULT enableNCRendering(HWND hWnd)
{
enum DWMNCRENDERINGPOLICY ncrp = DWMNCRP_ENABLED;
HRESULT hr = DwmSetWindowAttribute(hWnd,
DWMWA_NCRENDERING_POLICY,
&ncrp,
sizeof(ncrp));
if (!SUCCEEDED(hr))
printf("Failed 0\n");
return hr;
}
HRESULT EnableBlurBehind(HWND hwnd)
{
DWM_BLURBEHIND bb = {0};
bb.dwFlags = DWM_BB_ENABLE;
bb.fEnable = true;
bb.hRgnBlur = NULL;
HRESULT hr = DwmEnableBlurBehindWindow(hwnd, &bb);
if (!SUCCEEDED(hr))
printf("Failed 1\n");
return hr;
}
HRESULT ExtendIntoClientAll(HWND hwnd)
{
MARGINS margins = {-1};
HRESULT hr = DwmExtendFrameIntoClientArea(hwnd, &margins);
if (!SUCCEEDED(hr))
printf("Failed 2\n");
return hr;
}
ATOM MyRegisterClass(HINSTANCE hInst, LPCWSTR name, UINT styles, COLORREF bkg_colour, WNDPROC proc)
{
WNDCLASSEXW wc;
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = styles;
wc.lpfnWndProc = proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIconW(hInst, (LPCWSTR)IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(bkg_colour); // CreateSolidBrush(RGB(255, 0, 0))
wc.lpszMenuName = NULL;
wc.hIconSm = LoadIconW(hInst, (LPCWSTR)IDI_APPLICATION);
wc.lpszClassName = (LPCWSTR)name;
return RegisterClassExW(&wc);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_NCHITTEST:
return HTCAPTION;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
MyRegisterClass(hInstance, L"Main", CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, RGB(255, 0, 0), WndProc);
hwnd = CreateWindowExW(WS_EX_LAYERED, L"Main", L"main", WS_POPUP, 0, 0, 1000, 500, NULL, NULL, hInstance, NULL);
if (!hwnd)
return 1;
SetLayeredWindowAttributes(hwnd, 0, 100, LWA_ALPHA);
enableNCRendering(hwnd);
EnableBlurBehind(hwnd);
ExtendIntoClientAll(hwnd);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
I have also tried SetWindowCompositionAttributes()
but it was undefined in Mingw, and I wasn't able to find much information on using that. It also doesn't give the desired effect and gives barely any blur:
#include <Winerror.h>
#include <dwmapi.h>
#include <gdiplus.h>
#include <stdio.h>
#include <windows.h>
HWND hwnd;
struct ACCENTPOLICY
{
int na;
int nf;
int nc;
int nA;
};
struct WINCOMPATTRDATA
{
int na;
PVOID pd;
ULONG ul;
};
typedef BOOL(WINAPI* pSetWindowCompositionAttribute)(HWND, WINCOMPATTRDATA*);
void makeBlur()
{
const HINSTANCE hm = LoadLibraryW(L"user32.dll");
if (hm)
{
const pSetWindowCompositionAttribute SetWindowCompositionAttribute = (pSetWindowCompositionAttribute)GetProcAddress(hm, "SetWindowCompositionAttribute");
if (SetWindowCompositionAttribute)
{
struct ACCENTPOLICY policy = {3, 0, 0, 0};
struct WINCOMPATTRDATA data = {19, &policy, sizeof(ACCENTPOLICY)};
SetWindowCompositionAttribute(hwnd, &data);
}
FreeLibrary(hm);
}
}
ATOM MyRegisterClass(HINSTANCE hInst, LPCWSTR name, UINT styles, COLORREF bkg_colour, WNDPROC proc)
{
WNDCLASSEXW wc;
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = styles;
wc.lpfnWndProc = proc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIconW(hInst, (LPCWSTR)IDI_APPLICATION);
wc.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW);
wc.hbrBackground = (HBRUSH)CreateSolidBrush(bkg_colour); // CreateSolidBrush(RGB(255, 0, 0))
wc.lpszMenuName = NULL;
wc.hIconSm = LoadIconW(hInst, (LPCWSTR)IDI_APPLICATION);
wc.lpszClassName = (LPCWSTR)name;
return RegisterClassExW(&wc);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch (msg)
{
case WM_NCHITTEST:
return HTCAPTION;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProcW(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
//getting accent colors
DWORD color = 0;
BOOL opaque = FALSE;
DwmGetColorizationColor(&color, &opaque);
BYTE blue = color;
color = color >> 8;
BYTE green = color;
color = color >> 8;
BYTE red = color;
color = color >> 8;
BYTE alpha = color;
MyRegisterClass(hInstance, L"Main", CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS, RGB(red, green, blue), WndProc);
hwnd = CreateWindowExW(WS_EX_LAYERED, L"Main", L"main", WS_POPUP, 0, 0, 1000, 500, NULL, NULL, hInstance, NULL);
if (!hwnd)
return 1;
SetLayeredWindowAttributes(hwnd, 0, 100, LWA_ALPHA);
makeBlur();
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessageW(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return msg.wParam;
}
How can I make my window blur?