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
This commit is contained in:
Vadim Zeitlin 2013-07-13 23:23:08 +00:00
parent 7527fdaac8
commit b8d8362ca0

View File

@ -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,25 +842,74 @@ 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;
switch ( GetWindowStyle() & wxBK_ALIGN_MASK )
{
case wxBK_TOP:
x = rc.right - 2;
y = 2;
break;
case wxBK_BOTTOM:
x = rc.right - 2;
y = rc.bottom - 2;
break;
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);
}
wxMSWDCImpl *impl = (wxMSWDCImpl*) memdc.GetImpl();
::FillRect(GetHdcOf(*impl), &rc, hbr);
MSWDefWindowProc(WM_PAINT, (WPARAM)(impl->GetHDC()), 0);
// For some reason in RTL mode, source offset has to be -1, otherwise the
// right border (physical) remains unpainted.
const wxCoord ofs = dir == wxLayout_RightToLeft ? -1 : 0;