1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/statbox.cpp 
   3 // Purpose:     wxStaticBox 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  21     #pragma implementation "statbox.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  35     #include "wx/dcclient.h" 
  38 #include "wx/statbox.h" 
  39 #include "wx/notebook.h" 
  40 #include "wx/sysopt.h" 
  42 #include "wx/dcmemory.h" 
  44 #include "wx/msw/private.h" 
  46 // ---------------------------------------------------------------------------- 
  48 // ---------------------------------------------------------------------------- 
  50 #if wxUSE_EXTENDED_RTTI 
  51 WX_DEFINE_FLAGS( wxStaticBoxStyle 
) 
  53 wxBEGIN_FLAGS( wxStaticBoxStyle 
) 
  54     // new style border flags, we put them first to 
  55     // use them for streaming out 
  56     wxFLAGS_MEMBER(wxBORDER_SIMPLE
) 
  57     wxFLAGS_MEMBER(wxBORDER_SUNKEN
) 
  58     wxFLAGS_MEMBER(wxBORDER_DOUBLE
) 
  59     wxFLAGS_MEMBER(wxBORDER_RAISED
) 
  60     wxFLAGS_MEMBER(wxBORDER_STATIC
) 
  61     wxFLAGS_MEMBER(wxBORDER_NONE
) 
  63     // old style border flags 
  64     wxFLAGS_MEMBER(wxSIMPLE_BORDER
) 
  65     wxFLAGS_MEMBER(wxSUNKEN_BORDER
) 
  66     wxFLAGS_MEMBER(wxDOUBLE_BORDER
) 
  67     wxFLAGS_MEMBER(wxRAISED_BORDER
) 
  68     wxFLAGS_MEMBER(wxSTATIC_BORDER
) 
  69     wxFLAGS_MEMBER(wxBORDER
) 
  71     // standard window styles 
  72     wxFLAGS_MEMBER(wxTAB_TRAVERSAL
) 
  73     wxFLAGS_MEMBER(wxCLIP_CHILDREN
) 
  74     wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
) 
  75     wxFLAGS_MEMBER(wxWANTS_CHARS
) 
  76     wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
) 
  77     wxFLAGS_MEMBER(wxALWAYS_SHOW_SB 
) 
  78     wxFLAGS_MEMBER(wxVSCROLL
) 
  79     wxFLAGS_MEMBER(wxHSCROLL
) 
  81 wxEND_FLAGS( wxStaticBoxStyle 
) 
  83 IMPLEMENT_DYNAMIC_CLASS_XTI(wxStaticBox
, wxControl
,"wx/statbox.h") 
  85 wxBEGIN_PROPERTIES_TABLE(wxStaticBox
) 
  86     wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
  87     wxPROPERTY_FLAGS( WindowStyle 
, wxStaticBoxStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
  92 wxEND_PROPERTIES_TABLE() 
  94 wxBEGIN_HANDLERS_TABLE(wxStaticBox
) 
  95 wxEND_HANDLERS_TABLE() 
  97 wxCONSTRUCTOR_6( wxStaticBox 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxString 
, Label 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
) 
  99 IMPLEMENT_DYNAMIC_CLASS(wxStaticBox
, wxControl
) 
 102 BEGIN_EVENT_TABLE(wxStaticBox
, wxControl
) 
 103     EVT_PAINT(wxStaticBox::OnPaint
) 
 106 // ============================================================================ 
 108 // ============================================================================ 
 110 // ---------------------------------------------------------------------------- 
 112 // ---------------------------------------------------------------------------- 
 114 bool wxStaticBox::Create(wxWindow 
*parent
, 
 116                          const wxString
& label
, 
 120                          const wxString
& name
) 
 122     if ( !CreateControl(parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) ) 
 125     if ( !MSWCreateControl(wxT("BUTTON"), label
, pos
, size
) ) 
 131 WXDWORD 
wxStaticBox::MSWGetStyle(long style
, WXDWORD 
*exstyle
) const 
 133     long styleWin 
= wxStaticBoxBase::MSWGetStyle(style
, exstyle
); 
 135     // no need for it anymore, must be removed for wxRadioBox child 
 136     // buttons to be able to repaint themselves 
 137     styleWin 
&= ~WS_CLIPCHILDREN
; 
 142     return styleWin 
| BS_GROUPBOX
; 
 145 wxSize 
wxStaticBox::DoGetBestSize() const 
 148     wxGetCharSize(GetHWND(), &cx
, &cy
, GetFont()); 
 151     GetTextExtent(wxGetWindowText(m_hWnd
), &wBox
, &cy
); 
 154     int hBox 
= EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy
); 
 156     return wxSize(wBox
, hBox
); 
 159 WXLRESULT 
