Simplify and correct MSW selection of background brush for children painting.
Check for the transparency of the window background in MSWGetBgBrush() itself and let MSWGetBgBrushForChild() just return the brush to be used. This required adding a MSW-specific hack to wxPanel to allow inheriting background of wxNotebook by its children which is slightly ugly but is exactly what we need to do in this case and makes the rest of the code much simpler. Also add a possibility to set the background of the page containing the control being tested to the widgets sample to test for background inheritance. This shows problems with wxSlider and wxRadioBox backgrounds but they're not new with this patch. Closes #12057. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64372 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -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()
|
||||
};
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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))
|
||||
|
@@ -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,
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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());
|
||||
|
||||
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;
|
||||
|
Reference in New Issue
Block a user