Menu appearance fixes for wxMSW (PR #26182)

107 views
Skip to first unread message

VZ

unread,
Feb 11, 2026, 3:37:12 PMFeb 11
to wx-...@googlegroups.com, Subscribed

Replaces #26053.


You can view, comment on, or merge this pull request online at:

  https://github.com/wxWidgets/wxWidgets/pull/26182

Commit Summary

  • 3cf8cc0 Fix appearance of owner drawn menus in dark mode
  • 45ab79f Fix rounded menu corners appearance under Windows 11

File Changes

(9 files)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182@github.com>

VZ

unread,
Feb 11, 2026, 4:09:59 PMFeb 11
to wx-...@googlegroups.com, Push

@vadz pushed 1 commit.

  • 83903ac Fix rounded menu corners appearance under Windows 11


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/before/45ab79f189ff0340774ca97327d3bb795a0c400d/after/83903accaf465b07babbb9378d4a08384d010bc4@github.com>

PB

unread,
Feb 11, 2026, 4:29:53 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@PBfordev commented on this pull request.


In src/msw/darkmode.cpp:

> +    if ( win )
+    {
+        wxUxThemeHandle hTheme
+            (
+                win,
+                L"LightMode_ImmersiveStart::Menu;MENU",
+                L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
+            );
+        colBorder = hTheme.GetColour(MENU_POPUPBORDERS, TMT_FILLCOLORHINT);
+    }
+
+    if ( !colBorder.IsOk() )
+        colBorder = wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER);
+
+    DWORD color = static_cast<DWORD>(wxColourToRGB(colBorder));
+    dwmSetWinAttr(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));

IIRC, it was this line to which I referred in the original PR, making the menus to have very light borders, as shown in the screenshots there.

IME, such borders are not common for dark menus on MSW.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787574250@github.com>

PB

unread,
Feb 11, 2026, 4:33:25 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@PBfordev commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

Should not code like this have a comment, but perhaps this magic is too dark... TBH, I don't even know what UAH menu means here...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787587376@github.com>

VZ

unread,
Feb 11, 2026, 4:35:17 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +    if ( win )
+    {
+        wxUxThemeHandle hTheme
+            (
+                win,
+                L"LightMode_ImmersiveStart::Menu;MENU",
+                L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
+            );
+        colBorder = hTheme.GetColour(MENU_POPUPBORDERS, TMT_FILLCOLORHINT);
+    }
+
+    if ( !colBorder.IsOk() )
+        colBorder = wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER);
+
+    DWORD color = static_cast<DWORD>(wxColourToRGB(colBorder));
+    dwmSetWinAttr(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));

What colour do they use for border under Windows 11?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787593720@github.com>

VZ

unread,
Feb 11, 2026, 4:37:05 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

Unfortunately I have no idea what does this mean either so I can't write a meaningful comment for it. @memoarfaa If you have any suggestions, they would be very welcome.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787601842@github.com>

PB

unread,
Feb 11, 2026, 4:56:30 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@PBfordev commented on this pull request.


In src/msw/darkmode.cpp:

> +    if ( win )
+    {
+        wxUxThemeHandle hTheme
+            (
+                win,
+                L"LightMode_ImmersiveStart::Menu;MENU",
+                L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
+            );
+        colBorder = hTheme.GetColour(MENU_POPUPBORDERS, TMT_FILLCOLORHINT);
+    }
+
+    if ( !colBorder.IsOk() )
+        colBorder = wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER);
+
+    DWORD color = static_cast<DWORD>(wxColourToRGB(colBorder));
+    dwmSetWinAttr(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));

Well, what is the reference? Here are few examples from applications shipped with Windows.

Explorer
darkmenu-explorer.png (view on web)

Edge
darkmenu-edge.png (view on web)

Notepad
darkmenu-notepad.png (view on web)

Microsoft 365 uses light border, but its menu are different from the rest, e.g., the width of the divider:
darkmenu-office.png (view on web)

FWIW, the only Win32 application with dark mode support I use is Notepad++ which does not have a light border and nor does have it MSVS 2026.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787677799@github.com>

VZ

unread,
Feb 11, 2026, 5:39:43 PMFeb 11
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

Ugh, I've tried testing myself under Windows 11 (it's a pretty old version, 10.0.22621.3155) and it looks like dark mode is totally broken there, this is how menu sample looks for me with master (it's almost the same with this PR):

image.png (view on web)

@PBfordev Do you not see this? It still works fine under Windows 10 (10.0.19044.3803) for me:

image.png (view on web)

but something is very wrong under 11...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3887623692@github.com>

Maarten

unread,
Feb 11, 2026, 7:02:48 PMFeb 11
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.


In include/wx/msw/private/menu.h:

> @@ -15,6 +15,7 @@ namespace wxMSWMenuImpl
 
 // Definitions for undocumented messages and structs used in this code.
 constexpr int WM_MENUBAR_DRAWMENU = 0x91;
+constexpr int WM_MENUBAR_INITMENU = 0x93;

93 after 92


In src/msw/darkmode.cpp:

> @@ -788,3 +811,51 @@ HandleMenuMessage(WXLRESULT* WXUNUSED(result),
 } // namespace wxMSWDarkMode
 
 #endif // wxUSE_DARK_MODE/!wxUSE_DARK_MODE
+
+void wxMSWImpl::EnableRoundCorners(HWND hwnd)
+{
+    const auto dwmSetWinAttr = wxDarkModeModule::GetDwmSetWindowAttribute();
+    if ( !dwmSetWinAttr )
+        return;
+
+    constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+    constexpr DWORD DWMWA_BORDER_COLOR = 34;
+    constexpr int WindowCornerPreference = 3; // DWMWCP_ROUNDSMALL
+
+    // Apply rounded corners
+    HRESULT hr = dwmSetWinAttr(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE,

On Windows 10, every time I open a menu the debugger logs the following:

clientcore\windows\dwm\dwmapi\attribute.cpp(185)\dwmapi.dll!00007FFFA9F62C57: (caller: 00007FFEDA0A29C1) ReturnHr(29) tid(2ef8) 80070057 The parameter is incorrect.

I don't think it supports rounded corners. Maybe limit it to Windows 11 only? Like it is already done in HandleEnterIdle.


In src/msw/darkmode.cpp:

> +
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;
+
+    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;

You can pass a wxWindow to this function, instead of getting the main app window.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.

them -> theme


In src/msw/darkmode.cpp:

> +    constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+    constexpr DWORD DWMWA_BORDER_COLOR = 34;

To be safe, maybe these should get a WX prefix. So they won't clash with the enum values from dwmapi.h.


In src/msw/darkmode.cpp:

> +                               &WindowCornerPreference,
+                               sizeof(WindowCornerPreference));
+
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;

wxColour


In src/msw/menu.cpp:

> @@ -938,6 +947,31 @@ WXHMENU wxMenuBar::Create()
                 wxLogLastError(wxT("AppendMenu"));
             }
         }
