]> git.saurik.com Git - wxWidgets.git/commitdiff
Applied patch [ 1166587 ] [wxMSW] Removes all flicker from wxStaticBox
authorJulian Smart <julian@anthemion.co.uk>
Wed, 30 Mar 2005 15:30:06 +0000 (15:30 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Wed, 30 Mar 2005 15:30:06 +0000 (15:30 +0000)
By Jamie Gadd

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33178 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/msw/radiobox.h
include/wx/msw/statbox.h
src/msw/radiobox.cpp
src/msw/statbox.cpp

index c90f3bec9471b125f4b11cbc71ce6aebe06abbdb..35563a220a81b87ae710ccc18fd57d3808bc5975 100644 (file)
@@ -13,8 +13,8 @@ All:
 - Added wxTempFileOutputStream by Stas Sergeev.
 - Fixed wxDateTime::SetToWeekDayInSameWeek(Sun, Monday_First).
 - Added WXK_SPECIAL keycodes for special hardware buttons.
-- Fixed bug with wxFile::Seek(-1, wxFromCurrent)
-- Added wxString/C array constructors to wxArrayString
+- Fixed bug with wxFile::Seek(-1, wxFromCurrent).
+- Added wxString/C array constructors to wxArrayString.
 
 All (GUI):
 
@@ -26,29 +26,31 @@ All (GUI):
 - Restored ability to set a custom splitter sash size with SetSashSize.
 - Fixed wxScrolledWindow sizer behaviour so that the virtual size
   isn't used to set the window size.
-- Added wxTE_BESTWRAP (based on patch by Mart Raudsepp)
+- Added wxTE_BESTWRAP (based on patch by Mart Raudsepp).
 - wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGED is now only sent once at the end of
-  splitter dragging and not after each CHANGING event (Jacobo Vilella Vilahur)
+  splitter dragging and not after each CHANGING event (Jacobo Vilella Vilahur).
 
 Unix:
 
-- Fixed build on Linux/AMD64
+- Fixed build on Linux/AMD64.
 
 wxMSW:
 
-- Added "orient" parameter to wxMDIParentFrame::Tile()
-- wxTextCtrl with wxTE_RICH2 style now uses RichEdit 4.1 if available
-- fix handling Alt-key events in wxComboBox (reported by Joakim Roubert)
-- wxWindow::Refresh() refreshes the window children as well
+- Added "orient" parameter to wxMDIParentFrame::Tile().
+- wxTextCtrl with wxTE_RICH2 style now uses RichEdit 4.1 if available.
+- fix handling Alt-key events in wxComboBox (reported by Joakim Roubert).
+- wxWindow::Refresh() refreshes the window children as well.
+- Improved static box and radio box refresh and background colour
+  handling (Jamie Gadd).
 
 wxGTK:
 
-- Improved wxSystemSettings::GetMetric() to work better with X11. (Mart Raudsepp)
+- Improved wxSystemSettings::GetMetric() to work better with X11 (Mart Raudsepp).
 - Corrected wxListBox selection handling.
 - Corrected default button size handling for different themes.
 - Corrected splitter sash size and look for different themes.
 - Fixed keyboard input for dead-keys.
-- Added support for more wrapping styles (Mart Raudsepp)
+- Added support for more wrapping styles (Mart Raudsepp).
 
 wxMac:
 
index 2658783a362b9072f10ca777080b8966225ecdb7..7607e04a40190be2684bf550975089092e8945c0 100644 (file)
@@ -144,6 +144,8 @@ protected:
                            int sizeFlags = wxSIZE_AUTO);
     virtual wxSize DoGetBestSize() const;
 
+    virtual WXHRGN MSWCalculateClippingRegion();
+    virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
 
     // the buttons we contain
     wxSubwindows *m_radioButtons;
index 1f89b27e536bad61c0d09bb4fdb8045687ab84eb..e222abbeb131ff49f75b10e12b19bac0deb80f0c 100644 (file)
@@ -48,8 +48,12 @@ protected:
     virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
     virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
 
+    virtual WXHRGN MSWCalculateClippingRegion();
+    virtual void MSWClipBoxRegion(HRGN hrgn, const RECT *rc);
+    void OnPaint(wxPaintEvent& event);
 
     DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox)
