diff --git a/include/wx/generic/panelg.h b/include/wx/generic/panelg.h index 5824c0efc4..4aa4c8c988 100644 --- a/include/wx/generic/panelg.h +++ b/include/wx/generic/panelg.h @@ -76,6 +76,20 @@ public: virtual bool IsCanvasWindow() const { return true; } #endif +#ifdef __WXMSW__ + // This is a hack to support inheriting of background through child + // wxPanel: at least wxNotebook needs this under wxMSW as its background + // should apply to its children which are usually wxPanels which normally + // don't have a transparent background. Calling this function allows to + // change this for the panels which are used as notebook pages. + void MSWSetTransparentBackground(bool isTransparent = true) + { + m_isTransparent = isTransparent; + } + + virtual bool HasTransparentBackground() { return m_isTransparent; } +#endif // __WXMSW__ + WX_DECLARE_CONTROL_CONTAINER(); protected: @@ -85,6 +99,11 @@ protected: // choose the default border for this window virtual wxBorder GetDefaultBorder() const { return wxWindowBase::GetDefaultBorder(); } +private: +#ifdef __WXMSW__ + bool m_isTransparent; +#endif // __WXMSW__ + DECLARE_DYNAMIC_CLASS_NO_COPY(wxPanel) DECLARE_EVENT_TABLE() }; diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 96b6d1bbe6..33b4354107 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -395,16 +395,16 @@ public: // the hDC parameter is the DC background will be drawn on, it can be used // to call SetBrushOrgEx() on it if the returned brush is a bitmap one // - // child parameter is never NULL + // child parameter is never NULL, it can be this window itself or one of + // its (grand)children // // the base class version returns a solid brush if we have a non default // background colour or 0 otherwise virtual WXHBRUSH MSWGetBgBrushForChild(WXHDC hDC, wxWindowMSW *child); // return the background brush to use for painting the given window by - // quering the parent windows via their MSWGetBgBrushForChild() recursively - WXHBRUSH MSWGetBgBrush(WXHDC hDC) { return MSWGetBgBrush(hDC, this); } - WXHBRUSH MSWGetBgBrush(WXHDC hDC, wxWindowMSW *child); + // querying the parent windows via MSWGetBgBrushForChild() recursively + WXHBRUSH MSWGetBgBrush(WXHDC hDC); enum MSWThemeColour { diff --git a/samples/widgets/widgets.cpp b/samples/widgets/widgets.cpp index 53a7b37016..d71656dd40 100644 --- a/samples/widgets/widgets.cpp +++ b/samples/widgets/widgets.cpp @@ -75,6 +75,7 @@ enum #endif // wxUSE_TOOLTIPS Widgets_SetFgColour, Widgets_SetBgColour, + Widgets_SetPageBg, Widgets_SetFont, Widgets_Enable, @@ -159,6 +160,7 @@ protected: #endif // wxUSE_TOOLTIPS void OnSetFgCol(wxCommandEvent& event); void OnSetBgCol(wxCommandEvent& event); + void OnSetPageBg(wxCommandEvent& event); void OnSetFont(wxCommandEvent& event); void OnEnable(wxCommandEvent& event); void OnSetBorder(wxCommandEvent& event); @@ -285,6 +287,7 @@ BEGIN_EVENT_TABLE(WidgetsFrame, wxFrame) EVT_MENU(Widgets_SetFgColour, WidgetsFrame::OnSetFgCol) EVT_MENU(Widgets_SetBgColour, WidgetsFrame::OnSetBgCol) + EVT_MENU(Widgets_SetPageBg, WidgetsFrame::OnSetPageBg) EVT_MENU(Widgets_SetFont, WidgetsFrame::OnSetFont) EVT_MENU(Widgets_Enable, WidgetsFrame::OnEnable) @@ -381,6 +384,7 @@ WidgetsFrame::WidgetsFrame(const wxString& title) #endif // wxUSE_TOOLTIPS menuWidget->Append(Widgets_SetFgColour, wxT("Set &foreground...\tCtrl-F")); menuWidget->Append(Widgets_SetBgColour, wxT("Set &background...\tCtrl-B")); + menuWidget->Append(Widgets_SetPageBg, wxT("Set &page background...\tShift-Ctrl-B")); menuWidget->Append(Widgets_SetFont, wxT("Set f&ont...\tCtrl-O")); menuWidget->AppendCheckItem(Widgets_Enable, wxT("&Enable/disable\tCtrl-E")); @@ -766,16 +770,35 @@ void WidgetsFrame::OnSetTooltip(wxCommandEvent& WXUNUSED(event)) #endif // wxUSE_TOOLTIPS -void WidgetsFrame::OnSetFgCol(wxCommandEvent& WXUNUSED(event)) +namespace +{ + +// Trivial wrapper for wxGetColourFromUser() which also does something even if +// the colour dialog is not available in the current build (which may happen +// for the ports in development and it is still useful to see how colours work) +wxColour GetColourFromUser(wxWindow *parent, const wxColour& colDefault) { #if wxUSE_COLOURDLG + return wxGetColourFromUser(parent, colDefault); +#else // !wxUSE_COLOURDLG + if ( colDefault == *wxBLACK ) + return *wxWHITE; + else + return *wxBLACK; +#endif // wxUSE_COLOURDLG/!wxUSE_COLOURDLG +} + +} // anonymous namespace + +void WidgetsFrame::OnSetFgCol(wxCommandEvent& WXUNUSED(event)) +{ // allow for debugging the default colour the first time this is called WidgetsPage *page = CurrentPage(); if (!m_colFg.Ok()) m_colFg = page->GetForegroundColour(); - wxColour col = wxGetColourFromUser(this, m_colFg); + wxColour col = GetColourFromUser(this, m_colFg); if ( !col.Ok() ) return; @@ -789,20 +812,16 @@ void WidgetsFrame::OnSetFgCol(wxCommandEvent& WXUNUSED(event)) (*it)->SetForegroundColour(m_colFg); (*it)->Refresh(); } -#else - wxLogMessage(wxT("Colour selection dialog not available in current build.")); -#endif } void WidgetsFrame::OnSetBgCol(wxCommandEvent& WXUNUSED(event)) { -#if wxUSE_COLOURDLG WidgetsPage *page = CurrentPage(); if ( !m_colBg.Ok() ) m_colBg = page->GetBackgroundColour(); - wxColour col = wxGetColourFromUser(this, m_colBg); + wxColour col = GetColourFromUser(this, m_colBg); if ( !col.Ok() ) return; @@ -816,9 +835,16 @@ void WidgetsFrame::OnSetBgCol(wxCommandEvent& WXUNUSED(event)) (*it)->SetBackgroundColour(m_colBg); (*it)->Refresh(); } -#else - wxLogMessage(wxT("Colour selection dialog not available in current build.")); -#endif +} + +void WidgetsFrame::OnSetPageBg(wxCommandEvent& WXUNUSED(event)) +{ + wxColour col = GetColourFromUser(this, GetBackgroundColour()); + if ( !col.Ok() ) + return; + + CurrentPage()->SetBackgroundColour(col); + CurrentPage()->Refresh(); } void WidgetsFrame::OnSetFont(wxCommandEvent& WXUNUSED(event)) diff --git a/src/generic/panelg.cpp b/src/generic/panelg.cpp index 3bff49d8d7..ee4a901a06 100644 --- a/src/generic/panelg.cpp +++ b/src/generic/panelg.cpp @@ -104,6 +104,10 @@ WX_DELEGATE_TO_CONTROL_CONTAINER(wxPanel, wxWindow) void wxPanel::Init() { WX_INIT_CONTROL_CONTAINER(); + +#ifdef __WXMSW__ + m_isTransparent = false; +#endif // __WXMSW__ } bool wxPanel::Create(wxWindow *parent, wxWindowID id, diff --git a/src/msw/control.cpp b/src/msw/control.cpp index 1cc9dce77e..056794b517 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -368,7 +368,7 @@ WXHBRUSH wxControl::DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd) if ( !colBg.Ok() ) { if ( wxWindow *win = wxFindWinFromHandle(hWnd) ) - hbr = MSWGetBgBrush(pDC, win); + hbr = win->MSWGetBgBrush(pDC); // if the control doesn't have any bg colour, foreground colour will be // ignored as the return value would be 0 -- so forcefully give it a diff --git a/src/msw/notebook.cpp b/src/msw/notebook.cpp index 7148d34139..793d0dd8d7 100644 --- a/src/msw/notebook.cpp +++ b/src/msw/notebook.cpp @@ -818,6 +818,14 @@ bool wxNotebook::InsertPage(size_t nPage, // succeeded: save the pointer to the page m_pages.Insert(pPage, nPage); + // also ensure that the notebook background is used for its pages by making + // them transparent: this ensures that MSWGetBgBrush() queries the notebook + // for the background brush to be used for erasing them + if ( wxPanel *panel = wxDynamicCast(pPage, wxPanel) ) + { + panel->MSWSetTransparentBackground(); + } + // we may need to adjust the size again if the notebook size changed: // normally this only happens for the first page we add (the tabs which // hadn't been there before are now shown) but for a multiline notebook it @@ -1252,23 +1260,7 @@ void wxNotebook::UpdateBgBrush() WXHBRUSH wxNotebook::MSWGetBgBrushForChild(WXHDC hDC, wxWindow *child) { - // Only apply to notebook pages and transparent children, see - // wxWindow::MSWGetBgBrushForChild() for explanation - bool shouldApply; - if ( child->GetParent() == this ) - { - // notebook page -- apply background - shouldApply = true; - } - else - { - // controls in a notebook page with transparent background should - // be handled too - shouldApply = child->HasTransparentBackground() && - child->GetParent()->GetParent() == this; - } - - if ( m_hbrBackground && shouldApply ) + if ( m_hbrBackground ) { // before drawing with the background brush, we need to position it // correctly diff --git a/src/msw/statbox.cpp b/src/msw/statbox.cpp index 0a5b78abd2..3c2dfcf06d 100644 --- a/src/msw/statbox.cpp +++ b/src/msw/statbox.cpp @@ -363,16 +363,15 @@ void wxStaticBox::PaintBackground(wxDC& dc, const RECT& rc) // we did it // 3. this is backwards compatible behaviour and some people rely on it, // see http://groups.google.com/groups?selm=4252E932.3080801%40able.es - wxWindow *parent = GetParent(); wxMSWDCImpl *impl = (wxMSWDCImpl*) dc.GetImpl(); - HBRUSH hbr = (HBRUSH)parent->MSWGetBgBrush(impl->GetHDC(), this); + HBRUSH hbr = MSWGetBgBrush(impl->GetHDC()); // if there is no special brush for painting this control, just use the // solid background colour wxBrush brush; if ( !hbr ) { - brush = wxBrush(parent->GetBackgroundColour()); + brush = wxBrush(GetParent()->GetBackgroundColour()); hbr = GetHbrushOf(brush); } diff --git a/src/msw/window.cpp b/src/msw/window.cpp index b747396699..4767df4088 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -4916,42 +4916,32 @@ bool wxWindowMSW::DoEraseBackground(WXHDC hDC) } WXHBRUSH -wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), wxWindowMSW *child) +wxWindowMSW::MSWGetBgBrushForChild(WXHDC WXUNUSED(hDC), + wxWindowMSW * WXUNUSED(child)) { if ( m_hasBgCol ) { - // our background colour applies to: - // 1. this window itself, always - // 2. all children unless the colour is "not inheritable" - // 3. even if it is not inheritable, our immediate transparent - // children should still inherit it -- but not any transparent - // children because it would look wrong if a child of non - // transparent child would show our bg colour when the child itself - // does not - if ( child == this || - m_inheritBgCol || - (child->HasTransparentBackground() && - child->GetParent() == this) ) - { - // draw children with the same colour as the parent - wxBrush * - brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour()); + wxBrush * + brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour()); - return (WXHBRUSH)GetHbrushOf(*brush); - } + return (WXHBRUSH)GetHbrushOf(*brush); } return 0; } -WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC, wxWindowMSW *child) +WXHBRUSH wxWindowMSW::MSWGetBgBrush(WXHDC hDC) { for ( wxWindowMSW *win = this; win; win = win->GetParent() ) { - WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, child); + WXHBRUSH hBrush = win->MSWGetBgBrushForChild(hDC, this); if ( hBrush ) return hBrush; + // don't use the parent background if we're not transparent + if ( !win->HasTransparentBackground() ) + break; + // background is not inherited beyond top level windows if ( win->IsTopLevel() ) break;