+
+#if wxUSE_OWNER_DRAWN
+        // Set menu background color
+        wxUxThemeHandle hTheme
+            (
+                GetFrame()->AsWindow(),
+                L"LightMode_ImmersiveStart::Menu;Menu",
+                L"DarkMode_ImmersiveStart::Menu;Menu"
+            );
+        wxColor colMenu = hTheme.GetColour(MENU_POPUPBACKGROUND, TMT_FILLCOLOR);

wxColour


In src/msw/menuitem.cpp:

> @@ -1261,7 +1340,18 @@ void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& co
         {
             colText = GetTextColour();
             if ( !colText.IsOk() )
-                wxRGBToColour(colText, ::GetThemeSysColor(hTheme, COLOR_MENUTEXT));
+            {
+                if ( wxMSWDarkMode::IsActive() )
+                {
+                    colText = hTheme.GetColour(MENU_POPUPITEM, TMT_TEXTCOLOR, MS_NORMAL);

I think this should be MPI_NORMAL instead of MS_NORMAL (both are 1). The definition at the start of this file can then be removed.

See the states for MENU_POPUPITEM in https://learn.microsoft.com/en-us/windows/win32/controls/parts-and-states


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

UAH is mentioned in darkmode.cpp with a link. It seems to be a common name for the Windows messages and structs used for custom menu drawing. But I cannot find a clear definition either.

dwReserved (or dwFlags as it is called elsewhere) doesn't seem to have any documentation. But I noticed these two bits are always set when the menu is opened, and never when the menu is closed.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3787874290@github.com>

Maarten

unread,
Feb 12, 2026, 6:34:43 AMFeb 12
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

Ugh, I've tried testing myself under Windows 11 (it's a pretty old version, 10.0.22621.3155) and it looks like dark mode is totally broken there

Looks fine in Windows 11 25H2.

I do not have those light borders.
Screenshot.2026-02-12.123234.png (view on web)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3890391150@github.com>

PB

unread,
Feb 12, 2026, 10:40:14 AMFeb 12
to wx-...@googlegroups.com, Subscribed
PBfordev left a comment (wxWidgets/wxWidgets#26182)

I can also confirm the menus are not broken in Win11 25H2 (I don't have access to an older version) dark mode both in the master and with this PR.

The light menu border is not present any longer (unlike in the original PR), sorry.

EDIT: The menus in the PR version do not handle switching between the dark and light mode well, they DO look broken after doing that. Does not happen in the master.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3891660664@github.com>

Mohmed abdel-fattah

unread,
Feb 13, 2026, 9:55:41 PMFeb 13
to wx-...@googlegroups.com, Subscribed

@memoarfaa commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

Hi @vadz , @MaartenBent , @PBfordev

UAH Menu Flags Reference (For Explanation Purposes Only)

⚠️ Note: This is an ongoing investigation based on observed behavior. These flags are undocumented and may not be complete or 100% accurate. Use for educational purposes only.

📊 Observed Flag Patterns

Flag Value Type Bit 0 State/Op Messages Observed Description Themed Non-Themed
0x00000001 Popup (1) CREATE WM_MENUBAR_INITMENU (0x93) Popup menu object created
0x00000200 MenuBar (0) INIT_FIRST WM_MENUBAR_INITMENU (0x93) First menu initialization
0x00000A00 MenuBar (0) MEASURE WM_MENUBAR_INITMENU (0x93)
WM_MENUBAR_DRAWMENU (0x91)
WM_MENUBAR_DRAWMENUITEM (0x92)
WM_MENUBAR_MEASUREMENUITEM (0x94)
Measuring/drawing items
0x00000A10 MenuBar (0) INACTIVE WM_MENUBAR_INITMENU (0x93)
WM_MENUBAR_DRAWMENU (0x91)
WM_MENUBAR_DRAWMENUITEM (0x92)
Menu bar inactive state
0x00000800 MenuBar (0) HOT WM_MENUBAR_DRAWMENUITEM (0x92)
WM_MENUBAR_DRAWMENU (0x91)
Hot tracking
0x00000810 MenuBar (0) HOT_INACTIVE WM_MENUBAR_DRAWMENUITEM (0x92) Hot + inactive
0x00000100 MenuBar (0) NORMAL WM_MENUBAR_DRAWMENUITEM (0x92) Normal drawing
0x00000101 Popup (1) SELECTED WM_MENUBAR_DRAWMENUITEM (0x92) Selected state (rare)
0x00000140 MenuBar (0) HOT WM_MENUBAR_DRAWMENUITEM (0x92) Hot drawing
0x00000180 MenuBar (0) INACTIVE WM_MENUBAR_DRAWMENUITEM (0x92) Inactive drawing
0x000001C0 MenuBar (0) HOT_INACTIVE WM_MENUBAR_DRAWMENUITEM (0x92) Hot + inactive drawing
0x04000001 Popup (1) POPUP_INIT WM_MENUBAR_INITMENU (0x93) Popup menu initialization (after click)
0x04000801 Popup (1) POPUP_MEASURE WM_MENUBAR_MEASUREMENUITEM (0x94) Measuring popup menu items

📋 Preliminary Message Mapping

Message Flag Values Observed
WM_MENUBAR_INITMENU (0x93) 0x00000200, 0x00000A00, 0x00000A10, 0x00000001, 0x04000001
WM_MENUBAR_DRAWMENU (0x91) 0x00000A00, 0x00000A10, 0x00000800
WM_MENUBAR_DRAWMENUITEM (0x92) 0x00000A00, 0x00000A10, 0x00000800, 0x00000810, 0x00000100, 0x00000101, 0x00000140, 0x00000180, 0x000001C0
WM_MENUBAR_MEASUREMENUITEM (0x94) 0x00000A00, 0x04000801

🔍 Preliminary Observations

Flags seen in ALL environments (core menu functionality):

  • 0x00000001 - Popup creation
  • 0x00000200 - First initialization
  • 0x00000A00 - Measurement/drawing (menu bar)
  • 0x00000100 - Normal drawing
  • 0x04000001 - Popup initialization (appears when submenu opens)
  • 0x04000801 - Popup measurement (appears when submenu items are measured)

Flags only seen in themed environments (visual feedback):

  • 0x00000A10 - Menu bar inactive state
  • 0x00000800 - Hot tracking on menu bar
  • 0x00000810 - Hot tracking when window inactive
  • 0x00000101 - Selected/pressed state
  • 0x00000140 - Drawing hot state
  • 0x00000180 - Drawing inactive state
  • 0x000001C0 - Drawing hot+inactive state


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3800203253@github.com>

Mohmed abdel-fattah

unread,
Feb 13, 2026, 11:08:59 PMFeb 13
to wx-...@googlegroups.com, Subscribed
memoarfaa left a comment (wxWidgets/wxWidgets#26182)

@PBfordev

EDIT 2: And a nitpick: In the PR, the menu item separator is not always drawn at full menu width (minus bitmaps). This is different from light mode and the master dark mode. Not sure if by design (this is not uniform, see the screenshots in my previous post). It happens only in the Menu menu in the menu sample (the one that has Break() called upon).

If this by design? the answer is Yes.
The owner's drawing menu contains a MENU_POPUPGUTER Part and it's better to keep It as it's.
contextpopup.png (view on web)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3900771862@github.com>

Mohmed abdel-fattah

unread,
Feb 13, 2026, 11:10:35 PMFeb 13
to wx-...@googlegroups.com, Subscribed

@memoarfaa commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -788,3 +811,51 @@ HandleMenuMessage(WXLRESULT* WXUNUSED(result),
 } // namespace wxMSWDarkMode
 
 #endif // wxUSE_DARK_MODE/!wxUSE_DARK_MODE
+
+void wxMSWImpl::EnableRoundCorners(HWND hwnd)
+{
+    const auto dwmSetWinAttr = wxDarkModeModule::GetDwmSetWindowAttribute();
+    if ( !dwmSetWinAttr )
+        return;
+
+    constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+    constexpr DWORD DWMWA_BORDER_COLOR = 34;
+    constexpr int WindowCornerPreference = 3; // DWMWCP_ROUNDSMALL
+
+    // Apply rounded corners
+    HRESULT hr = dwmSetWinAttr(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE,

On Windows 10, every time I open a menu the debugger logs the following:

clientcore\windows\dwm\dwmapi\attribute.cpp(185)\dwmapi.dll!00007FFFA9F62C57: (caller: 00007FFEDA0A29C1) ReturnHr(29) tid(2ef8) 80070057 The parameter is incorrect.

I don't think it supports rounded corners. Maybe limit it to Windows 11 only? Like it is already done in HandleEnterIdle.

Yes this is true.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3800725013@github.com>

PB

unread,
Feb 14, 2026, 2:09:29 AMFeb 14
to wx-...@googlegroups.com, Subscribed
PBfordev left a comment (wxWidgets/wxWidgets#26182)

@PBfordev

EDIT 2: And a nitpick: In the PR, the menu item separator is not always drawn at full menu width (minus bitmaps). This is different from light mode and the master dark mode. Not sure if by design (this is not uniform, see the screenshots in my previous post). It happens only in the Menu menu in the menu sample (the one that has Break() called upon).

If this by design? the answer is Yes. The owner's drawing menu contains a MENU_POPUPGUTER Part and it's better to keep It as it's.

I don't really care either way. But I find surprising it is not consistent: As I wrote, in the menu sample it can be seen that the separators are full width for menus File, Menubar, and Test (and they have bitmaps, checks and radios) but not for menu Menu (which calls Break() and has two columns).

BTW, I hope you understand I appreciate your work here, this is just a review, not an attempt to annoy you.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3901291358@github.com>

VZ

unread,
Feb 14, 2026, 10:07:30 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +    if ( win )
+    {
+        wxUxThemeHandle hTheme
+            (
+                win,
+                L"LightMode_ImmersiveStart::Menu;MENU",
+                L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
+            );
+        colBorder = hTheme.GetColour(MENU_POPUPBORDERS, TMT_FILLCOLORHINT);
+    }
+
+    if ( !colBorder.IsOk() )
+        colBorder = wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER);
+
+    DWORD color = static_cast<DWORD>(wxColourToRGB(colBorder));
+    dwmSetWinAttr(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));

@memoarfaa What do you think of using a different colour here? It looks like light border is not typically used for the menus.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801941304@github.com>

VZ

unread,
Feb 14, 2026, 10:10:59 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

Thanks, this is very useful, but according to this table, shouldn't we test for dwReserved == 0x4000001? I.e. why do we call EnableRoundCorners() twice, for both POPUP_INIT and POPUP_MEASURE, is this intentional?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801942912@github.com>

VZ

unread,
Feb 14, 2026, 10:11:30 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -579,6 +586,22 @@ HandleMenuMessage(WXLRESULT* result,
 
     switch ( nMsg )
     {
+        case WM_MENUBAR_INITMENU:
+            // Menu them is turned off in high contrast mode.
+            if ( wxMSWImpl::IsHighContrast() )
+                break;
+
+            // Enable rounded corners for UAH menus
+            if ( auto* const pUahMenu = (MenuBarDrawMenu*)lParam )
+            {
+                if ( pUahMenu->dwReserved & 0x4000001 )

P.S. As I still can't test this myself, could someone (sorry @PBfordev if it means you again) please test if replacing & with == still works?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801943437@github.com>

VZ

unread,
Feb 14, 2026, 10:14:10 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> @@ -788,3 +811,51 @@ HandleMenuMessage(WXLRESULT* WXUNUSED(result),
 } // namespace wxMSWDarkMode
 
 #endif // wxUSE_DARK_MODE/!wxUSE_DARK_MODE
+
+void wxMSWImpl::EnableRoundCorners(HWND hwnd)
+{
+    const auto dwmSetWinAttr = wxDarkModeModule::GetDwmSetWindowAttribute();
+    if ( !dwmSetWinAttr )
+        return;
+
+    constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+    constexpr DWORD DWMWA_BORDER_COLOR = 34;
+    constexpr int WindowCornerPreference = 3; // DWMWCP_ROUNDSMALL
+
+    // Apply rounded corners
+    HRESULT hr = dwmSetWinAttr(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE,

Added, thanks.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801947744@github.com>

VZ

unread,
Feb 14, 2026, 10:16:15 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +    constexpr DWORD DWMWA_WINDOW_CORNER_PREFERENCE = 33;
+    constexpr DWORD DWMWA_BORDER_COLOR = 34;

This would make them inconsistent with DWMWA_USE_IMMERSIVE_DARK_MODE. Let's leave them like this for now and maybe change them all at once later if/when we start including dwmapi.h.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801952285@github.com>

VZ

unread,
Feb 14, 2026, 10:21:01 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/menuitem.cpp:

> @@ -1261,7 +1340,18 @@ void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& co
         {
             colText = GetTextColour();
             if ( !colText.IsOk() )
-                wxRGBToColour(colText, ::GetThemeSysColor(hTheme, COLOR_MENUTEXT));
+            {
+                if ( wxMSWDarkMode::IsActive() )
+                {
+                    colText = hTheme.GetColour(MENU_POPUPITEM, TMT_TEXTCOLOR, MS_NORMAL);

Thanks, you're right, of course.

I still wonder what is this (from tmschema.h) about though:

BEGIN_TM_PART_STATES(MENU)
TM_STATE(1,MS,NORMAL)
TM_STATE(2,MS,SELECTED)
TM_STATE(3,MS,DEMOTED)
END_TM_PART_STATES()


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801957327@github.com>

VZ

unread,
Feb 14, 2026, 10:22:45 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +    if ( win )
+    {
+        wxUxThemeHandle hTheme
+            (
+                win,
+                L"LightMode_ImmersiveStart::Menu;MENU",
+                L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
+            );
+        colBorder = hTheme.GetColour(MENU_POPUPBORDERS, TMT_FILLCOLORHINT);
+    }
+
+    if ( !colBorder.IsOk() )
+        colBorder = wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVEBORDER);
+
+    DWORD color = static_cast<DWORD>(wxColourToRGB(colBorder));
+    dwmSetWinAttr(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));

Oops, after reading to the end, I see that @PBfordev doesn't see the light borders any longer, apparently, so this is probably good as it is, finally, sorry.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801958185@github.com>

VZ

unread,
Feb 14, 2026, 10:27:01 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;
+
+    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;

I think you meant HWND, right? If so, I've modified the code to do it like this now, thanks. If not, please let me know what did you mean.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801960338@github.com>

VZ

unread,
Feb 14, 2026, 10:39:47 AMFeb 14
to wx-...@googlegroups.com, Push

@vadz pushed 3 commits.

  • 7996469 Allow creating appropriate wxUxThemeHandle in dark mode from HWND
  • e8e9252 Fix appearance of owner drawn menus in dark mode
  • 331adf3 Fix rounded menu corners appearance under Windows 11


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/before/83903accaf465b07babbb9378d4a08384d010bc4/after/331adf3dbf34c46c80a18f2982d51595f1a92fe7@github.com>

Maarten

unread,
Feb 14, 2026, 10:40:07 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.


In src/msw/darkmode.cpp:

> +
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;
+
+    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;

That's not what I meant, but maybe that works as well. Though I don't know if a hwnd of a menu is fine, or if it should be a window.

My original idea was this:

 include/wx/msw/private/darkmode.h | 2 +-
 src/msw/darkmode.cpp              | 5 ++---
 src/msw/window.cpp                | 2 +-
 3 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/include/wx/msw/private/darkmode.h b/include/wx/msw/private/darkmode.h
index 56db19a7a7b..cc523ce30bf 100644
--- a/include/wx/msw/private/darkmode.h
+++ b/include/wx/msw/private/darkmode.h
@@ -72,7 +72,7 @@ namespace wxMSWImpl
 
 // This function is not dark mode specific but reuses the code in darkmode.cpp,
 // so it's implemented there as well.
-void EnableRoundCorners(HWND hwnd);
+void EnableRoundCorners(wxWindow* win, HWND menuHwnd);
 
 } // namespace wxMSWImpl
 
diff --git a/src/msw/darkmode.cpp b/src/msw/darkmode.cpp
index 73b56c882be..f8b41b4eeac 100644
--- a/src/msw/darkmode.cpp
+++ b/src/msw/darkmode.cpp
@@ -597,7 +597,7 @@ HandleMenuMessage(WXLRESULT* result,
                 if ( pUahMenu->dwReserved & 0x4000001 )
                 {
                     if ( HWND hWndMenu = ::WindowFromDC(pUahMenu->hdc) )
-                        wxMSWImpl::EnableRoundCorners(hWndMenu);
+                        wxMSWImpl::EnableRoundCorners(w, hWndMenu);
                 }
             }
             break;
@@ -812,7 +812,7 @@ HandleMenuMessage(WXLRESULT* WXUNUSED(result),
 
 #endif // wxUSE_DARK_MODE/!wxUSE_DARK_MODE
 
-void wxMSWImpl::EnableRoundCorners(HWND hwnd)
+void wxMSWImpl::EnableRoundCorners(wxWindow* win, HWND hwnd)
 {
     const auto dwmSetWinAttr = wxDarkModeModule::GetDwmSetWindowAttribute();
     if ( !dwmSetWinAttr )
@@ -841,7 +841,6 @@ void wxMSWImpl::EnableRoundCorners(HWND hwnd)
     // Determine the appropriate border colour for the current theme.
     wxColor colBorder;
 
-    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;
     if ( win )
     {
         wxUxThemeHandle hTheme
diff --git a/src/msw/window.cpp b/src/msw/window.cpp
index 0522e6e7d9e..eb519aa3d07 100644
--- a/src/msw/window.cpp
+++ b/src/msw/window.cpp
@@ -4300,7 +4300,7 @@ bool wxWindowMSW::HandleEnterIdle(WXWPARAM wParam, WXLPARAM lParam)
 
     if ( !wxMSWDarkMode::IsActive() && !wxMSWImpl::IsHighContrast() )
     {
-        wxMSWImpl::EnableRoundCorners(reinterpret_cast<HWND>(lParam));
+        wxMSWImpl::EnableRoundCorners(this, reinterpret_cast<HWND>(lParam));
     }
 #else
     wxUnusedVar(wParam);


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801967113@github.com>

Maarten

unread,
Feb 14, 2026, 10:45:35 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.


In src/msw/menuitem.cpp:

> @@ -1261,7 +1340,18 @@ void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& co
         {
             colText = GetTextColour();
             if ( !colText.IsOk() )
-                wxRGBToColour(colText, ::GetThemeSysColor(hTheme, COLOR_MENUTEXT));
+            {
+                if ( wxMSWDarkMode::IsActive() )
+                {
+                    colText = hTheme.GetColour(MENU_POPUPITEM, TMT_TEXTCOLOR, MS_NORMAL);

I don't have this header at all. Is it from the Windows 7 SDK?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801970172@github.com>

VZ

unread,
Feb 14, 2026, 10:48:59 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/darkmode.cpp:

> +
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;
+
+    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;

Ah, I see, sorry for misunderstanding.

I'm not sure which window is needed here either (and it's possible that it doesn't even matter...). Does the latest version work for you under Windows 11? If so, I'd probably leave it as is.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801973874@github.com>

VZ

unread,
Feb 14, 2026, 10:50:43 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/menuitem.cpp:

> @@ -1261,7 +1340,18 @@ void wxMenuItem::GetColourToUse(wxODStatus stat, wxColour& colText, wxColour& co
         {
             colText = GetTextColour();
             if ( !colText.IsOk() )
-                wxRGBToColour(colText, ::GetThemeSysColor(hTheme, COLOR_MENUTEXT));
+            {
+                if ( wxMSWDarkMode::IsActive() )
+                {
+                    colText = hTheme.GetColour(MENU_POPUPITEM, TMT_TEXTCOLOR, MS_NORMAL);

No, it's from MinGW-w64 (I only copy symbol values for the stuff we use in wx from there, not from SDK directly, just in case...).

Under Debian, it's /usr/share/mingw-w64/include/tmschema.h from mingw-w64-common package.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3801976641@github.com>

Maarten

unread,
Feb 14, 2026, 11:40:00 AMFeb 14
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.


In src/msw/darkmode.cpp:

> +
+    if ( FAILED(hr) )
+        return;
+
+    // Clean up conflicting styles like drop shadows.
+    DWORD style = ::GetClassLongPtr(hwnd, GCL_STYLE);
+    if ( style & CS_DROPSHADOW )
+    {
+        style &= ~CS_DROPSHADOW;
+        ::SetClassLongPtr(hwnd, GCL_STYLE, style);
+    }
+
+    // Determine the appropriate border colour for the current theme.
+    wxColor colBorder;
+
+    wxWindow* const win = wxTheApp ? wxTheApp->GetTopWindow() : nullptr;

Border color still looks correct in dark and light mode when using hwnd directly.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3802074705@github.com>

Maarten

unread,
Feb 14, 2026, 11:47:46 AMFeb 14
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

I do see the problem that @PBfordev mentioned. After switching from light to dark mode in Windows settings, with the app open, the 'normal' menus get broken. The owner-drawn menu stays light. I didn't test if this already happens before this PR.
Screenshot.2026-02-14.174347.png (view on web) Screenshot.2026-02-14.174409.png (view on web)


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3902160060@github.com>

VZ

unread,
Feb 14, 2026, 12:11:03 PMFeb 14
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

My guess would be that it doesn't work correctly in master either, but it would be nice to test this, if possible...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3902189919@github.com>

PB

unread,
Feb 14, 2026, 12:39:23 PMFeb 14
to wx-...@googlegroups.com, Subscribed
PBfordev left a comment (wxWidgets/wxWidgets#26182)

My guess would be that it doesn't work correctly in master either, but it would be nice to test this, if possible...

As I wrote, it does NOT happen in the master with menus. OTOH, both are broken in many other ways:

In the menu sample basically everything besides the menubar stays dark. E.g., the frame caption and background, the edit control and the status bar.

Some things improve after moving the frame to another monitor, the frame remains dark, and there are artifacts on the status bar (frame gripper?) and the edit control (black border):
image.png (view on web)

And one more nitpick related to this PR, the checkmark bitmap background seems different from the normal menu and two-column menu (with Break() called upon it, i.e., similar as with the separator width):
image.png (view on web)
vs
image.png (view on web)

Sorry for all these not-so-great news.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3902229205@github.com>

VZ

unread,
Feb 14, 2026, 3:46:50 PMFeb 14
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

I guess we should still merge it as the behaviour when changing between light and dark mode dynamically is broken anyhow, while this, at least, improves things when dark mode is already turned on when the application launches.

Do you agree?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3902493889@github.com>

Mohmed abdel-fattah

unread,
Feb 14, 2026, 10:41:08 PMFeb 14
to wx-...@googlegroups.com, Subscribed

@memoarfaa commented on this pull request.


In src/msw/window.cpp:

> 

Sorry for all these not-so-great news.

Ok @PBfordev these is old news .

@vadz

I guess we should still merge it as the behaviour when changing between light and dark mode dynamically is broken anyhow, while this, at least, improves things when dark mode is already turned on when the application launches.

Do you agree?

I say give me some time for this.
#26053 (comment)
But I'm busy these days, so let's help each other get this over with by tomorrow, including your Windows 11 system issue.

  • Let's start with the first one.

In the menu sample basically everything besides the menubar stays dark. E.g., the frame caption and background, the edit control and the status bar.

Some things improve after moving the frame to another monitor, the frame remains dark, and there are artifacts on the status bar (frame gripper?) and the edit control (black border): image

  • Handel OnSysColourChanged

// Responds to colour changes: passes event on to children.
void wxWindowMSW::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
{
    // update the menu background colour to match the current theme as otherwise
    wxString strTheme = wxMSWDarkMode::IsActive() ? L"DarkMode_ImmersiveStart::Menu;MENU" : L"LightMode_ImmersiveStart::Menu;Menu";
    wxUxThemeHandle hTheme = wxUxThemeHandle::NewAtStdDPI(strTheme.c_str());
    wxColour wxMenuColor = hTheme.GetColour(MENU_POPUPBACKGROUND, TMT_FILLCOLOR);
    if (wxMenuColor.IsOk())
    {
        COLORREF crMenu = wxColourToRGB(wxMenuColor);
        LOGBRUSH lbr;
        memset(&lbr, 0, sizeof(LOGBRUSH));
        lbr.lbColor = crMenu;
        HBRUSH GBRUSH = CreateBrushIndirect(&lbr);
        WinStruct<MENUINFO> mi;
        HWND hWnd = GetHwnd();
        HMENU hMenu = ::GetMenu(hWnd);
        if (hMenu)
        {
           MENUINFO MenuInfo = { 0};
            memset(&MenuInfo, 0, sizeof(MENUINFO));
            MenuInfo.cbSize = sizeof(mi);
            GetMenuInfo(hMenu, &mi);
            mi.fMask = MIM_BACKGROUND | MIM_APPLYTOSUBMENUS;
            mi.hbrBack = (HBRUSH)wxTheBrushList->FindOrCreateBrush(crMenu)->GetResourceHandle();
            if (!::SetMenuInfo(hMenu, &mi))
            {
                wxLogLastError(wxT("SetMenuInfo(MIM_BACKGROUND)"));
            }
        }

    }
    // the top level window also reset the standard colour map as it might have
    // changed (there is no need to do it for the non top level windows as we
    // only have to do it once)
    if ( IsTopLevel() )
    {
        // FIXME-MT
        gs_hasStdCmap = false;

    }
    wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
    while ( node )
    {
        // Only propagate to non-top-level windows because Windows already
        // sends this event to all top-level ones
        wxWindow *win = node->GetData();
        if ( !win->IsTopLevel() )
        {
            // we need to send the real WM_SYSCOLORCHANGE and not just trigger
            // EVT_SYS_COLOUR_CHANGED call because the latter wouldn't work for
            // the standard controls
            ::SendMessage(GetHwndOf(win), WM_SYSCOLORCHANGE, 0, 0);
        }

        node = node->GetNext();
    }
}


https://github.com/user-attachments/assets/ad5eb386-7206-4941-b81f-f0f80869c600


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3803327938@github.com>

Mohmed abdel-fattah

unread,
Feb 15, 2026, 12:46:21 AMFeb 15
to wx-...@googlegroups.com, Subscribed
memoarfaa left a comment (wxWidgets/wxWidgets#26182)

@PBfordev

I don't really care either way. But I find surprising it is not consistent: As I wrote, in the menu sample it can be seen that the separators are full width for menus File, Menubar, and Test (and they have bitmaps, checks and radios) but not for menu Menu (which calls Break() and has two columns).

BTW, I hope you understand I appreciate your work here, this is just a review, not an attempt to annoy you.

I understand and know that there is no attempt to upset me; we are all here to make an improvement.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3903367407@github.com>

Mohmed abdel-fattah

unread,
Feb 15, 2026, 2:21:41 AMFeb 15
to wx-...@googlegroups.com, Subscribed
memoarfaa left a comment (wxWidgets/wxWidgets#26182)

@vadz

Ugh, I've tried testing myself under Windows 11 (it's a pretty old version, 10.0.22621.3155) and it looks like dark mode is totally broken there, this is how menu sample looks for me with master (it's almost the same with this PR):

P.S. As I still can't test this myself, could someone (sorry @PBfordev if it means you again) please test if replacing & with == still works?

but something is very wrong under 11...

Regarding your Windows 11 version, 10.0.22621.3155, I have an almost identical version (an ISO file containing all versions) and dark mode works perfectly for me with Rounded Corner at Hyper-V.

https://github.com/user-attachments/assets/1d6ba93b-7e5c-4288-ab90-0dab408d4663

from image I seen it's seemes that.

1- Your Window scrollbar is not themed.
2- Window without rounded corners.
3- Menubar can't draw menu Items text.
Screenshot.2026-02-15.075231.png (view on web)

analysis the proplem.

1- Incorrect use of the SetWindowTheme function with a class that does not exist in Aero Msstyles theme (Aero.Msstyles).
can turn off SetWindowTheme in code.
2- Cutome Aero.Msstyles.
can use this exe to list darkMode Classes

CMapDarkMode.rar

Screenshot.2026-02-15.091014.png (view on web)

My be your Windows 11 has difference windows edition. My edition is pro What's your edition?

- About rounded corners.

1-my be beacuase of Incorrect use of the SetWindowTheme.
2- my be beacuase of Running in Hyper-V.
Enfoce Round Corners at Hyper-V

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Dwm]
"ForceEffectMode"=dword:00000002



Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3903509905@github.com>

VZ

unread,
Feb 15, 2026, 9:32:13 AMFeb 15
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

I wouldn't worry much about the problem in my very old Windows 11 VM, nobody is probably running it any longer but, just in case, this is also a Pro version, here is the information copy-pasted from "System » About":

Edition	Windows 11 Pro
Version	22H2
Installed on	‎9 ‎Feb ‎2023
OS build	22621.4317
Experience	Windows Feature Experience Pack 1000.22700.1041.0

The only problem is that I can't update it (I had installed it using old version of QEMU where TPM passthrough worked without problems, but somehow it doesn't work any more and I can't upgrade without working TPM...) and so can't currently test anything myself.

Setting ForceEffectMode doesn't do anything for me. Of course, the weird thing is that Windows itself works just fine and menus in e.g. notepad have round corners, it's only wx which has problems on this system.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3904554461@github.com>

VZ

unread,
Feb 15, 2026, 10:36:55 AMFeb 15
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

I wouldn't worry much about the problem in my very old Windows 11 VM

Well, maybe I should. I've made TPM work with QEMU again and updated to the latest version

Edition	Windows 11 Pro
Version	25H2
Installed on	‎15 ‎Feb ‎2026
OS build	26200.7840
Experience	Windows Feature Experience Pack 1000.26100.291.0

and I still have the same problems.

So on one hand this is probably still not that bad because it's clearly something broken in my VM and not more generally, but OTOH it's very inconvenient because I still can't test dark mode support under Windows 11 and I don't know what to do about it.

Maybe the problem is that my VM doesn't have any dedicated GPU? But then it never did and yet dark mode worked fine in it some (long) time ago...


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3904692612@github.com>

VZ

unread,
Feb 20, 2026, 9:18:39 AMFeb 20
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

We need to decide whether this should be merged or not. I still can't test this myself, so I'm not sure, but I think it's better to improve dark mode support even if it makes switching between modes work even worse — but then it's already broken, so this is arguably less important...

What do the others think?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3935120148@github.com>

PB

unread,
Feb 20, 2026, 3:32:45 PMFeb 20
to wx-...@googlegroups.com, Subscribed
PBfordev left a comment (wxWidgets/wxWidgets#26182)

Well, wxWidgets does not handle the switching between dark and light modes well, but AFAICT, the controls remain usable.

When switching from the light to dark mode with the PR, the menus are unreadable:
wxmenu-switch-light.png (view on web)

The menus are barely readable (dark text on dark background) when switching the other direction. I understand that people don't switch the mode often.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3937025028@github.com>

VZ

unread,
Feb 20, 2026, 4:11:32 PMFeb 20
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

@memoarfaa Any chance you could improve this to avoid regressions when switching between modes soon, i.e. before the end of the month?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3937177667@github.com>

Maarten

unread,
Feb 21, 2026, 6:32:50 AMFeb 21
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

They did post a possible fix using OnSysColourChanged in #26182 (comment). This is your PR @vadz , so they can't push a commit with the actual fix.
I'll try to test it by manually applying it.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3938643212@github.com>

VZ

unread,
Feb 21, 2026, 8:02:45 AMFeb 21
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

I didn't even realize this patch was supposed to fix this issue :-( Not being able to test it myself is really annoying. TIA for looking at this!


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3938747294@github.com>

Maarten

unread,
Feb 21, 2026, 4:29:07 PMFeb 21
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

I cleaned up the suggested patch, and it works with adding the code below to wxWindowMSW::OnSysColourChanged().
(note: only works when getting the hTheme without a hwnd/window).

This is basically the exact same code as added to wxMenuBar::Create, so maybe it can be combined into one function. Except that GetFrame()->AsWindow() should be removed like I mentioned above, it works fine without it.

There is one special case that doesn't work. This happens when starting in light mode and switching to dark mode, and when the menu that has a Break() (like in the menu example).
This happens because breaks are set to owner-drawn when created in dark-mode (added in this PR). But when switching to dark-mode later, it is not owner-drawn.
To me this seems like a very limited use-case, so I think this shouldn't stop this PR from getting merged.

#if wxUSE_OWNER_DRAWN
    // Update menu background color
    if ( HMENU hMenu = ::GetMenu(GetHwnd()) )
    {
        auto hTheme = wxUxThemeHandle::NewAtStdDPI
            (
                L"LightMode_ImmersiveStart::Menu;MENU",
                
L"DarkMode_ImmersiveStart::Menu;DarkMode::Menu;MENU"
            );
        wxColour colMenu = hTheme.GetColour(MENU_POPUPBACKGROUND, TMT_FILLCOLOR);
        if ( colMenu.IsOk() )
        {
            wxBrush* const brush =
                wxTheBrushList->FindOrCreateBrush(wxColourToRGB(colMenu));

            WinStruct<MENUINFO> mi;
            mi.fMask = MIM_BACKGROUND | MIM_APPLYTOSUBMENUS;
            mi.hbrBack = GetHbrushOf(*brush);
            if ( !::SetMenuInfo(hMenu, &mi) )
            {
                wxLogLastError(wxT("SetMenuInfo(MIM_BACKGROUND)"));
            }
        }
    }
#endif // wxUSE_OWNER_DRAWN


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3939534387@github.com>

VZ

unread,
Feb 21, 2026, 6:07:43 PMFeb 21
to wx-...@googlegroups.com, Push

@vadz pushed 1 commit.

  • ed55221 Update wxMenuBar background after system colours change


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/before/331adf3dbf34c46c80a18f2982d51595f1a92fe7/after/ed552217fea243d81c0398999d36ef4ac320cc59@github.com>

VZ

unread,
Feb 21, 2026, 6:08:24 PMFeb 21
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

Thanks a lot, I've refactored the code as proposed and pushed the commit — please let me know if I have broken anything. If not, and if @PBfordev doesn't see any other blockers, I'll merge this soon (tomorrow?).


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3939664197@github.com>

Maarten

unread,
Feb 21, 2026, 6:35:38 PMFeb 21
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.

This works for me.

There is just one inconsistency around MSWApplyThemeBackground. In wxFrame it is guarded with wxUSE_OWNER_DRAWN, but in wxMenuBar it isn't (anymore). I don't think it needs one, so it could be removed in wxFrame.


In src/msw/menu.cpp:

> @@ -338,6 +342,11 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
     // (and don't forget to reset the flag)
     if ( m_doBreak ) {
         flags |= MF_MENUBREAK;
+        if ( wxMSWDarkMode::IsActive() )
+        {
+            // Menu breaks must be owner drawn to work properly in dark mode
+            pItem->SetOwnerDrawn(true);

This needs a #if wxUSE_OWNER_DRAWN guard


In src/msw/menu.cpp:

>      }
 
     return m_hMenu;
 }
 
+void wxMenuBar::MSWApplyThemeBackground()
+{
+    // Set menu background color
+    wxUxThemeHandle hTheme = wxUxThemeHandle::NewAtStdDPI
+        (
+         L"LightMode_ImmersiveStart::Menu;Menu",
+         L"DarkMode_ImmersiveStart::Menu;Menu"
+        );
+    wxColor colMenu = hTheme.GetColour(MENU_POPUPBACKGROUND, TMT_FILLCOLOR);

wxColour


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3836205254@github.com>

Maarten

unread,
Feb 22, 2026, 5:48:14 AMFeb 22
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

There is just one inconsistency around MSWApplyThemeBackground. In wxFrame it is guarded with wxUSE_OWNER_DRAWN, but in wxMenuBar it isn't (anymore). I don't think it needs one, so it could be removed in wxFrame

On second thought, maybe it is better to keep the guard, but move it into MSWApplyThemeBackground(). Because changing the menu colour is only useful in combination with owner-drawn menu(item)s.
When I test it with wxUSE_OWNER_DRAWN disabled, it can result in black text on dark menu. And then I think it is better to keep the light menu, even in dark mode.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3940692344@github.com>

RobertRoeb

unread,
Feb 22, 2026, 7:23:14 AMFeb 22
to wx-...@googlegroups.com, Subscribed
RobertRoeb left a comment (wxWidgets/wxWidgets#26182)

Is it now possible to change between dark and light mode during run-time on MSW as well?


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3940842423@github.com>

Maarten

unread,
Feb 22, 2026, 7:26:39 AMFeb 22
to wx-...@googlegroups.com, Subscribed
MaartenBent left a comment (wxWidgets/wxWidgets#26182)

No, there are still many flaws. But if it happens I won't make the menu unreadable.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3940848290@github.com>

VZ

unread,
Feb 22, 2026, 9:38:21 AMFeb 22
to wx-...@googlegroups.com, Push

@vadz pushed 1 commit.

  • b33e88d Update wxMenuBar background after system colours change


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/before/ed552217fea243d81c0398999d36ef4ac320cc59/after/b33e88d2ac1c1768d9484d9e58d7293dab7f7692@github.com>

VZ

unread,
Feb 22, 2026, 9:38:39 AMFeb 22
to wx-...@googlegroups.com, Subscribed
vadz left a comment (wxWidgets/wxWidgets#26182)

Amended after your comments, thanks Maarten!


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/c3941077597@github.com>

Maarten

unread,
Feb 22, 2026, 9:52:55 AMFeb 22
to wx-...@googlegroups.com, Subscribed

@MaartenBent commented on this pull request.

In src/msw/menu.cpp:

> @@ -338,6 +342,11 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
     // (and don't forget to reset the flag)
     if ( m_doBreak ) {
         flags |= MF_MENUBREAK;
+        if ( wxMSWDarkMode::IsActive() )
+        {
+            // Menu breaks must be owner drawn to work properly in dark mode
+            pItem->SetOwnerDrawn(true);

You forgot to fix this? SetOwnerDrawn is only available with wxUSE_OWNER_DRAWN.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3837962807@github.com>

VZ

unread,
Feb 22, 2026, 9:56:36 AMFeb 22
to wx-...@googlegroups.com, Push

@vadz pushed 1 commit.

  • 95f9b07 Update wxMenuBar background after system colours change


View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/before/b33e88d2ac1c1768d9484d9e58d7293dab7f7692/after/95f9b074fe9404c014cb8e736a045ab2913cab47@github.com>

VZ

unread,
Feb 22, 2026, 9:57:10 AMFeb 22
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.


In src/msw/menu.cpp:

> @@ -338,6 +342,11 @@ bool wxMenu::DoInsertOrAppend(wxMenuItem *pItem, size_t pos)
     // (and don't forget to reset the flag)
     if ( m_doBreak ) {
         flags |= MF_MENUBREAK;
+        if ( wxMSWDarkMode::IsActive() )
+        {
+            // Menu breaks must be owner drawn to work properly in dark mode
+            pItem->SetOwnerDrawn(true);

Sorry, don't know how this happened, I thought I did fix it but clearly didn't :-( Thanks for noticing, really fixed now.


Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/review/3837983546@github.com>

VZ

unread,
Feb 23, 2026, 5:36:35 AMFeb 23
to wx-...@googlegroups.com, Subscribed

Merged #26182 into master.


Reply to this email directly, view it on GitHub, or unsubscribe.

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26182/issue_event/22997024069@github.com>

Reply all
Reply to author
Forward
0 new messages