From 169fb2c7f5994d883eea4fb7a82bd711ff025aaf Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 8 Apr 2016 22:15:56 +0200 Subject: [PATCH 1/3] Fix background for children of windows with RTL layout in wxMSW To correctly compute the brush origin offset for painting background of a child in a window using RTL layout, we need to offset it by the child origin i.e. its _right_ top corner in this case and not the left top corner as we did before. Conveniently, although not very explicitly, MapWindowPoints() already takes care of this for us if we just pass it both the left and right points, but we wrongly passed it only a single one, so it couldn't work its magic in this case. Change this to fix the drawing artefacts which appeared over wxNotebook children with transparent background (e.g. wxStaticText) due to the use of wrong origin before. --- src/msw/window.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 01c9d59584..5be1dbca19 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -4888,7 +4888,13 @@ wxWindowMSW::MSWGetBgBrushForChild(WXHDC hDC, wxWindowMSW *child) RECT rc; ::GetWindowRect(GetHwndOf(child), &rc); - ::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 1); + // It is important to pass both points to MapWindowPoints() as in + // addition to converting them to our coordinate system, this function + // will also exchange the left and right coordinates if this window + // uses RTL layout, which is exactly what we need here as the child + // window origin is its _right_ top corner in this case and not the + // left one. + ::MapWindowPoints(NULL, GetHwnd(), (POINT *)&rc, 2); int x = rc.left, y = rc.top; From 0487a3d3f175398862bb780523aeee7f24bc645c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 8 Apr 2016 23:11:46 +0200 Subject: [PATCH 2/3] Use correct size for the notebook background bitmap in wxMSW Using "r.x + r.width" didn't really make much sense, it just happened to be close enough to the real value to not create any problems when using LTR layout, but was wrong in RTL, resulting in visible vertical line being visible in the notebook client area. Fix this using the same GetThemeBackgroundExtent() for determining the bitmap size as is used for drawing over it. --- src/msw/notebook.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 67e5fa2f7f..1773587820 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -1151,9 +1151,26 @@ WXHBRUSH wxNotebook::QueryBgBitmap() if ( r.IsEmpty() ) return 0; + wxUxThemeHandle theme(this, L"TAB"); + if ( !theme ) + return 0; + + RECT rc; + wxCopyRectToRECT(r, rc); + WindowHDC hDC(GetHwnd()); + wxUxThemeEngine::Get()->GetThemeBackgroundExtent + ( + theme, + (HDC) hDC, + 9 /* TABP_PANE */, + 0, + &rc, + &rc + ); + MemoryHDC hDCMem(hDC); - CompatibleBitmap hBmp(hDC, r.x + r.width, r.y + r.height); + CompatibleBitmap hBmp(hDC, rc.right, rc.bottom); SelectInHDC selectBmp(hDCMem, hBmp); From eed5700a078dea111380ec3fc4ecadf5ed8ae457 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 10 Apr 2016 20:49:36 +0200 Subject: [PATCH 3/3] Refactor: remove wxNotebook::DoDrawBackground() in wxMSW The code in QueryBgBitmap() and MSWPrintChild() is sufficiently different that we can't easily reuse the drawing calls between them, so don't tie ourselves in knots trying to do it, just duplicating these 2 calls in the 2 functions is not that bad and the code is more clear. No real changes. --- include/wx/msw/notebook.h | 5 -- src/msw/notebook.cpp | 111 +++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 66 deletions(-) diff --git a/include/wx/msw/notebook.h b/include/wx/msw/notebook.h index 64d6bfc5d4..6e0ee3af01 100644 --- a/include/wx/msw/notebook.h +++ b/include/wx/msw/notebook.h @@ -178,11 +178,6 @@ protected: // creates the brush to be used for drawing the tab control background void UpdateBgBrush(); - - // common part of QueryBgBitmap() and MSWPrintChild() - // - // if child == NULL, draw background for the entire notebook itself - bool DoDrawBackground(WXHDC hDC, wxWindow *child = NULL); #endif // wxUSE_UXTHEME // these function are used for reducing flicker on notebook resize diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 1773587820..ce5c20016c 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -1102,49 +1102,6 @@ void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event) #if wxUSE_UXTHEME -bool wxNotebook::DoDrawBackground(WXHDC hDC, wxWindow *child) -{ - wxUxThemeHandle theme(child ? child : this, L"TAB"); - if ( !theme ) - return false; - - // get the notebook client rect (we're not interested in drawing tabs - // themselves) - wxRect r = GetPageSize(); - if ( r.IsEmpty() ) - return false; - - RECT rc; - wxCopyRectToRECT(r, rc); - - // map rect to the coords of the window we're drawing in - if ( child ) - ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2); - - // we have the content area (page size), but we need to draw all of the - // background for it to be aligned correctly - wxUxThemeEngine::Get()->GetThemeBackgroundExtent - ( - theme, - (HDC) hDC, - 9 /* TABP_PANE */, - 0, - &rc, - &rc - ); - wxUxThemeEngine::Get()->DrawThemeBackground - ( - theme, - (HDC) hDC, - 9 /* TABP_PANE */, - 0, - &rc, - NULL - ); - - return true; -} - WXHBRUSH wxNotebook::QueryBgBitmap() { wxRect r = GetPageSize(); @@ -1172,10 +1129,18 @@ WXHBRUSH wxNotebook::QueryBgBitmap() MemoryHDC hDCMem(hDC); CompatibleBitmap hBmp(hDC, rc.right, rc.bottom); - SelectInHDC selectBmp(hDCMem, hBmp); - - if ( !DoDrawBackground((WXHDC)(HDC)hDCMem) ) - return 0; + { + SelectInHDC selectBmp(hDCMem, hBmp); + wxUxThemeEngine::Get()->DrawThemeBackground + ( + theme, + hDCMem, + 9 /* TABP_PANE */, + 0, + &rc, + NULL + ); + } // deselect bitmap from the memory HDC before using it return (WXHBRUSH)::CreatePatternBrush(hBmp); } @@ -1197,25 +1162,21 @@ void wxNotebook::UpdateBgBrush() bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child) { - // solid background colour overrides themed background drawing - if ( !UseBgCol() && DoDrawBackground(hDC, child) ) - return true; + const wxRect r = GetPageSize(); + if ( r.IsEmpty() ) + return false; + + RECT rc; + wxCopyRectToRECT(r, rc); + + // map rect to the coords of the window we're drawing in + if ( child ) + ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2); // If we're using a solid colour (for example if we've switched off // theming for this notebook), paint it if (UseBgCol()) { - wxRect r = GetPageSize(); - if ( r.IsEmpty() ) - return false; - - RECT rc; - wxCopyRectToRECT(r, rc); - - // map rect to the coords of the window we're drawing in - if ( child ) - ::MapWindowPoints(GetHwnd(), GetHwndOf(child), (POINT *)&rc, 2); - wxBrush brush(GetBackgroundColour()); HBRUSH hbr = GetHbrushOf(brush); @@ -1223,6 +1184,34 @@ bool wxNotebook::MSWPrintChild(WXHDC hDC, wxWindow *child) return true; } + else // No solid background colour, try to use themed background. + { + wxUxThemeHandle theme(child, L"TAB"); + if ( theme ) + { + // we have the content area (page size), but we need to draw all of the + // background for it to be aligned correctly + wxUxThemeEngine::Get()->GetThemeBackgroundExtent + ( + theme, + (HDC) hDC, + 9 /* TABP_PANE */, + 0, + &rc, + &rc + ); + wxUxThemeEngine::Get()->DrawThemeBackground + ( + theme, + (HDC) hDC, + 9 /* TABP_PANE */, + 0, + &rc, + NULL + ); + return true; + } + } return wxNotebookBase::MSWPrintChild(hDC, child); }