From b8d8362ca0727454ebe8a83358c2a3103b09df20 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 13 Jul 2013 23:23:08 +0000 Subject: [PATCH] Use wxNotebook background colour for the tab row background in wxMSW. The free space near the tabs was always filled with the default light grey colour, use wxNotebook background colour itself to fill it now. Do it by changing the code in wxNotebook::OnPaint() to use the background colour brush and ExtFloodFill() to paint over the default grey, instead of the patterned background brush which is supposed to be used for the pages area only and not for the tabs and which was not even taken into account anyhow as the default window proc erases the entire contents of the DC we pass to it anyhow (at least in the default top-aligned tabs case). Also inherit the background colour from parent by default now, this ensures that wxNotebook blends with its parent when its background colour has been explicitly set by default, without the need to call its SetBackgroundColour() explicitly. See #13745. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74505 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/msw/notebook.cpp | 84 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 14 deletions(-) diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 6b171c7a74..7a5bf36c59 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -254,6 +254,13 @@ bool wxNotebook::Create(wxWindow *parent, if ( !MSWCreateControl(className, wxEmptyString, pos, size) ) return false; + // Inherit parent attributes and, unlike the default, also inherit the + // parent background colour in order to blend in with its background if + // it's set to a non-default value. + InheritAttributes(); + if ( parent->InheritsBackgroundColour() && !UseBgCol() ) + SetBackgroundColour(parent->GetBackgroundColour()); + #if wxUSE_UXTHEME if ( HasFlag(wxNB_NOPAGETHEME) || wxSystemOptions::IsFalse(wxT("msw.notebook.themed-background")) ) @@ -835,24 +842,73 @@ void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event)) const wxLayoutDirection dir = dc.GetLayoutDirection(); memdc.SetLayoutDirection(dir); - // if there is no special brush just use the solid background colour -#if wxUSE_UXTHEME - HBRUSH hbr = (HBRUSH)m_hbrBackground; -#else - HBRUSH hbr = 0; -#endif - wxBrush brush; - if ( !hbr ) + const HDC hdc = GetHdcOf(memdc); + + // The drawing logic of the native tab control is absolutely impenetrable + // but observation shows that in the current Windows versions (XP and 7), + // the tab control always erases its entire background in its window proc + // when the tabs are top-aligned but does not do it when the tabs are in + // any other position. + // + // This means that we can't rely on our background colour being used for + // the blank area in the tab row because this doesn't work in the default + // top-aligned case, hence the hack with ExtFloodFill() below. But it also + // means that we still do need to erase the DC to account for the other + // cases. + // + // Moreover, just in case some very old or very new (or even future, + // although it seems unlikely that this is ever going to change by now) + // version of Windows didn't do it like this, do both things in all cases + // instead of optimizing away the one of them which doesn't do anything for + // the effectively used tab orientation -- better safe than fast. + + // Notice that we use our own background here, not the background used for + // the pages, because the tab row background must blend with the parent and + // so the background colour inherited from it (if any) must be used. + AutoHBRUSH hbr(wxColourToRGB(GetBackgroundColour())); + + ::FillRect(hdc, &rc, hbr); + + MSWDefWindowProc(WM_PAINT, (WPARAM)hdc, 0); + + // At least for the top-aligned tabs, our background colour was overwritten + // and so we now replace the default background with our colour. This is + // horribly inefficient, of course, but seems to be the only way to do it. + if ( UseBgCol() ) { - brush = wxBrush(GetBackgroundColour()); - hbr = GetHbrushOf(brush); - } + SelectInHDC selectBrush(hdc, hbr); + + // Find the point which must contain the default background colour: + // this is a hack, of course, but using this point "close" to the + // corner seems to work fine in practice. + int x = 0, + y = 0; - wxMSWDCImpl *impl = (wxMSWDCImpl*) memdc.GetImpl(); + switch ( GetWindowStyle() & wxBK_ALIGN_MASK ) + { + case wxBK_TOP: + x = rc.right - 2; + y = 2; + break; - ::FillRect(GetHdcOf(*impl), &rc, hbr); + case wxBK_BOTTOM: + x = rc.right - 2; + y = rc.bottom - 2; + break; - MSWDefWindowProc(WM_PAINT, (WPARAM)(impl->GetHDC()), 0); + case wxBK_LEFT: + x = 2; + y = rc.bottom - 2; + break; + + case wxBK_RIGHT: + x = 2; + y = rc.bottom - 2; + break; + } + + ::ExtFloodFill(hdc, x, y, ::GetSysColor(COLOR_BTNFACE), FLOODFILLSURFACE); + } // For some reason in RTL mode, source offset has to be -1, otherwise the // right border (physical) remains unpainted. -- 2.45.2