DWMBlurGlass
DWMBlurGlass copied to clipboard
Borders of certain non-resizable Windows
Since Windows 10, the physical border width on certain non-resizable windows has been intentionally shrunk. See the below image:
Explorer: Resizable, thick borders OldNewExplorer configuration: Non-resizable, thin borders Winver: Non-resizable, ...thick borders?
Not all non-resizable windows have thin borders for whatever reason. ~~From what I can tell, every non-resizable window that is a dialog (e.g. spawned by DialogBoxParamW
) has thick borders,~~ (no, they don't) but there are more which do, so I don't know the exact parameters for it. Anyways, here is the exact same window configuration in Windows 8.1.
As you can see, the borders here are all thick, despite two out of three of these windows being non-resizable.
Something I just noticed: the appearance of all non-resizable borders are the same, no matter the width. Take a look at this:
The Explorer window's borders match the titlebar, but both Winver and OldNewExplorer configuration have a faded color. I can't imagine this has much relevance, but it's still worth pointing out.
So, what do you want to achieve?
So, what do you want to achieve?
That's exactly what I'm wondering 😂 I don't see how this is a bug with DWMBG
So, what do you want to achieve?
Oh, sorry that I wasn't clear with that, haha. I want to achieve the borders Vista-8.1 had in 10 with DWMBG. This program has had other stuff for old themes like that added in the past, so I figured it wouldn't be out of scope for the project.
That's exactly what I'm wondering 😂 I don't see how this is a bug with DWMBG
Not a bug report, feature request. Note the "enhancement" tag.
Check out this WindHawk mod, it works for me: https://windhawk.net/mods/force-thick-frames
@NebelNidas I have tried but the solution you given have some bugs.
The first bug: As for windows with WS_THICKFRAME style, the cursor will become cross (resizing) when hovering the border of these windows, even if these windows are not resizable.
Before using force-thick-frames.
After using force-thick-frames.
Another bug: there are some windows which still have a thin border, even using force-thick-frames.
I also found out such an opinion from https://github.com/Maplespe/DWMBlurGlass/issues/248, and hope it will be useful.
A window can have a thick frame without having WS_THICKFRAME style.
Wait for better solution, and hope DWMBlurGlass can solve this problem.
The Explorer window's borders match the titlebar, but both Winver and OldNewExplorer configuration have a faded color. I can't imagine this has much relevance, but it's still worth pointing out.
I have noticed all apps with ribbon don't use borders the same way like other apps, they use the title bars color, which is also the reason of the missing black border in file explorer and other ribbon apps
Windows 7 calculates the difference between thick border frame and thin border frame in "CTopLevelWindow::CalculateOutsideMargins", then sets a margin using SetMargin function
We can do the same as Windows 7 but it has problems:
- DWMBlurGlass custom blur method doesn't have in mind the margins
- You can click through the borders margin
I did a quick Windhawk mod (only tested on 21H2 LTSC) that i will leave here if someone wants to test, any help for fixing the problems is appreciated
// ==WindhawkMod==
// @id thick-frames
// @name DWM thick frames test
// @version 0.1
// @include dwm.exe
// ==/WindhawkMod==
#include <uxtheme.h>
#include <windhawk_api.h>
#include <windhawk_utils.h>
bool(__thiscall* SetMargin)(struct _MARGINS*, int, int, int, int, struct _MARGINS const*);
bool __thiscall SetMargin_hook(struct _MARGINS* a1, int cxLeftWidth, int cxRightWidth, int cyTopHeight, int cyBottomHeight, struct _MARGINS const* a6) {
return SetMargin(a1, cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight, a6);
}
bool(__thiscall* UpdateMarginsDependentOnStyle)(void*);
bool __thiscall UpdateMarginsDependentOnStyle_hook(void* pThis) {
int ret = UpdateMarginsDependentOnStyle(pThis);
struct tagRECT Rect;
struct _MARGINS a3;
DWORD* windowData;
int dwStyle;
DWORD dwExStyle;
int v8;
LONG v9;
int v10;
int v11;
LONG right;
int v13;
int v14;
LONG v15;
LONG bottom;
windowData = (DWORD*)*((unsigned long long*)pThis + 91);
dwStyle = windowData[25];
dwExStyle = windowData[26];
// CalculateOutsideMargins from Windows 7
Rect.left = 0;
Rect.top = 0;
Rect.right = 0;
Rect.bottom = 0;
AdjustWindowRectEx(&Rect, dwStyle | 0x40000, 0, dwExStyle);
v8 = windowData[16];
v9 = windowData[17];
v10 = -Rect.left;
v11 = -Rect.top;
if (v8 > -Rect.left)
v10 = windowData[16];
a3.cxLeftWidth = v8 - v10;
right = Rect.right;
if (v9 > Rect.right)
right = v9;
v13 = v9 - right;
v14 = windowData[18];
a3.cxRightWidth = v13;
v15 = windowData[19];
if (v14 > v11)
v11 = v14;
a3.cyTopHeight = v14 - v11;
bottom = Rect.bottom;
if (v15 > Rect.bottom)
bottom = v15;
a3.cyBottomHeight = v15 - bottom;
// Check NC size
if (windowData[16] > 0 && windowData[17] > 0 && windowData[18] > 0 && windowData[19] > 0) {
SetMargin((struct _MARGINS*)((char*)pThis + 628), a3.cxLeftWidth,
a3.cxRightWidth, a3.cyTopHeight, a3.cyBottomHeight, 0);
}
return ret;
}
BOOL Wh_ModInit() {
Wh_Log(L"Init");
HMODULE uDWM = LoadLibraryW(L"uDWM.dll");
if (!uDWM) {
Wh_Log(L"Failed to load uDWM.dll");
return FALSE;
}
WindhawkUtils::SYMBOL_HOOK symbolHooks[] = {
{
{L"private: bool __cdecl CTopLevelWindow::UpdateMarginsDependentOnStyle(void)"},
(void**)&UpdateMarginsDependentOnStyle,
(void*)UpdateMarginsDependentOnStyle_hook,
},
{
{L"bool __cdecl SetMargin(struct _MARGINS *,int,int,int,int,struct _MARGINS const *)"},
(void**)&SetMargin,
(void*)SetMargin_hook,
},
};
if (!WindhawkUtils::HookSymbols(uDWM, symbolHooks, ARRAYSIZE(symbolHooks))) {
Wh_Log(L"Error hooking");
return FALSE;
}
return TRUE;
}
Windows 7 calculates the difference between thick border frame and thin border frame in "CTopLevelWindow::CalculateOutsideMargins", then sets a margin using SetMargin function
We can do the same as Windows 7 but it has problems:
1. DWMBlurGlass custom blur method doesn't have in mind the margins 2. You can click through the borders margin
I did a quick Windhawk mod (only tested on 21H2 LTSC) that i will leave here if someone wants to test, any help for fixing the problems is appreciated
// ==WindhawkMod== // @id thick-frames // @name DWM thick frames test // @version 0.1 // @include dwm.exe // ==/WindhawkMod== #include <uxtheme.h> #include <windhawk_api.h> #include <windhawk_utils.h> bool(__thiscall* SetMargin)(struct _MARGINS*, int, int, int, int, struct _MARGINS const*); bool __thiscall SetMargin_hook(struct _MARGINS* a1, int cxLeftWidth, int cxRightWidth, int cyTopHeight, int cyBottomHeight, struct _MARGINS const* a6) { return SetMargin(a1, cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight, a6); } bool(__thiscall* UpdateMarginsDependentOnStyle)(void*); bool __thiscall UpdateMarginsDependentOnStyle_hook(void* pThis) { int ret = UpdateMarginsDependentOnStyle(pThis); struct tagRECT Rect; struct _MARGINS a3; DWORD* windowData; int dwStyle; DWORD dwExStyle; int v8; LONG v9; int v10; int v11; LONG right; int v13; int v14; LONG v15; LONG bottom; windowData = (DWORD*)*((unsigned long long*)pThis + 91); dwStyle = windowData[25]; dwExStyle = windowData[26]; // CalculateOutsideMargins from Windows 7 Rect.left = 0; Rect.top = 0; Rect.right = 0; Rect.bottom = 0; AdjustWindowRectEx(&Rect, dwStyle | 0x40000, 0, dwExStyle); v8 = windowData[16]; v9 = windowData[17]; v10 = -Rect.left; v11 = -Rect.top; if (v8 > -Rect.left) v10 = windowData[16]; a3.cxLeftWidth = v8 - v10; right = Rect.right; if (v9 > Rect.right) right = v9; v13 = v9 - right; v14 = windowData[18]; a3.cxRightWidth = v13; v15 = windowData[19]; if (v14 > v11) v11 = v14; a3.cyTopHeight = v14 - v11; bottom = Rect.bottom; if (v15 > Rect.bottom) bottom = v15; a3.cyBottomHeight = v15 - bottom; // Check NC size if (windowData[16] > 0 && windowData[17] > 0 && windowData[18] > 0 && windowData[19] > 0) { SetMargin((struct _MARGINS*)((char*)pThis + 628), a3.cxLeftWidth, a3.cxRightWidth, a3.cyTopHeight, a3.cyBottomHeight, 0); } return ret; } BOOL Wh_ModInit() { Wh_Log(L"Init"); HMODULE uDWM = LoadLibraryW(L"uDWM.dll"); if (!uDWM) { Wh_Log(L"Failed to load uDWM.dll"); return FALSE; } WindhawkUtils::SYMBOL_HOOK symbolHooks[] = { { {L"private: bool __cdecl CTopLevelWindow::UpdateMarginsDependentOnStyle(void)"}, (void**)&UpdateMarginsDependentOnStyle, (void*)UpdateMarginsDependentOnStyle_hook, }, { {L"bool __cdecl SetMargin(struct _MARGINS *,int,int,int,int,struct _MARGINS const *)"}, (void**)&SetMargin, (void*)SetMargin_hook, }, }; if (!WindhawkUtils::HookSymbols(uDWM, symbolHooks, ARRAYSIZE(symbolHooks))) { Wh_Log(L"Error hooking"); return FALSE; } return TRUE; }
I haven't looked into it exactly, but Windows 10 DWM and UxTheme (XP-7 basic theme window frames) seem to share the same conditions for thin-framed windows. I don't know what these conditions are, but it's true that at least programs running under compatibility mode tend to (always?) use thin frames, even if they're resizable.
@Xdmg01 I'm a beginner on Windhawk, so maybe I misuse your code. I have tested your mod on Windows 10 22H2 but it still don't work.
@Xdmg01 I'm a beginner on Windhawk, so maybe I misuse your code. I have tested your mod on Windows 10 22H2 but it still don't work.
You need to set up Windhawk to allow DWM injection. In the advanced settings, there should be a special placeholder setting "<critical_system_processes>" in the process exclusion list. You must remove this and ensure that the setting "Load mods into critical system processes" (doesn't even seem to be translated into Japanese lol) is set to an option to allow it. Then it should be able to inject into DWM.
By the way, if a DWM mod is incompatible, you can brick your system and need to use another OS or boot into a Windows installer to fix it. Remove the compiled mod DLL at C:\ProgramData\Windhawk\Engine\Mods\64
and you should be alright.
I should mention the cases of this occurring:
This behaviour has been present since Windows Vista. However, back then, it was limited to the basic theme (UxTheme), with Aero extending the frames beyond their "real" size to compensate. As of Windows 10, DWM also does this.
This occurs in any application that is not built with a subsystem version of at least 6.00. These applications are just not allowed to access the border padding metrics at all, including UxTheme itself, which is responsible for drawing window frames. Basically, any program that supports XP gets these as a compatibility hack.
See also: https://web.archive.org/web/20110910065719/http://objectmix.com/clipper/749482-getsystemmetrics-sm_cxpaddedborder.html
I should mention the cases of this occurring:
This behaviour has been present since Windows Vista. However, back then, it was limited to the basic theme (UxTheme), with Aero extending the frames beyond their "real" size to compensate. As of Windows 10, DWM also does this.
This occurs in any application that is not built with a subsystem version of at least 6.00. These applications are just not allowed to access the border padding metrics at all, including UxTheme itself, which is responsible for drawing window frames. Basically, any program that supports XP gets these as a compatibility hack.
See also: https://web.archive.org/web/20110910065719/http://objectmix.com/clipper/749482-getsystemmetrics-sm_cxpaddedborder.html
Also, seemingly any application run in compatibility mode gets thin borders on every window, including resizable ones. However, using the Application Verifier utility's HighVersionLie removes that effect and makes borders act as if compatibility mode was not enabled.
Oh, also, dialogness, like I mentioned in the OP, is not relevant at all. I was mistaken.
I should mention the cases of this occurring: This behaviour has been present since Windows Vista. However, back then, it was limited to the basic theme (UxTheme), with Aero extending the frames beyond their "real" size to compensate. As of Windows 10, DWM also does this. This occurs in any application that is not built with a subsystem version of at least 6.00. These applications are just not allowed to access the border padding metrics at all, including UxTheme itself, which is responsible for drawing window frames. Basically, any program that supports XP gets these as a compatibility hack. See also: https://web.archive.org/web/20110910065719/http://objectmix.com/clipper/749482-getsystemmetrics-sm_cxpaddedborder.html
Also, seemingly any application run in compatibility mode gets thin borders on every window, including resizable ones. However, using the Application Verifier utility's HighVersionLie removes that effect and makes borders act as if compatibility mode was not enabled.
The resizable "thin borders" when using compatibility mode aren't the same as non resizable thin borders, they are 1px wider Also this happens with basic frames so Dwm has probably nothing to do with it
I should mention the cases of this occurring: This behaviour has been present since Windows Vista. However, back then, it was limited to the basic theme (UxTheme), with Aero extending the frames beyond their "real" size to compensate. As of Windows 10, DWM also does this. This occurs in any application that is not built with a subsystem version of at least 6.00. These applications are just not allowed to access the border padding metrics at all, including UxTheme itself, which is responsible for drawing window frames. Basically, any program that supports XP gets these as a compatibility hack. See also: https://web.archive.org/web/20110910065719/http://objectmix.com/clipper/749482-getsystemmetrics-sm_cxpaddedborder.html
Also, seemingly any application run in compatibility mode gets thin borders on every window, including resizable ones. However, using the Application Verifier utility's HighVersionLie removes that effect and makes borders act as if compatibility mode was not enabled.
The resizable "thin borders" when using compatibility mode aren't the same as non resizable thin borders, they are 1px wider Also this happens with basic frames so Dwm has probably nothing to do with it
DWM has everything to do with it. This has always happened on basic frames, just that Windows Vista/7/8.x DWM ignored the border size and always used thick frames. There is even an API specifically to get the DWM window's rect including the fake DWM border. (DwmGetWindowAttribute
with DWMWA_EXTENDED_FRAME_BOUNDS
attribute)
I also noticed that with the modcode above, extended frame dialog windows do not blink (i.e. flicker between active and inactive titlebar colors) when clicked outside the active area, instead staying on the same active titlebar style. This bug does not affect the other dialogs whose margins were not changed.
Is there any way to achieve this without windhawk and compatbility mode? The thin borders look ugly and bug me.
Windows 7 calculates the difference between thick border frame and thin border frame in "CTopLevelWindow::CalculateOutsideMargins", then sets a margin using SetMargin function
We can do the same as Windows 7 but it has problems:
1. DWMBlurGlass custom blur method doesn't have in mind the margins 2. You can click through the borders margin
I did a quick Windhawk mod (only tested on 21H2 LTSC) that i will leave here if someone wants to test, any help for fixing the problems is appreciated
// ==WindhawkMod== // @id thick-frames // @name DWM thick frames test // @version 0.1 // @include dwm.exe // ==/WindhawkMod== #include <uxtheme.h> #include <windhawk_api.h> #include <windhawk_utils.h> bool(__thiscall* SetMargin)(struct _MARGINS*, int, int, int, int, struct _MARGINS const*); bool __thiscall SetMargin_hook(struct _MARGINS* a1, int cxLeftWidth, int cxRightWidth, int cyTopHeight, int cyBottomHeight, struct _MARGINS const* a6) { return SetMargin(a1, cxLeftWidth, cxRightWidth, cyTopHeight, cyBottomHeight, a6); } bool(__thiscall* UpdateMarginsDependentOnStyle)(void*); bool __thiscall UpdateMarginsDependentOnStyle_hook(void* pThis) { int ret = UpdateMarginsDependentOnStyle(pThis); struct tagRECT Rect; struct _MARGINS a3; DWORD* windowData; int dwStyle; DWORD dwExStyle; int v8; LONG v9; int v10; int v11; LONG right; int v13; int v14; LONG v15; LONG bottom; windowData = (DWORD*)*((unsigned long long*)pThis + 91); dwStyle = windowData[25]; dwExStyle = windowData[26]; // CalculateOutsideMargins from Windows 7 Rect.left = 0; Rect.top = 0; Rect.right = 0; Rect.bottom = 0; AdjustWindowRectEx(&Rect, dwStyle | 0x40000, 0, dwExStyle); v8 = windowData[16]; v9 = windowData[17]; v10 = -Rect.left; v11 = -Rect.top; if (v8 > -Rect.left) v10 = windowData[16]; a3.cxLeftWidth = v8 - v10; right = Rect.right; if (v9 > Rect.right) right = v9; v13 = v9 - right; v14 = windowData[18]; a3.cxRightWidth = v13; v15 = windowData[19]; if (v14 > v11) v11 = v14; a3.cyTopHeight = v14 - v11; bottom = Rect.bottom; if (v15 > Rect.bottom) bottom = v15; a3.cyBottomHeight = v15 - bottom; // Check NC size if (windowData[16] > 0 && windowData[17] > 0 && windowData[18] > 0 && windowData[19] > 0) { SetMargin((struct _MARGINS*)((char*)pThis + 628), a3.cxLeftWidth, a3.cxRightWidth, a3.cyTopHeight, a3.cyBottomHeight, 0); } return ret; } BOOL Wh_ModInit() { Wh_Log(L"Init"); HMODULE uDWM = LoadLibraryW(L"uDWM.dll"); if (!uDWM) { Wh_Log(L"Failed to load uDWM.dll"); return FALSE; } WindhawkUtils::SYMBOL_HOOK symbolHooks[] = { { {L"private: bool __cdecl CTopLevelWindow::UpdateMarginsDependentOnStyle(void)"}, (void**)&UpdateMarginsDependentOnStyle, (void*)UpdateMarginsDependentOnStyle_hook, }, { {L"bool __cdecl SetMargin(struct _MARGINS *,int,int,int,int,struct _MARGINS const *)"}, (void**)&SetMargin, (void*)SetMargin_hook, }, }; if (!WindhawkUtils::HookSymbols(uDWM, symbolHooks, ARRAYSIZE(symbolHooks))) { Wh_Log(L"Error hooking"); return FALSE; } return TRUE; }
these broken borders also seem to be the same ones that other thick frame mods don't affect to begin with
try this borders have blur and windows arent resizable not made by me https://raw.githubusercontent.com/ramensoftware/windhawk-mods/2f162c3f58d4ef04f6d69ec7865f0c2db2f33ba1/mods/force-thick-frames-plus.wh.cpp
try this borders have blur and windows arent resizable not made by me https://raw.githubusercontent.com/ramensoftware/windhawk-mods/2f162c3f58d4ef04f6d69ec7865f0c2db2f33ba1/mods/force-thick-frames-plus.wh.cpp
this just tries to force an attribute onto a window, which comes with a number of issues