]> git.saurik.com Git - wxWidgets.git/commitdiff
fixes to static box borders calculations and significant code cleanup (finalizes...
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 2 Apr 2005 01:17:51 +0000 (01:17 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 2 Apr 2005 01:17:51 +0000 (01:17 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33247 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/msw/radiobox.h
include/wx/msw/statbox.h
src/msw/radiobox.cpp
src/msw/statbox.cpp

index 7607e04a40190be2684bf550975089092e8945c0..cb08edafee987bd181bae4d3f77eb1018765c251 100644 (file)
@@ -144,8 +144,11 @@ protected:
                            int sizeFlags = wxSIZE_AUTO);
     virtual wxSize DoGetBestSize() const;
 
-    virtual WXHRGN MSWCalculateClippingRegion();
-    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
+    virtual WXHRGN MSWGetRegionWithoutChildren();
+    virtual WXLRESULT MSWWindowProc(WXUINT nMsg,
+                                    WXWPARAM wParam,
+                                    WXLPARAM lParam);
+
 
     // the buttons we contain
     wxSubwindows *m_radioButtons;
index ae0cd5030e7f7d74f1bf75f2faa8691111508e24..0922fe12eed42c10955b6d6ef641ed379dd40b3f 100644 (file)
@@ -48,12 +48,19 @@ protected:
     virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
     virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
 
-    virtual WXHRGN MSWCalculateClippingRegion();
-    virtual void MSWClipBoxRegion(WXHRGN hrgn, const WXRECTPTR rc);
+    // return the region with all the windows inside this static box excluded
+    virtual WXHRGN MSWGetRegionWithoutChildren();
+
+    // remove the parts which are painted by static box itself from the given
+    // region which is embedded in a rectangle (0, 0)-(w, h)
+    virtual void MSWGetRegionWithoutSelf(WXHRGN hrgn, int w, int h);
+
+    // paint the given rectangle with our background colour
+    void PaintBackground(wxDC& dc, const struct tagRECT& rc);
+
     void OnPaint(wxPaintEvent& event);
 
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox)
-    DECLARE_EVENT_TABLE()
 };
 
 #endif // _WX_MSW_STATBOX_H_
index a6df181a1a5f75d141b8895ffd11c2b34e7ed22f..253c31204d8fbd005032d9aa9c5467e4bfb4f3cc 100644 (file)
@@ -816,25 +816,21 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
     return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
 }
 
-WXHRGN wxRadioBox::MSWCalculateClippingRegion()
+WXHRGN wxRadioBox::MSWGetRegionWithoutChildren()
 {
     RECT rc;
     ::GetWindowRect(GetHwnd(), &rc);
     HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
 
-    size_t count = GetCount();
+    const size_t count = GetCount();
     for ( size_t i = 0; i < count; ++i )
     {
         ::GetWindowRect((*m_radioButtons)[i], &rc);
-        HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
+        AutoHRGN hrgnchild(::CreateRectRgnIndirect(&rc));
         ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
-        ::DeleteObject(hrgnchild);
     }
 
-    ::GetWindowRect(GetHwnd(), &rc);
-    ::OffsetRgn(hrgn, -rc.left, -rc.top);
-
-    return hrgn;
+    return (WXHRGN)hrgn;
 }
 
 WXLRESULT wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
index 77b7a8939cc98ed2554f79f94547c9c5fb3a38f2..deb7761c269ec8e67c6caa86e4caad81a3500594 100644 (file)
@@ -99,10 +99,6 @@ wxCONSTRUCTOR_6( wxStaticBox , wxWindow* , Parent , wxWindowID , Id , wxString ,
 IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
 #endif
 
-BEGIN_EVENT_TABLE(wxStaticBox, wxControl)
-    EVT_PAINT(wxStaticBox::OnPaint)
-END_EVENT_TABLE()
-
 // ============================================================================
 // implementation
 // ============================================================================
@@ -125,6 +121,8 @@ bool wxStaticBox::Create(wxWindow *parent,
     if ( !MSWCreateControl(wxT("BUTTON"), label, pos, size) )
         return false;
 
+    Connect(wxEVT_PAINT, wxPaintEventHandler(wxStaticBox::OnPaint));
+
     return true;
 }
 
@@ -198,58 +196,61 @@ void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
 #endif // !wxDIALOG_UNIT_COMPATIBILITY
 }
 
-// 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)
+{
+    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 hrgnchild;
+    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);
-    
-    wxList hWnds;
-    HWND child = ::GetWindow((HWND) GetParent()->GetHWND(), GW_CHILD);
-    while (child != 0)
-    {
-        hWnds.Append((wxObject*) child);
-        child = ::GetWindow(child, GW_HWNDNEXT);
-    }
-    
-    for (wxNode* node = hWnds.GetFirst(); node; node = node->GetNext())
+
+    // 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) )
     {
-        HWND child = (HWND) node->GetData();
-        wxWindow* childWindow = wxGetWindowFromHWND((WXHWND) child);
+        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 (!childWindow || !childWindow->IsKindOf(CLASSINFO(wxStaticBox)))
+        if ( !childWindow || !wxDynamicCast(childWindow, wxStaticBox) )
         {
             ::GetWindowRect(child, &rc);
-            if ( RectInRegion(hrgn, &rc) )
+            if ( ::RectInRegion(hrgn, &rc) )
             {
                 // need to remove WS_CLIPSIBLINGS from all sibling windows
                 // that are within this staticbox if set
@@ -267,17 +268,29 @@ WXHRGN wxStaticBox::MSWCalculateClippingRegion()
                                    SWP_FRAMECHANGED);
                 }
 
-                HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
-                ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
-                ::DeleteObject(hrgnchild);
+                AutoHRGN hrgnChild(::CreateRectRgnIndirect(&rc));
+                ::CombineRgn(hrgn, hrgn, hrgnChild, RGN_DIFF);
             }
         }
     }
-    
-    ::GetWindowRect(GetHwnd(), &rc);
-    ::OffsetRgn(hrgn, -rc.left, -rc.top);
 
-    return hrgn;
+    return (WXHRGN)hrgn;
+}
+
+// helper for OnPaint()
+void wxStaticBox::PaintBackground(wxDC& dc, const RECT& rc)
+{
+    HBRUSH hbr = (HBRUSH)DoMSWControlColor(GetHdcOf(dc), wxNullColour);
+    if ( !hbr )
+    {
+        wxBrush *
+            brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour());
+        if ( brush )
+            hbr = GetHbrushOf(*brush);
+    }
+
+    if ( hbr )
+        ::FillRect(GetHdcOf(dc), &rc, hbr);
 }
 
 void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
@@ -286,48 +299,45 @@ 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