Applied patch [ 1166587 ] [wxMSW] Removes all flicker from wxStaticBox

By Jamie Gadd


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33178 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Julian Smart
2005-03-30 15:30:06 +00:00
parent 802fa22622
commit eba99da4c0
5 changed files with 208 additions and 25 deletions

View 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:

View 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;

View 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_

View 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

View File

@@ -38,15 +38,10 @@
#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