Fix wxPaintDC invalidation in wxMSW wxNotebook in dark mode Claling GetTabRect() while painting wxNotebook could result in another WM_PAINT sent by the native control when using multiple tab rows and after handling this nested WM_PAINT wxMSW code called EndPaint() on the DC used by wxPaintDC that we had created before calling GetTabRect(). This is almost certainly wrong and we should use reference counting instead of assuming that nothing can use the HDC once we return from WM_PAINT handler as the code seems to be doing currently, but for now just avoid the problem by calling GetTabRect() before creating wxPaintDC instead to ensure that wxPaintDC remains valid while we draw on it. Closes #25700.
... | ... | @@ -183,8 +183,9 @@ protected: |
183 | 183 | void OnEraseBackground(wxEraseEvent& event);
|
184 | 184 | void OnPaint(wxPaintEvent& event);
|
185 | 185 | |
186 | - // Paint the notebook ourselves on the provided DC.
|
|
187 | - void MSWNotebookPaint(wxDC& dc);
|
|
186 | + // Paint the notebook ourselves using wxPaintDC (so this can be only called
|
|
187 | + // from wxEVT_PAINT handler).
|
|
188 | + void MSWNotebookPaint();
|
|
188 | 189 | |
189 | 190 | |
190 | 191 | // true if we have already subclassed our updown control
|
... | ... | @@ -1255,8 +1255,17 @@ DrawNotebookTab(wxWindow* win, |
1255 | 1255 | |
1256 | 1256 | } // anonymous namespace
|
1257 | 1257 | |
1258 | -void wxNotebook::MSWNotebookPaint(wxDC& dc)
|
|
1258 | +void wxNotebook::MSWNotebookPaint()
|
|
1259 | 1259 | {
|
1260 | + // This is tricky: GetTabRect() may result in a nested WM_PAINT when the
|
|
1261 | + // native control decides to generate it from its Tab_CalcPaintMetrics()
|
|
1262 | + // for some reason (this happens at least when using multiple tab rows), so
|
|
1263 | + // we need to call it before creating wxPaintDC as otherwise the current
|
|
1264 | + // paint DC would be invalidated by EndPaint() while we use it, see #25700.
|
|
1265 | + wxRect rectTabArea = GetTabRect(0);
|
|
1266 | + |
|
1267 | + // Now create and use the DC.
|
|
1268 | + wxPaintDC dc(this);
|
|
1260 | 1269 | dc.Clear();
|
1261 | 1270 | |
1262 | 1271 | const wxDirection tabOrient = GetTabOrientation();
|
... | ... | @@ -1282,7 +1291,6 @@ void wxNotebook::MSWNotebookPaint(wxDC& dc) |
1282 | 1291 | return;
|
1283 | 1292 | |
1284 | 1293 | // Start by erasing the tabs area background.
|
1285 | - wxRect rectTabArea = GetTabRect(0);
|
|
1286 | 1294 | rectTabArea = ExpandSelectedTab(rectTabArea, tabOrient);
|
1287 | 1295 | if ( tabOrient == wxTOP || tabOrient == wxBOTTOM )
|
1288 | 1296 | rectTabArea.SetRight(sizeWindow.x);
|
... | ... | @@ -1370,16 +1378,16 @@ void wxNotebook::OnPaint(wxPaintEvent& event) |
1370 | 1378 | return;
|
1371 | 1379 | }
|
1372 | 1380 | |
1373 | - wxPaintDC dc(this);
|
|
1374 | - |
|
1375 | 1381 | if ( wxMSWDarkMode::IsActive() )
|
1376 | 1382 | {
|
1377 | 1383 | // We can't use default painting in dark mode, it just doesn't work
|
1378 | 1384 | // there, whichever theme we use, so draw everything ourselves.
|
1379 | - MSWNotebookPaint(dc);
|
|
1385 | + MSWNotebookPaint();
|
|
1380 | 1386 | return;
|
1381 | 1387 | }
|
1382 | 1388 | |
1389 | + wxPaintDC dc(this);
|
|
1390 | + |
|
1383 | 1391 | RECT rc;
|
1384 | 1392 | ::GetClientRect(GetHwnd(), &rc);
|
1385 | 1393 | if ( !rc.right || !rc.bottom )
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help