Skip to content

Commit ecac8c5

Browse files
committed
Fix flickering when redrawing menu borders
We no longer need to wait until it is possible to redraw borders This option is now enabled by default Thanks to TranslucentFlyouts project
1 parent 3fb8790 commit ecac8c5

3 files changed

Lines changed: 63 additions & 75 deletions

File tree

AcrylicMenus/MenuHandler.cpp

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,6 @@ void CALLBACK MenuHandler::WinEventProc(
6969
DwmSetWindowAttribute(hWnd, DWMWA_BORDER_COLOR, &dwColorBorder, sizeof(COLORREF));
7070
}
7171
}
72-
else if (MENU_REDRAW_BORDER && (!MenuManager::g_bIsDarkMode || SettingsHelper::g_redrawDarkThemeBorders10))
73-
{
74-
// We can't draw on non-client area right after window has showed
75-
WindowHelper::SendMessageDelayed(hWnd, WM_REDRAWBORDER, 160);
76-
}
7772
}
7873
break;
7974
}
@@ -93,6 +88,8 @@ void CALLBACK MenuHandler::WinEventProc(
9388
}
9489
}
9590

91+
static constexpr int nonClientMarginSize{ 3 };
92+
static constexpr int systemOutlineSize{ 1 };
9693
LRESULT CALLBACK MenuHandler::SubclassProc(
9794
HWND hWnd,
9895
UINT uMsg,
@@ -102,13 +99,66 @@ LRESULT CALLBACK MenuHandler::SubclassProc(
10299
DWORD_PTR dwRefData
103100
)
104101
{
102+
bool handled = false;
103+
LRESULT result{ 0 };
104+
105105
switch (uMsg)
106106
{
107-
case WM_REDRAWBORDER:
107+
#if (MENU_REDRAW_BORDER == TRUE)
108+
///
109+
/// Windows 10 has ugly white context menu borders
110+
/// As the borders are in the non-client area,
111+
/// we can't hook the painting event and need
112+
/// to redraw them manually
113+
///
114+
/// This is enabled only for light mode menus,
115+
/// because it is noticeable, due to low contrast
116+
/// between menu background color and original white border,
117+
/// but this is very noticeable in dark mode
118+
///
119+
/// On Windows 11, we change borders color
120+
/// natively using DwmSetWindowAttribute API
121+
///
122+
case WM_PRINT:
123+
{
124+
handled = true;
125+
126+
POINT pt;
127+
128+
HDC wndDC = (HDC)wParam;
129+
SaveDC(wndDC);
130+
131+
RECT rcPaint;
132+
GetClipBox(wndDC, &rcPaint);
133+
FillRect(wndDC, &rcPaint, GetStockBrush(BLACK_BRUSH));
134+
135+
SetViewportOrgEx(wndDC, nonClientMarginSize, nonClientMarginSize, &pt);
136+
result = DefSubclassProc(hWnd, WM_PRINTCLIENT, wParam, lParam);
137+
138+
SetViewportOrgEx(wndDC, pt.x, pt.y, nullptr);
139+
140+
RestoreDC(wndDC, -1);
141+
}
142+
break;
143+
case WM_NCPAINT:
108144
{
109-
WindowHelper::RedrawMenuBorder(hWnd);
145+
handled = true;
146+
147+
HDC wndDC = GetWindowDC(hWnd);
148+
149+
if (wParam != NULLREGION && wParam != ERROR)
150+
{
151+
SelectClipRgn(wndDC, reinterpret_cast<HRGN>(wParam));
152+
}
153+
154+
RECT rcPaint;
155+
GetClipBox(wndDC, &rcPaint);
156+
FillRect(wndDC, &rcPaint, GetStockBrush(BLACK_BRUSH));
157+
158+
ReleaseDC(hWnd, wndDC);
110159
}
111160
break;
161+
#endif
112162
case MN_BUTTONUP:
113163
{
114164
// We need to prevent the system default menu fade out animation
@@ -163,5 +213,10 @@ LRESULT CALLBACK MenuHandler::SubclassProc(
163213
break;
164214
}
165215

166-
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
216+
if (!handled)
217+
{
218+
result = DefSubclassProc(hWnd, uMsg, wParam, lParam);
219+
}
220+
221+
return result;
167222
}

AcrylicMenus/WindowHelper.h

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,6 @@ namespace AcrylicMenus
77
{
88
namespace WindowHelper
99
{
10-
///
11-
/// Windows 10 has ugly white context menu borders
12-
/// As the borders are in the non-client area,
13-
/// we can't hook the painting event and need
14-
/// to redraw them manually
15-
///
16-
/// This is enabled only for light mode menus,
17-
/// because it is noticeable, due to low contrast
18-
/// between menu background color and original white border,
19-
/// but this is very noticeable in dark mode
20-
///
21-
/// On Windows 11, we change borders color
22-
/// natively using DwmSetWindowAttribute API
23-
///
24-
25-
void RedrawMenuBorder(HWND hWnd)
26-
{
27-
RECT wndRect;
28-
GetWindowRect(hWnd, &wndRect);
29-
OffsetRect(&wndRect, -wndRect.left, -wndRect.top);
30-
31-
HDC wndDC = GetWindowDC(hWnd);
32-
33-
ExcludeClipRect(wndDC,
34-
wndRect.left + 1,
35-
wndRect.top + 1,
36-
wndRect.right - 1,
37-
wndRect.bottom - 1
38-
);
39-
40-
FillRect(wndDC, &wndRect, (HBRUSH)GetStockObject(BLACK_BRUSH));
41-
}
42-
4310
///
4411
/// After user selects option, if menu fade out animation
4512
/// is enabled in system settings, system will draw
@@ -146,37 +113,5 @@ namespace WindowHelper
146113
}
147114

148115
#pragma endregion
149-
150-
#pragma region Delayed Message
151-
152-
struct DELAYEDMESSAGEINFO
153-
{
154-
HWND hWnd;
155-
UINT uMsg;
156-
DWORD dwDelayMilliseconds;
157-
};
158-
DWORD WINAPI SendMessageDelayedThreadProc(LPVOID lpParameter)
159-
{
160-
DELAYEDMESSAGEINFO* info = (DELAYEDMESSAGEINFO*)lpParameter;
161-
if (info->dwDelayMilliseconds)
162-
{
163-
Sleep(info->dwDelayMilliseconds);
164-
}
165-
SendMessage(info->hWnd, info->uMsg, 0, 0);
166-
delete info;
167-
return 0;
168-
}
169-
void SendMessageDelayed(HWND hWnd, UINT uMsg, DWORD dwDelayMilliseconds)
170-
{
171-
DELAYEDMESSAGEINFO* info = new DELAYEDMESSAGEINFO;
172-
info->hWnd = hWnd;
173-
info->uMsg = uMsg;
174-
info->dwDelayMilliseconds = dwDelayMilliseconds;
175-
176-
HANDLE hThread = CreateThread(NULL, 0, &SendMessageDelayedThreadProc, info, 0, NULL);
177-
if (hThread) CloseHandle(hThread);
178-
}
179-
180-
#pragma endregion
181116
}
182117
}

AcrylicMenus/dllmain.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ using namespace AcrylicMenus;
77

88
HMODULE g_hModule = nullptr;
99
bool SystemHelper::g_bIsWindows11 = false;
10-
bool SettingsHelper::g_redrawDarkThemeBorders10 = false;
1110

1211
BOOL APIENTRY DllMain(
1312
HMODULE hModule,
@@ -22,7 +21,6 @@ BOOL APIENTRY DllMain(
2221
g_hModule = hModule;
2322
DisableThreadLibraryCalls(hModule);
2423
SystemHelper::g_bIsWindows11 = SystemHelper::DetectOSBuildNumber() >= 22000;
25-
SettingsHelper::g_redrawDarkThemeBorders10 = SettingsHelper::IsFeatureEnabled(L"RedrawDarkThemeBorders");
2624
AcrylicMenus::Startup();
2725
break;
2826
}

0 commit comments

Comments
 (0)