wxStaticBox::MSWWindowProc(WXUINT nMsg
, WXWPARAM wParam
, WXLPARAM lParam
) 
 162     if ( nMsg 
== WM_NCHITTEST 
) 
 164         // This code breaks some other processing such as enter/leave tracking 
 165         // so it's off by default. 
 167         static int s_useHTClient 
= -1; 
 168         if (s_useHTClient 
== -1) 
 169             s_useHTClient 
= wxSystemOptions::GetOptionInt(wxT("msw.staticbox.htclient")); 
 170         if (s_useHTClient 
== 1) 
 172             int xPos 
= LOWORD(lParam
);  // horizontal position of cursor 
 173             int yPos 
= HIWORD(lParam
);  // vertical position of cursor 
 175             ScreenToClient(&xPos
, &yPos
); 
 177             // Make sure you can drag by the top of the groupbox, but let 
 178             // other (enclosed) controls get mouse events also 
 180                 return (long)HTCLIENT
; 
 183 #endif // !__WXWINCE__ 
 185     return wxControl::MSWWindowProc(nMsg
, wParam
, lParam
); 
 188 void wxStaticBox::GetBordersForSizer(int *borderTop
, int *borderOther
) const 
 190     wxStaticBoxBase::GetBordersForSizer(borderTop
, borderOther
); 
 192     // if not using correct (but backwards cojmpatible) text metrics 
 193     // calculations, we need to add some extra margin or otherwise static box 
 195 #if !wxDIALOG_UNIT_COMPATIBILITY 
 196     if ( !GetLabel().empty() ) 
 197         *borderTop 
+= GetCharHeight()/3; 
 198 #endif // !wxDIALOG_UNIT_COMPATIBILITY 
 201 // rc must be in client coords! 
 202 void wxStaticBox::MSWClipBoxRegion(HRGN hrgn
, const RECT 
*rc
) 
 207     hrgnchild 
= ::CreateRectRgn(0, 0, rc
->right
, 14); 
 208     ::CombineRgn(hrgn
, hrgn
, hrgnchild
, RGN_DIFF
); 
 209     ::DeleteObject(hrgnchild
); 
 212     hrgnchild 
= ::CreateRectRgn(0, rc
->bottom 
- 7, rc
->right
, rc
->bottom
); 
 213     ::CombineRgn(hrgn
, hrgn
, hrgnchild
, RGN_DIFF
); 
 214     ::DeleteObject(hrgnchild
); 
 217     hrgnchild 
= ::CreateRectRgn(0, 0, 7, rc
->bottom
); 
 218     ::CombineRgn(hrgn
, hrgn
, hrgnchild
, RGN_DIFF
); 
 219     ::DeleteObject(hrgnchild
); 
 222     hrgnchild 
= ::CreateRectRgn(rc
->right 
- 7, 0, rc
->right
, rc
->bottom
); 
 223     ::CombineRgn(hrgn
, hrgn
, hrgnchild
, RGN_DIFF
); 
 224     ::DeleteObject(hrgnchild
); 
 227 WXHRGN 
wxStaticBox::MSWCalculateClippingRegion() 
 230     ::GetWindowRect(GetHwnd(), &rc
); 
 231     HRGN hrgn 
= ::CreateRectRgn(rc
.left
, rc
.top
, rc
.right 
+ 1, rc
.bottom 
+ 1); 
 233     wxWindowList::compatibility_iterator node 
= GetParent()->GetChildren().GetFirst(); 
 236         wxWindow 
