Add support for arbitrary window labels in wxStaticBox to wxMSW

Just reparent the label window and position it accordingly and, also,
avoid painting over it in MSW-specific code.
This commit is contained in:
Vadim Zeitlin
2017-12-24 20:07:05 +01:00
parent 36c4b7651e
commit 687192d86a
3 changed files with 83 additions and 5 deletions

View File

@@ -27,6 +27,16 @@ public:
Create(parent, id, label, pos, size, style, name); Create(parent, id, label, pos, size, style, name);
} }
wxStaticBox(wxWindow* parent, wxWindowID id,
wxWindow* label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString &name = wxStaticBoxNameStr)
{
Create(parent, id, label, pos, size, style, name);
}
bool Create(wxWindow *parent, wxWindowID id, bool Create(wxWindow *parent, wxWindowID id,
const wxString& label, const wxString& label,
const wxPoint& pos = wxDefaultPosition, const wxPoint& pos = wxDefaultPosition,
@@ -34,6 +44,13 @@ public:
long style = 0, long style = 0,
const wxString& name = wxStaticBoxNameStr); const wxString& name = wxStaticBoxNameStr);
bool Create(wxWindow *parent, wxWindowID id,
wxWindow* label,
const wxPoint& pos = wxDefaultPosition,
const wxSize& size = wxDefaultSize,
long style = 0,
const wxString& name = wxStaticBoxNameStr);
/// Implementation only /// Implementation only
virtual void GetBordersForSizer(int *borderTop, int *borderOther) const wxOVERRIDE; virtual void GetBordersForSizer(int *borderTop, int *borderOther) const wxOVERRIDE;
@@ -66,5 +83,8 @@ protected:
wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox); wxDECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox);
}; };
// Indicate that we have the ctor overload taking wxWindow as label.
#define wxHAS_WINDOW_LABEL_IN_STATIC_BOX
#endif // _WX_MSW_STATBOX_H_ #endif // _WX_MSW_STATBOX_H_

View File

@@ -111,7 +111,7 @@ public:
} }
@endcode @endcode
Currently this constructor is only available in wxGTK, use Currently this constructor is only available in wxGTK and wxMSW, use
@c wxHAS_WINDOW_LABEL_IN_STATIC_BOX to check whether it can be used at @c wxHAS_WINDOW_LABEL_IN_STATIC_BOX to check whether it can be used at
compile-time. compile-time.

View File

@@ -107,6 +107,27 @@ bool wxStaticBox::Create(wxWindow *parent,
return true; return true;
} }
bool wxStaticBox::Create(wxWindow* parent,
wxWindowID id,
wxWindow* labelWin,
const wxPoint& pos,
const wxSize& size,
long style,
const wxString& name)
{
wxCHECK_MSG( labelWin, false, wxS("Label window can't be null") );
if ( !Create(parent, id, wxString(), pos, size, style, name) )
return false;
m_labelWin = labelWin;
m_labelWin->Reparent(this);
m_labelWin->Move(FromDIP(LABEL_HORZ_OFFSET), 0);
return true;
}
WXDWORD wxStaticBox::MSWGetStyle(long style, WXDWORD *exstyle) const WXDWORD wxStaticBox::MSWGetStyle(long style, WXDWORD *exstyle) const
{ {
long styleWin = wxStaticBoxBase::MSWGetStyle(style, exstyle); long styleWin = wxStaticBoxBase::MSWGetStyle(style, exstyle);
@@ -269,7 +290,21 @@ void wxStaticBox::MSWGetRegionWithoutSelf(WXHRGN hRgn, int w, int h)
GetBordersForSizer(&borderTop, &border); GetBordersForSizer(&borderTop, &border);
// top // top
SubtractRectFromRgn(hrgn, 0, 0, w, borderTop); if ( m_labelWin )
{
// Don't exclude the entire rectangle at the top, we do need to paint
// the background of the gap between the label window and the box
// frame.
const wxRect labelRect = m_labelWin->GetRect();
const int gap = FromDIP(LABEL_HORZ_BORDER);
SubtractRectFromRgn(hrgn, 0, 0, labelRect.GetLeft() - gap, borderTop);
SubtractRectFromRgn(hrgn, labelRect.GetRight() + gap, 0, w, borderTop);
}
else
{
SubtractRectFromRgn(hrgn, 0, 0, w, borderTop);
}
// bottom // bottom
SubtractRectFromRgn(hrgn, 0, h - border, w, h); SubtractRectFromRgn(hrgn, 0, h - border, w, h);
@@ -415,7 +450,7 @@ void wxStaticBox::PaintForeground(wxDC& dc, const RECT&)
// background mode doesn't change anything: the static box def window proc // background mode doesn't change anything: the static box def window proc
// still draws the label in its own colours, so we need to redraw the text // still draws the label in its own colours, so we need to redraw the text
// ourselves if we have a non default fg colour // ourselves if we have a non default fg colour
if ( m_hasFgCol && wxUxThemeEngine::GetIfActive() ) if ( m_hasFgCol && wxUxThemeEngine::GetIfActive() && !m_labelWin )
{ {
// draw over the text in default colour in our colour // draw over the text in default colour in our colour
HDC hdc = GetHdcOf(*impl); HDC hdc = GetHdcOf(*impl);
@@ -535,8 +570,31 @@ void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
GetBordersForSizer(&borderTop, &border); GetBordersForSizer(&borderTop, &border);
// top // top
dc.Blit(border, 0, rc.right - border, borderTop, if ( m_labelWin )
&memdc, border, 0); {
// We also have to exclude the area taken by the label window,
// otherwise there would be flicker when it draws itself on top of it.
const wxRect labelRect = m_labelWin->GetRect();
// We also leave a small border around label window to make it appear
// more similarly to a plain text label.
const int gap = FromDIP(LABEL_HORZ_BORDER);
dc.Blit(border, 0,
labelRect.GetLeft() - gap - border,
borderTop,
&memdc, border, 0);
dc.Blit(labelRect.GetRight() + gap, 0,
rc.right - (labelRect.GetRight() + gap),
borderTop,
&memdc, border, 0);
}
else
{
dc.Blit(border, 0, rc.right - border, borderTop,
&memdc, border, 0);
}
// bottom // bottom
dc.Blit(border, rc.bottom - border, rc.right - border, border, dc.Blit(border, rc.bottom - border, rc.right - border, border,
&memdc, border, rc.bottom - border); &memdc, border, rc.bottom - border);