I encountered the same problem, and after spending over 6 hours on this, I'm so proud to say that I have a solution! Anyway, there's also an limitation, I'll mention it later.
well, in breif, this is it:
visualEffect.h:
#include <dwmapi.h> // note that you may have to use msvc for this
// More friendly names
enum EffectType : int {
EffectType_Default = DWMSBT_AUTO,
EffectType_None = DWMSBT_NONE,
EffectType_Mica = DWMSBT_MAINWINDOW,
EffectType_Acrylic = DWMSBT_TRANSIENTWINDOW,
EffectType_MicaAlt = DWMSBT_TABBEDWINDOW
};
enum CornerPreference : int {
Corner_Default = DWMWCP_DEFAULT,
Corner_NoRound = DWMWCP_DONOTROUND,
Corner_Round = DWMWCP_ROUND,
Corner_RoundSmall = DWMWCP_ROUNDSMALL
};
bool SetAcrylicEffect(HWND hwnd, EffectType type = EffectType_Mica, CornerPreference corner = Corner_Round);
visualEffect.cpp
#include "visualEffect.h"
bool SetAcrylicEffect(HWND hwnd, EffectType type, CornerPreference corner)
{
if(!hwnd) return false;
HRESULT hr1, hr2;
DWM_SYSTEMBACKDROP_TYPE backdrop = static_cast<DWM_SYSTEMBACKDROP_TYPE>(type);
hr1 = DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, &backdrop, sizeof(backdrop));
// set rounded corner preference
if(corner != Corner_Default) {
// when it's not default
DWM_WINDOW_CORNER_PREFERENCE cp = static_cast<DWM_WINDOW_CORNER_PREFERENCE>(corner);
hr2 = DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cp, sizeof(cp));
}
else {
hr2 = S_OK; // regard as success
}
return SUCCEEDED(hr1) && SUCCEEDED(hr2);
}
You need to link dwmapi like this in your CMakeLists.txt:
target_link_libraries(YourApplication PRIVATE dwmapi)
Some important things you need to know:
Corner_Round is fixed 8px radius, and Corner_RoundSmall is fixed 4px. You can not change this, because this is builtin for dwm. There values are usually good enough, so if you really want it you should just set your window to 8px radius.
after using setAttribute(Qt::WA_Translucentbackground), the transparent part for your window is not regarded as the window region, so it acts like non-client area. And if you use the stylesheet or paintEvent on your centralwidget or something, the effect looks broken.
So the best approach on Qt, is set another overlay widget at the bottom, and put everything else on top of it.
The overlay widget should have something like this:
#overlay {
background: rgba(255, 255, 255, 2); /*1 makes it not transparent at all, and 0 does not work*/
}
and this:
// something here
{
ui->setupUi(this);
setAttribute(Qt::WA_TranslucentBackground);
if(!SetAcrylicEffect((HWND)this->winId(), EffectType_Acrylic, Corner_Round)) {
qWarning() << "Failed to launch Acrylic Effect, fallback to default transparency" << GetLastError();
}
}
also this:
[image: a598cfd7-66a8-4c06-9aaf-15a8b7578bf5.png]
And you're done!
You can find the full version on my github, but the above one should be completely usable already.