*child 
= node
->GetData(); 
 238         // can't just test for (this != child) here since if a wxStaticBox 
 239         // overlaps another wxStaticBox then neither are drawn. The overlapping 
 240         // region will flicker but we shouldn't have overlapping windows anyway. 
 241         if ( !child
->IsKindOf(CLASSINFO(wxStaticBox
)) ) 
 243             ::GetWindowRect(GetHwndOf(child
), &rc
); 
 244             if ( RectInRegion(hrgn
, &rc
) ) 
 246                 // need to remove WS_CLIPSIBLINGS from all sibling windows 
 247                 // that are within this staticbox if set 
 248                 LONG style 
= ::GetWindowLong(GetHwndOf(child
), GWL_STYLE
); 
 249                 if ( style 
& WS_CLIPSIBLINGS 
) 
 251                     style 
&= ~WS_CLIPSIBLINGS
; 
 252                     ::SetWindowLong(GetHwndOf(child
), GWL_STYLE
, style
); 
 254                     // MSDN: "If you have changed certain window data using 
 255                     // SetWindowLong, you must call SetWindowPos to have the 
 256                     // changes take effect." 
 257                     ::SetWindowPos(GetHwndOf(child
), NULL
, 0, 0, 0, 0, 
 258                                    SWP_NOMOVE 
| SWP_NOSIZE 
| SWP_NOZORDER 
| 
 262                 HRGN hrgnchild 
= ::CreateRectRgnIndirect(&rc
); 
 263                 ::CombineRgn(hrgn
, hrgn
, hrgnchild
, RGN_DIFF
); 
 264                 ::DeleteObject(hrgnchild
); 
 268         node 
= node
->GetNext(); 
 270     ::GetWindowRect(GetHwnd(), &rc
); 
 271     ::OffsetRgn(hrgn
, -rc
.left
, -rc
.top
); 
 276 void wxStaticBox::OnPaint(wxPaintEvent
& WXUNUSED(event
)) 
 280     ::GetClientRect(GetHwnd(), &rc
); 
 282     // paint the actual box 
 284     wxBitmap 
bitmap(rc
.right
, rc
.bottom
); 
 285     memdc
.SelectObject(bitmap
); 
 288     WXHBRUSH hbr 
= DoMSWControlColor(GetHdcOf(memdc
), wxNullColour
); 
 291         wxBrush 
*brush 
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour(), wxSOLID
); 
 292         hbr 
= (WXHBRUSH
)brush
->GetResourceHandle(); 
 295     // draw solid box, but only blit the good bits 
 296     ::FillRect(GetHdcOf(memdc
), &rc
, (HBRUSH
)hbr
); 
 297     MSWDefWindowProc(WM_PAINT
, (WPARAM
)GetHdcOf(memdc
), 0); 
 300     dc
.Blit(7, 0, rc
.right 
- 7, 14, &memdc
, 7, 0); 
 302     dc
.Blit(7, rc
.bottom 
- 7, rc
.right 
- 7, rc
.bottom
, &memdc
, 7, rc
.bottom 
- 7); 
 304     dc
.Blit(0, 0, 7, rc
.bottom
, &memdc
, 0, 0); 
 306     dc
.Blit(rc
.right 
- 7, 0, rc
.right
, rc
.bottom
, &memdc
, rc
.right 
- 7, 0); 
 309     HRGN hrgn 
= (HRGN
)MSWCalculateClippingRegion(); 
 310     // now remove the box itself 
 311     MSWClipBoxRegion(hrgn
, &rc
); 
 313     hbr 
= DoMSWControlColor(GetHdcOf(dc
), wxNullColour
); 
 316         wxBrush 
*brush 
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour(), wxSOLID
); 
 317         hbr 
= (WXHBRUSH
)brush
->GetResourceHandle(); 
 320     ::SelectClipRgn(GetHdcOf(dc
), hrgn
); 
 321     ::FillRect(GetHdcOf(dc
), &rc
, (HBRUSH
)hbr
); 
 322     ::SelectClipRgn(GetHdcOf(dc
), NULL
); 
 323     ::DeleteObject(hrgn
); 
 326 #endif // wxUSE_STATBOX