MSW: Dark mode borders (PR #26571)

8 views
Skip to first unread message

Steve Cornett

unread,
Jun 8, 2026, 10:11:17 AM (15 hours ago) Jun 8
to wx-...@googlegroups.com, Subscribed

For Windows dark mode, draw themed borders instead of translating wxBORDER_THEME to wxBORDER_SIMPLE. Borders have the same thickness between light mode and dark mode for consistent alignment and positioning. See #26529.

In dark mode, the border styles wxBORDER_STATIC, wxBORDER_RAISED and wxBORDER_SUNKEN are sometimes drawn by the system using light mode colours. So draw these borders similarly to themed borders, but using the proper width. There is no attempt to mimic a raised or sunken look.

The WM_NCPAINT and WM_NCPAINT message handling is simplified and corrected for calculating the border width.


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

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

Commit Summary

File Changes

(2 files)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26571@github.com>

VZ

unread,
Jun 8, 2026, 10:31:25 AM (14 hours ago) Jun 8
to wx-...@googlegroups.com, Subscribed

@vadz commented on this pull request.

Thanks, I didn't test this yet but the changes look good to me.


In src/msw/window.cpp:

> +                    static_assert(EP_EDITTEXT == LVP_LISTITEM);
+                    static_assert(ETS_NORMAL == LISS_NORMAL);

Need to cast to int to avoid warnings and probably should provide a message to avoid requiring C++14.


In src/msw/window.cpp:

>                      ::ExcludeClipRect(GetHdcOf(*impl), rcClient.left, rcClient.top,
                                       rcClient.right, rcClient.bottom);
 
+                    // Draw the theme border and background.
+
+                    // The EDIT theme gives a good general purpose border in light mode.
+                    // There does not seem to be a dark mode EDIT theme that looks good.
+                    // The ListView theme below looks good in dark mode.
+                    wxUxThemeHandle hTheme(this, L"EDIT", L"DarkMode_DarkTheme::ListView");

I wonder if it could be worth caching this theme to avoid opening/closing it all the time. I have no idea how expensive this is, so maybe it's not worth it, but OTOH keeping it open (as a global var) should be pretty simple.


In src/msw/window.cpp:

> -                        // If GetThemeBackgroundContentRect() failed, as can
-                        // happen with at least some custom themes, just use
-                        // the original client rectangle.
-                        rcClient = *rect;
-                    }
-
-                    InflateRect(&rcClient, -1, -1);
-                    if (wParam)
-                        csparam->rgrc[0] = rcClient;
-                    else
-                        *((RECT*)lParam) = rcClient;
-
-                    // WVR_REDRAW triggers a bug whereby child windows are moved up and left,
-                    // so don't use.
-                    // rc.result = WVR_REDRAW;
+                    const auto borderWidth = GetWindowBorderSize().x / 2;

I wonder if it could make sense to add some MSWGetBorderThickness() returning just this, i.e. a single int, not multiplied by 2, unlike GetWindowBorderSize() which returns a wxSize multiplied by it.

The idea being is that / 2 begs the question of what happens when the value is odd, which actually can never happen, but this is not really obvious.


In src/msw/window.cpp:

> -                if (DoTranslateBorder(GetBorder()) == wxBORDER_THEME)
+                // Determine whether we should draw a border.
+                bool drawBorder = false;
+                switch ( DoTranslateBorder(GetBorder()) )
+                {
+                    case wxBORDER_THEME:
+                        drawBorder = true;
+                        break;
+                    case wxBORDER_STATIC:
+                    case wxBORDER_RAISED:
+                    case wxBORDER_SUNKEN:
+                        // In dark mode, explicitly draw these border styles because
+                        // the default drawing uses light mode colours.
+                        drawBorder = wxMSWDarkMode::IsActive();
+                        break;
+                }

I'd add the cases for the other values (SIMPLE and NONE) just to make it clear that we do handle them here.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Steve Cornett

unread,
Jun 8, 2026, 10:32:58 AM (14 hours ago) Jun 8
to wx-...@googlegroups.com, Push

@stevecor pushed 1 commit.


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26571/before/ea7ba978a50f70710a65e0d8dc7a8a3e346b9966/after/17a111883f5cd3493a34c8f4e945c82b2ee764f2@github.com>

Steve Cornett

unread,
Jun 8, 2026, 10:50:27 AM (14 hours ago) Jun 8
to wx-...@googlegroups.com, Subscribed

@stevecor commented on this pull request.


In src/msw/window.cpp:

>                      ::ExcludeClipRect(GetHdcOf(*impl), rcClient.left, rcClient.top,
                                       rcClient.right, rcClient.bottom);
 
+                    // Draw the theme border and background.
+
+                    // The EDIT theme gives a good general purpose border in light mode.
+                    // There does not seem to be a dark mode EDIT theme that looks good.
+                    // The ListView theme below looks good in dark mode.
+                    wxUxThemeHandle hTheme(this, L"EDIT", L"DarkMode_DarkTheme::ListView");

I timed this with wxStopWatch and got just 11µs for 242 calls.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

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

Steve Cornett

unread,
Jun 8, 2026, 10:56:10 AM (14 hours ago) Jun 8
to wx-...@googlegroups.com, Push

@stevecor pushed 1 commit.

  • 0345e1b Add all border switch cases


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26571/before/17a111883f5cd3493a34c8f4e945c82b2ee764f2/after/0345e1b94bc9614b8b9c0cfff51abb990b818aa4@github.com>

Steve Cornett

unread,
Jun 8, 2026, 11:17:32 AM (13 hours ago) Jun 8
to wx-...@googlegroups.com, Push

@stevecor pushed 1 commit.

  • 9c0bd0f Add MSWGetBorderThickness()


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26571/before/0345e1b94bc9614b8b9c0cfff51abb990b818aa4/after/9c0bd0fa969bd935f65a8fd72f853247ec3d4144@github.com>

Steve Cornett

unread,
Jun 8, 2026, 11:37:31 AM (13 hours ago) Jun 8
to wx-...@googlegroups.com, Push

@stevecor pushed 1 commit.


View it on GitHub or unsubscribe.


Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!

You are receiving this because you are subscribed to this thread.Message ID: <wxWidgets/wxWidgets/pull/26571/before/9c0bd0fa969bd935f65a8fd72f853247ec3d4144/after/c34e1f1593514955971ba91433ae30929589d866@github.com>

Reply all
Reply to author
Forward
0 new messages