+    DECLARE_EVENT_TABLE()
 };
 
 #endif // _WX_MSW_STATBOX_H_
index d34034c6b1b7a600132c7b67535817b87f50c7f2..a6df181a1a5f75d141b8895ffd11c2b34e7ed22f 100644 (file)
@@ -165,9 +165,6 @@ bool wxRadioBox::Create(wxWindow *parent,
     wxUnusedVar(val);
 #endif // wxUSE_VALIDATORS/!wxUSE_VALIDATORS
 
-    // and now create the buttons
-    HWND hwndParent = GetHwndOf(parent);
-
     m_radioButtons = new wxSubwindows(n);
     m_radioWidth = new int[n];
     m_radioHeight = new int[n];
@@ -186,7 +183,7 @@ bool wxRadioBox::Create(wxWindow *parent,
                                       choices[i],
                                       styleBtn,
                                       0, 0, 0, 0,   // will be set in SetSize()
-                                      hwndParent,
+                                      GetHwnd(),
                                       (HMENU)newId,
                                       wxGetInstance(),
                                       NULL);
@@ -209,7 +206,7 @@ bool wxRadioBox::Create(wxWindow *parent,
     (void)::CreateWindow(_T("BUTTON"),
                          wxEmptyString,
                          WS_GROUP | BS_AUTORADIOBUTTON | WS_CHILD,
-                         0, 0, 0, 0, hwndParent,
+                         0, 0, 0, 0, GetHwnd(),
                          (HMENU)NewControlId(), wxGetInstance(), NULL);
 
     m_radioButtons->SetFont(GetFont());
@@ -515,8 +512,8 @@ void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
     if (y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
         yy = currentY;
 
-    int y_offset = yy;
-    int x_offset = xx;
+    int y_offset = 0;
+    int x_offset = 0;
 
     int cx1, cy1;
     wxGetCharSize(m_hWnd, &cx1, &cy1, GetFont());
@@ -819,5 +816,55 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
     return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
 }
 
+WXHRGN wxRadioBox::MSWCalculateClippingRegion()
+{
+    RECT rc;
+    ::GetWindowRect(GetHwnd(), &rc);
+    HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
+
+    size_t count = GetCount();
+    for ( size_t i = 0; i < count; ++i )
+    {
+        ::GetWindowRect((*m_radioButtons)[i], &rc);
+        HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
+        ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+        ::DeleteObject(hrgnchild);
+    }
+
+    ::GetWindowRect(GetHwnd(), &rc);
+    ::OffsetRgn(hrgn, -rc.left, -rc.top);
+
+    return hrgn;
+}
+
+WXLRESULT wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+{
+#ifndef __WXWINCE__
+    if ( nMsg == WM_PRINTCLIENT )
+    {
+        // first check to see if a parent window knows how to paint us better
+        for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
+            if ( win->MSWPrintChild(this, wParam, lParam) )
+                return true;
+
+        // nope, so lets do it ourselves
+        RECT rc;
+        WXHBRUSH hbr = DoMSWControlColor((HDC)wParam, wxNullColour);
+        if ( !hbr )
+        {
+            wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
+            hbr = (WXHBRUSH)brush->GetResourceHandle();
+        }
+
+        ::GetClientRect(GetHwnd(), &rc);
+        ::FillRect((HDC)wParam, &rc, (HBRUSH)hbr);
+
+        return true;
+    }
+#endif
+    // __WXWINCE__
+
+    return wxStaticBox::MSWWindowProc(nMsg, wParam, lParam);
+}
 #endif // wxUSE_RADIOBOX
 
index cd21abe8574c29f199dd56bb27ff15099ccede8a..6e2254b8506ae0ac1be72f42decbe81b24e1cf46 100644 (file)
 #include "wx/statbox.h"
 #include "wx/notebook.h"
 #include "wx/sysopt.h"
+#include "wx/image.h"
 
 #include "wx/msw/private.h"
 
-// under CE this style is not defined but we don't need to make static boxes
-// transparent there neither
-#ifndef WS_EX_TRANSPARENT
-    #define WS_EX_TRANSPARENT 0
-#endif
-
 // ----------------------------------------------------------------------------
 // wxWin macros
 // ----------------------------------------------------------------------------
@@ -103,6 +98,10 @@ 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
 // ============================================================================
@@ -132,8 +131,12 @@ WXDWORD wxStaticBox::MSWGetStyle(long style, WXDWORD *exstyle) const
 {
     long styleWin = wxStaticBoxBase::MSWGetStyle(style, exstyle);
 
+    // no need for it anymore, must be removed for wxRadioBox child
+    // buttons to be able to repaint themselves
+    styleWin &= ~WS_CLIPCHILDREN;
+
     if ( exstyle )
-        *exstyle = WS_EX_TRANSPARENT;
+        *exstyle = 0;
 
     return styleWin | BS_GROUPBOX;
 }
@@ -194,5 +197,130 @@ void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
 #endif // !wxDIALOG_UNIT_COMPATIBILITY
 }
 
+// rc must be in client coords!
+void wxStaticBox::MSWClipBoxRegion(HRGN hrgn, const RECT *rc)
+{
+    HRGN hrgnchild;
+
+    // top
+    hrgnchild = ::CreateRectRgn(0, 0, rc->right, 14);
+    ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+    ::DeleteObject(hrgnchild);
+
+    // bottom
+    hrgnchild = ::CreateRectRgn(0, rc->bottom - 7, rc->right, rc->bottom);
+    ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+    ::DeleteObject(hrgnchild);
+
+    // left
+    hrgnchild = ::CreateRectRgn(0, 0, 7, rc->bottom);
+    ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+    ::DeleteObject(hrgnchild);
+
+    // right
+    hrgnchild = ::CreateRectRgn(rc->right - 7, 0, rc->right, rc->bottom);
+    ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+    ::DeleteObject(hrgnchild);
+}
+
+WXHRGN wxStaticBox::MSWCalculateClippingRegion()
+{
+    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 )
+    {
+        wxWindow *child = node->GetData();
+
+        // 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)) )
+        {
+            ::GetWindowRect(GetHwndOf(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);
+                if ( style & WS_CLIPSIBLINGS )
+                {
+                    style &= ~WS_CLIPSIBLINGS;
+                    ::SetWindowLong(GetHwndOf(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,
+                                   SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+                                   SWP_FRAMECHANGED);
+                }
+
+                HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
+                ::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
+                ::DeleteObject(hrgnchild);
+            }
+        }
+
+        node = node->GetNext();
+    }
+    ::GetWindowRect(GetHwnd(), &rc);
+    ::OffsetRgn(hrgn, -rc.left, -rc.top);
+
+    return hrgn;
+}
+
+void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
+{
+    wxPaintDC dc(this);
+    RECT rc;
+    ::GetClientRect(GetHwnd(), &rc);
+
+    // paint the actual box
+    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);
+    MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(memdc), 0);
+
+    // top
+    dc.Blit(7, 0, rc.right - 7, 14, &memdc, 7, 0);
+    // bottom
+    dc.Blit(7, rc.bottom - 7, rc.right - 7, rc.bottom, &memdc, 7, rc.bottom - 7);
+    // left
+    dc.Blit(0, 0, 7, rc.bottom, &memdc, 0, 0);
+    // right
+    dc.Blit(rc.right - 7, 0, rc.right, rc.bottom, &memdc, rc.right - 7, 0);
+
+    // paint the inner
+    HRGN hrgn = (HRGN)MSWCalculateClippingRegion();
+    // now remove the box itself
+    MSWClipBoxRegion(hrgn, &rc);
+
+    hbr = DoMSWControlColor(GetHdcOf(dc), wxNullColour);
+    if ( !hbr )
+    {
+        wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
+        hbr = (WXHBRUSH)brush->GetResourceHandle();
+    }
+
+    ::SelectClipRgn(GetHdcOf(dc), hrgn);
+    ::FillRect(GetHdcOf(dc), &rc, (HBRUSH)hbr);
+    ::SelectClipRgn(GetHdcOf(dc), NULL);
+    ::DeleteObject(hrgn);
+}
+
 #endif // wxUSE_STATBOX