IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
#endif
-BEGIN_EVENT_TABLE(wxStaticBox, wxControl)
- EVT_PAINT(wxStaticBox::OnPaint)
-END_EVENT_TABLE()
-
// ============================================================================
// implementation
// ============================================================================
if ( !MSWCreateControl(wxT("BUTTON"), label, pos, size) )
return false;
+#ifndef __WXWINCE__
+ Connect(wxEVT_PAINT, wxPaintEventHandler(wxStaticBox::OnPaint));
+#endif
+
return true;
}
+wxBorder wxStaticBox::GetDefaultBorder() const
+{
+ return wxBORDER_NONE;
+}
+
WXDWORD wxStaticBox::MSWGetStyle(long style, WXDWORD *exstyle) const
{
long styleWin = wxStaticBoxBase::MSWGetStyle(style, exstyle);
{
wxStaticBoxBase::GetBordersForSizer(borderTop, borderOther);
- // if not using correct (but backwards cojmpatible) text metrics
- // calculations, we need to add some extra margin or otherwise static box
- // title is clipped
-#if !wxDIALOG_UNIT_COMPATIBILITY
- if ( !GetLabel().empty() )
- *borderTop += GetCharHeight()/3;
-#endif // !wxDIALOG_UNIT_COMPATIBILITY
+ // need extra space, don't know how much but this seems to be enough
+ *borderTop += GetCharHeight()/3;
}
-// rc must be in client coords!
-void wxStaticBox::MSWClipBoxRegion(WXHRGN hrgn, const WXRECTPTR rc)
+// MSWGetRegionWithoutSelf helper: removes the given rectangle from region
+static inline void
+SubtractRectFromRgn(HRGN hrgn, int left, int top, int right, int bottom)
{
- HRGN hrgnchild;
+ AutoHRGN hrgnRect(::CreateRectRgn(left, top, right, bottom));
+ if ( !hrgnRect )
+ {
+ wxLogLastError(_T("CreateRectRgn()"));
+ return;
+ }
+
+ ::CombineRgn(hrgn, hrgn, hrgnRect, RGN_DIFF);
+}
+
+void wxStaticBox::MSWGetRegionWithoutSelf(WXHRGN hRgn, int w, int h)
+{
+ HRGN hrgn = (HRGN)hRgn;
+
+ // remove the area occupied by the static box borders from the region
+ int borderTop, border;
+ GetBordersForSizer(&borderTop, &border);
// top
- hrgnchild = ::CreateRectRgn(0, 0, ((const RECT*) rc)->right, 14);
- ::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
- ::DeleteObject(hrgnchild);
+ SubtractRectFromRgn(hrgn, 0, 0, w, borderTop);
// bottom
- hrgnchild = ::CreateRectRgn(0, ((const RECT*) rc)->bottom - 7, ((const RECT*) rc)->right, ((const RECT*) rc)->bottom);
- ::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
- ::DeleteObject(hrgnchild);
+ SubtractRectFromRgn(hrgn, 0, h - border, w, h);
// left
- hrgnchild = ::CreateRectRgn(0, 0, 7, ((const RECT*) rc)->bottom);
- ::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
- ::DeleteObject(hrgnchild);
+ SubtractRectFromRgn(hrgn, 0, 0, border, h);
// right
- hrgnchild = ::CreateRectRgn(((const RECT*) rc)->right - 7, 0, ((const RECT*) rc)->right, ((const RECT*) rc)->bottom);
- ::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
- ::DeleteObject(hrgnchild);
+ SubtractRectFromRgn(hrgn, w - border, 0, w, h);
}
-WXHRGN wxStaticBox::MSWCalculateClippingRegion()
+WXHRGN wxStaticBox::MSWGetRegionWithoutChildren()
{
RECT rc;
::GetWindowRect(GetHwnd(), &rc);
HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
- wxWindowList::compatibility_iterator node = GetParent()->GetChildren().GetFirst();
- while ( node )
+ // iterate over all child windows (not just wxWindows but all windows)
+ for ( HWND child = ::GetWindow(GetHwndOf(GetParent()), GW_CHILD);
+ child;
+ child = ::GetWindow(child, GW_HWNDNEXT) )
{
- wxWindow *child = node->GetData();
+ wxWindow *childWindow = wxGetWindowFromHWND((WXHWND) child);
// can't just test for (this != child) here since if a wxStaticBox
// overlaps another wxStaticBox then neither are drawn. The overlapping
// region will flicker but we shouldn't have overlapping windows anyway.
- if ( !child->IsKindOf(CLASSINFO(wxStaticBox)) )
+ if ( !childWindow || !wxDynamicCast(childWindow, wxStaticBox) )
{
- ::GetWindowRect(GetHwndOf(child), &rc);
- if ( RectInRegion(hrgn, &rc) )
+ ::GetWindowRect(child, &rc);
+ if ( ::RectInRegion(hrgn, &rc) )
{
// need to remove WS_CLIPSIBLINGS from all sibling windows
// that are within this staticbox if set
- LONG style = ::GetWindowLong(GetHwndOf(child), GWL_STYLE);
+ LONG style = ::GetWindowLong(child, GWL_STYLE);
if ( style & WS_CLIPSIBLINGS )
{
style &= ~WS_CLIPSIBLINGS;
- ::SetWindowLong(GetHwndOf(child), GWL_STYLE, style);
+ ::SetWindowLong(child, GWL_STYLE, style);
// MSDN: "If you have changed certain window data using
// SetWindowLong, you must call SetWindowPos to have the
// changes take effect."
- ::SetWindowPos(GetHwndOf(child), NULL, 0, 0, 0, 0,
+ ::SetWindowPos(child, NULL, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_FRAMECHANGED);
}
- HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
- ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
- ::DeleteObject(hrgnchild);
+ AutoHRGN hrgnChild(::CreateRectRgnIndirect(&rc));
+ ::CombineRgn(hrgn, hrgn, hrgnChild, RGN_DIFF);
}
}
+ }
+
+ return (WXHRGN)hrgn;
+}
- node = node->GetNext();
+// helper for OnPaint()
+void wxStaticBox::PaintBackground(wxDC& dc, const RECT& rc)
+{
+ // note that static box should be transparent, so it should show its
+ // parents colour, not its own
+ wxWindow * const parent = GetParent();
+
+ HBRUSH hbr = (HBRUSH)parent->MSWGetBgBrush(dc.GetHDC());
+ if ( !hbr )
+ {
+ wxBrush *brush =
+ wxTheBrushList->FindOrCreateBrush(parent->GetBackgroundColour());
+ if ( brush )
+ hbr = GetHbrushOf(*brush);
}
- ::GetWindowRect(GetHwnd(), &rc);
- ::OffsetRgn(hrgn, -rc.left, -rc.top);
- return hrgn;
+ if ( hbr )
+ ::FillRect(GetHdcOf(dc), &rc, hbr);
}
void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
RECT rc;
::GetClientRect(GetHwnd(), &rc);
- // paint the actual box
+ // draw the entire box in a memory DC, but only blit the bits not redrawn
+ // either by our children windows nor by FillRect() painting the background
+ // below
wxMemoryDC memdc;
wxBitmap bitmap(rc.right, rc.bottom);
memdc.SelectObject(bitmap);
- // get bg brush
- WXHBRUSH hbr = DoMSWControlColor(GetHdcOf(memdc), wxNullColour);
- if ( !hbr )
- {
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
- hbr = (WXHBRUSH)brush->GetResourceHandle();
- }
-
- // draw solid box, but only blit the good bits
- ::FillRect(GetHdcOf(memdc), &rc, (HBRUSH)hbr);
+ PaintBackground(memdc, rc);
MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(memdc), 0);
+ int borderTop, border;
+ GetBordersForSizer(&borderTop, &border);
+
// top
- dc.Blit(7, 0, rc.right - 7, 14, &memdc, 7, 0);
+ dc.Blit(border, 0, rc.right - border, borderTop,
+ &memdc, border, 0);
// bottom
- dc.Blit(7, rc.bottom - 7, rc.right - 7, rc.bottom, &memdc, 7, rc.bottom - 7);
+ dc.Blit(border, rc.bottom - border, rc.right - border, rc.bottom,
+ &memdc, border, rc.bottom - border);
// left
- dc.Blit(0, 0, 7, rc.bottom, &memdc, 0, 0);
+ dc.Blit(0, 0, border, rc.bottom,
+ &memdc, 0, 0);
// right
- dc.Blit(rc.right - 7, 0, rc.right, rc.bottom, &memdc, rc.right - 7, 0);
+ dc.Blit(rc.right - border, 0, rc.right, rc.bottom,
+ &memdc, rc.right - border, 0);
- // paint the inner
- HRGN hrgn = (HRGN)MSWCalculateClippingRegion();
- // now remove the box itself
- MSWClipBoxRegion((WXHRGN) hrgn, (const WXRECTPTR) &rc);
+ AutoHRGN hrgn((HRGN)MSWGetRegionWithoutChildren());
+ RECT rcWin;
+ ::GetWindowRect(GetHwnd(), &rcWin);
+ ::OffsetRgn(hrgn, -rcWin.left, -rcWin.top);
- hbr = DoMSWControlColor(GetHdcOf(dc), wxNullColour);
- if ( !hbr )
- {
- wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
- hbr = (WXHBRUSH)brush->GetResourceHandle();
- }
+ // now remove the box itself
+ MSWGetRegionWithoutSelf((WXHRGN) hrgn, rc.right, rc.bottom);
+
+ // and paint the inside of the box (excluding child controls)
::SelectClipRgn(GetHdcOf(dc), hrgn);
- ::FillRect(GetHdcOf(dc), &rc, (HBRUSH)hbr);
+ PaintBackground(dc, rc);
::SelectClipRgn(GetHdcOf(dc), NULL);
- ::DeleteObject(hrgn);
}
#endif // wxUSE_STATBOX