fixes to static box borders calculations and significant code cleanup (finalizes patch 1166587)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33247 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -144,8 +144,11 @@ protected:
|
|||||||
int sizeFlags = wxSIZE_AUTO);
|
int sizeFlags = wxSIZE_AUTO);
|
||||||
virtual wxSize DoGetBestSize() const;
|
virtual wxSize DoGetBestSize() const;
|
||||||
|
|
||||||
virtual WXHRGN MSWCalculateClippingRegion();
|
virtual WXHRGN MSWGetRegionWithoutChildren();
|
||||||
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
virtual WXLRESULT MSWWindowProc(WXUINT nMsg,
|
||||||
|
WXWPARAM wParam,
|
||||||
|
WXLPARAM lParam);
|
||||||
|
|
||||||
|
|
||||||
// the buttons we contain
|
// the buttons we contain
|
||||||
wxSubwindows *m_radioButtons;
|
wxSubwindows *m_radioButtons;
|
||||||
|
@@ -48,12 +48,19 @@ protected:
|
|||||||
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
|
virtual WXDWORD MSWGetStyle(long style, WXDWORD *exstyle) const;
|
||||||
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam);
|
||||||
|
|
||||||
virtual WXHRGN MSWCalculateClippingRegion();
|
// return the region with all the windows inside this static box excluded
|
||||||
virtual void MSWClipBoxRegion(WXHRGN hrgn, const WXRECTPTR rc);
|
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);
|
void OnPaint(wxPaintEvent& event);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox)
|
DECLARE_DYNAMIC_CLASS_NO_COPY(wxStaticBox)
|
||||||
DECLARE_EVENT_TABLE()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _WX_MSW_STATBOX_H_
|
#endif // _WX_MSW_STATBOX_H_
|
||||||
|
@@ -816,25 +816,21 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
|
|||||||
return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
|
return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, message, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
WXHRGN wxRadioBox::MSWCalculateClippingRegion()
|
WXHRGN wxRadioBox::MSWGetRegionWithoutChildren()
|
||||||
{
|
{
|
||||||
RECT rc;
|
RECT rc;
|
||||||
::GetWindowRect(GetHwnd(), &rc);
|
::GetWindowRect(GetHwnd(), &rc);
|
||||||
HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
|
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 )
|
for ( size_t i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
::GetWindowRect((*m_radioButtons)[i], &rc);
|
::GetWindowRect((*m_radioButtons)[i], &rc);
|
||||||
HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
|
AutoHRGN hrgnchild(::CreateRectRgnIndirect(&rc));
|
||||||
::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
|
::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
|
||||||
::DeleteObject(hrgnchild);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::GetWindowRect(GetHwnd(), &rc);
|
return (WXHRGN)hrgn;
|
||||||
::OffsetRgn(hrgn, -rc.left, -rc.top);
|
|
||||||
|
|
||||||
return hrgn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WXLRESULT wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
WXLRESULT wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||||
|
@@ -99,10 +99,6 @@ wxCONSTRUCTOR_6( wxStaticBox , wxWindow* , Parent , wxWindowID , Id , wxString ,
|
|||||||
IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
|
IMPLEMENT_DYNAMIC_CLASS(wxStaticBox, wxControl)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(wxStaticBox, wxControl)
|
|
||||||
EVT_PAINT(wxStaticBox::OnPaint)
|
|
||||||
END_EVENT_TABLE()
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -125,6 +121,8 @@ bool wxStaticBox::Create(wxWindow *parent,
|
|||||||
if ( !MSWCreateControl(wxT("BUTTON"), label, pos, size) )
|
if ( !MSWCreateControl(wxT("BUTTON"), label, pos, size) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Connect(wxEVT_PAINT, wxPaintEventHandler(wxStaticBox::OnPaint));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,58 +196,61 @@ void wxStaticBox::GetBordersForSizer(int *borderTop, int *borderOther) const
|
|||||||
#endif // !wxDIALOG_UNIT_COMPATIBILITY
|
#endif // !wxDIALOG_UNIT_COMPATIBILITY
|
||||||
}
|
}
|
||||||
|
|
||||||
// rc must be in client coords!
|
// MSWGetRegionWithoutSelf helper: removes the given rectangle from region
|
||||||
void wxStaticBox::MSWClipBoxRegion(WXHRGN hrgn, const WXRECTPTR rc)
|
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 )
|
||||||
// top
|
{
|
||||||
hrgnchild = ::CreateRectRgn(0, 0, ((const RECT*) rc)->right, 14);
|
wxLogLastError(_T("CreateRectRgn()"));
|
||||||
::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
|
return;
|
||||||
::DeleteObject(hrgnchild);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// left
|
|
||||||
hrgnchild = ::CreateRectRgn(0, 0, 7, ((const RECT*) rc)->bottom);
|
|
||||||
::CombineRgn((HRGN) hrgn, (HRGN) hrgn, hrgnchild, RGN_DIFF);
|
|
||||||
::DeleteObject(hrgnchild);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WXHRGN wxStaticBox::MSWCalculateClippingRegion()
|
::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
|
||||||
|
SubtractRectFromRgn(hrgn, 0, 0, w, borderTop);
|
||||||
|
|
||||||
|
// bottom
|
||||||
|
SubtractRectFromRgn(hrgn, 0, h - border, w, h);
|
||||||
|
|
||||||
|
// left
|
||||||
|
SubtractRectFromRgn(hrgn, 0, 0, border, h);
|
||||||
|
|
||||||
|
// right
|
||||||
|
SubtractRectFromRgn(hrgn, w - border, 0, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
WXHRGN wxStaticBox::MSWGetRegionWithoutChildren()
|
||||||
{
|
{
|
||||||
RECT rc;
|
RECT rc;
|
||||||
::GetWindowRect(GetHwnd(), &rc);
|
::GetWindowRect(GetHwnd(), &rc);
|
||||||
HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
|
HRGN hrgn = ::CreateRectRgn(rc.left, rc.top, rc.right + 1, rc.bottom + 1);
|
||||||
|
|
||||||
wxList hWnds;
|
// iterate over all child windows (not just wxWindows but all windows)
|
||||||
HWND child = ::GetWindow((HWND) GetParent()->GetHWND(), GW_CHILD);
|
for ( HWND child = ::GetWindow(GetHwndOf(GetParent()), GW_CHILD);
|
||||||
while (child != 0)
|
child;
|
||||||
|
child = ::GetWindow(child, GW_HWNDNEXT) )
|
||||||
{
|
{
|
||||||
hWnds.Append((wxObject*) child);
|
|
||||||
child = ::GetWindow(child, GW_HWNDNEXT);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (wxNode* node = hWnds.GetFirst(); node; node = node->GetNext())
|
|
||||||
{
|
|
||||||
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
|
// can't just test for (this != child) here since if a wxStaticBox
|
||||||
// overlaps another wxStaticBox then neither are drawn. The overlapping
|
// overlaps another wxStaticBox then neither are drawn. The overlapping
|
||||||
// region will flicker but we shouldn't have overlapping windows anyway.
|
// 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);
|
::GetWindowRect(child, &rc);
|
||||||
if ( RectInRegion(hrgn, &rc) )
|
if ( ::RectInRegion(hrgn, &rc) )
|
||||||
{
|
{
|
||||||
// need to remove WS_CLIPSIBLINGS from all sibling windows
|
// need to remove WS_CLIPSIBLINGS from all sibling windows
|
||||||
// that are within this staticbox if set
|
// that are within this staticbox if set
|
||||||
@@ -267,17 +268,29 @@ WXHRGN wxStaticBox::MSWCalculateClippingRegion()
|
|||||||
SWP_FRAMECHANGED);
|
SWP_FRAMECHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRGN hrgnchild = ::CreateRectRgnIndirect(&rc);
|
AutoHRGN hrgnChild(::CreateRectRgnIndirect(&rc));
|
||||||
::CombineRgn(hrgn, hrgn, hrgnchild, RGN_DIFF);
|
::CombineRgn(hrgn, hrgn, hrgnChild, RGN_DIFF);
|
||||||
::DeleteObject(hrgnchild);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::GetWindowRect(GetHwnd(), &rc);
|
return (WXHRGN)hrgn;
|
||||||
::OffsetRgn(hrgn, -rc.left, -rc.top);
|
}
|
||||||
|
|
||||||
return 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))
|
void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
|
||||||
@@ -286,48 +299,45 @@ void wxStaticBox::OnPaint(wxPaintEvent& WXUNUSED(event))
|
|||||||
RECT rc;
|
RECT rc;
|
||||||
::GetClientRect(GetHwnd(), &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;
|
wxMemoryDC memdc;
|
||||||
wxBitmap bitmap(rc.right, rc.bottom);
|
wxBitmap bitmap(rc.right, rc.bottom);
|
||||||
memdc.SelectObject(bitmap);
|
memdc.SelectObject(bitmap);
|
||||||
|
|
||||||
// get bg brush
|
PaintBackground(memdc, rc);
|
||||||
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);
|
MSWDefWindowProc(WM_PAINT, (WPARAM)GetHdcOf(memdc), 0);
|
||||||
|
|
||||||
|
int borderTop, border;
|
||||||
|
GetBordersForSizer(&borderTop, &border);
|
||||||
|
|
||||||
// top
|
// top
|
||||||
dc.Blit(7, 0, rc.right - 7, 14, &memdc, 7, 0);
|
dc.Blit(border, 0, rc.right - border, borderTop,
|
||||||
|
&memdc, border, 0);
|
||||||
// bottom
|
// 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
|
// left
|
||||||
dc.Blit(0, 0, 7, rc.bottom, &memdc, 0, 0);
|
dc.Blit(0, 0, border, rc.bottom,
|
||||||
|
&memdc, 0, 0);
|
||||||
// right
|
// 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);
|
||||||
|
|
||||||
|
AutoHRGN hrgn((HRGN)MSWGetRegionWithoutChildren());
|
||||||
|
RECT rcWin;
|
||||||
|
::GetWindowRect(GetHwnd(), &rcWin);
|
||||||
|
::OffsetRgn(hrgn, -rcWin.left, -rcWin.top);
|
||||||
|
|
||||||
|
|
||||||
// paint the inner
|
|
||||||
HRGN hrgn = (HRGN)MSWCalculateClippingRegion();
|
|
||||||
// now remove the box itself
|
// now remove the box itself
|
||||||
MSWClipBoxRegion((WXHRGN) hrgn, (const WXRECTPTR) &rc);
|
MSWGetRegionWithoutSelf((WXHRGN) hrgn, rc.right, rc.bottom);
|
||||||
|
|
||||||
hbr = DoMSWControlColor(GetHdcOf(dc), wxNullColour);
|
|
||||||
if ( !hbr )
|
|
||||||
{
|
|
||||||
wxBrush *brush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
|
|
||||||
hbr = (WXHBRUSH)brush->GetResourceHandle();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// and paint the inside of the box (excluding child controls)
|
||||||
::SelectClipRgn(GetHdcOf(dc), hrgn);
|
::SelectClipRgn(GetHdcOf(dc), hrgn);
|
||||||
::FillRect(GetHdcOf(dc), &rc, (HBRUSH)hbr);
|
PaintBackground(dc, rc);
|
||||||
::SelectClipRgn(GetHdcOf(dc), NULL);
|
::SelectClipRgn(GetHdcOf(dc), NULL);
|
||||||
::DeleteObject(hrgn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // wxUSE_STATBOX
|
#endif // wxUSE_STATBOX
|
||||||
|
Reference in New Issue
Block a user