1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/radiobut.cpp 
   3 // Purpose:     wxRadioButton 
   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 "radiobut.h" 
  24 // For compilers that support precompilation, includes "wx.h". 
  25 #include "wx/wxprec.h" 
  34     #include "wx/radiobut.h" 
  35     #include "wx/settings.h" 
  36     #include "wx/dcscreen.h" 
  39 #include "wx/msw/private.h" 
  41 // ============================================================================ 
  42 // wxRadioButton implementation 
  43 // ============================================================================ 
  45 // ---------------------------------------------------------------------------- 
  46 // wxRadioButton creation 
  47 // ---------------------------------------------------------------------------- 
  50 #if wxUSE_EXTENDED_RTTI 
  51 WX_DEFINE_FLAGS( wxRadioButtonStyle 
) 
  53 wxBEGIN_FLAGS( wxRadioButtonStyle 
) 
  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     wxFLAGS_MEMBER(wxRB_GROUP
) 
  83 wxEND_FLAGS( wxRadioButtonStyle 
) 
  85 IMPLEMENT_DYNAMIC_CLASS_XTI(wxRadioButton
, wxControl
,"wx/radiobut.h") 
  87 wxBEGIN_PROPERTIES_TABLE(wxRadioButton
) 
  88     wxEVENT_PROPERTY( Click 
, wxEVT_COMMAND_RADIOBUTTON_SELECTED 
, wxCommandEvent 
) 
  89     wxPROPERTY( Font 
, wxFont 
, SetFont 
, GetFont  
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) 
  90     wxPROPERTY( Label
,wxString
, SetLabel
, GetLabel
, wxString(), 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
  91     wxPROPERTY( Value 
,bool, SetValue
, GetValue
,, 0 /*flags*/ , wxT("Helpstring") , wxT("group") ) 
  92     wxPROPERTY_FLAGS( WindowStyle 
, wxRadioButtonStyle 
, long , SetWindowStyleFlag 
, GetWindowStyleFlag 
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style 
  93 wxEND_PROPERTIES_TABLE() 
  95 wxBEGIN_HANDLERS_TABLE(wxRadioButton
) 
  96 wxEND_HANDLERS_TABLE() 
  98 wxCONSTRUCTOR_6( wxRadioButton 
, wxWindow
* , Parent 
, wxWindowID 
, Id 
, wxString 
, Label 
, wxPoint 
, Position 
, wxSize 
, Size 
, long , WindowStyle 
)  
 101 IMPLEMENT_DYNAMIC_CLASS(wxRadioButton
, wxControl
) 
 105 void wxRadioButton::Init() 
 110 bool wxRadioButton::Create(wxWindow 
*parent
, 
 112                            const wxString
& label
, 
 116                            const wxValidator
& validator
, 
 117                            const wxString
& name
) 
 119     if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) ) 
 122     long msStyle 
= WS_TABSTOP
; 
 123     if ( HasFlag(wxRB_GROUP
) ) 
 127        wxRB_SINGLE is a temporary workaround for the following problem: if you 
 128        have 2 radiobuttons in the same group but which are not consecutive in 
 129        the dialog, Windows can enter an infinite loop! The simplest way to 
 130        reproduce it is to create radio button, then a panel and then another 
 131        radio button: then checking the last button hangs the app. 
 133        Ideally, we'd detect (and avoid) such situation automatically but for 
 134        now, as I don't know how to do it, just allow the user to create 
 135        BS_RADIOBUTTON buttons for such situations. 
 137     msStyle 
|= HasFlag(wxRB_SINGLE
) ? BS_RADIOBUTTON 
: BS_AUTORADIOBUTTON
; 
 139     if ( HasFlag(wxCLIP_SIBLINGS
) ) 
 140         msStyle 
|= WS_CLIPSIBLINGS
; 
 142     if ( !MSWCreateControl(_T("BUTTON"), msStyle
, pos
, size
, label
, 0) ) 
 145     // for compatibility with wxGTK, the first radio button in a group is 
 146     // always checked (this makes sense anyhow as you need to ensure that at 
 147     // least one button in the group is checked and this is the simlpest way to 
 149     if ( HasFlag(wxRB_GROUP
) ) 
 155 // ---------------------------------------------------------------------------- 
 156 // wxRadioButton functions 
 157 // ---------------------------------------------------------------------------- 
 159 void wxRadioButton::SetValue(bool value
) 
 161     (void)::SendMessage(GetHwnd(), BM_SETCHECK
, (value
?BST_CHECKED
:BST_UNCHECKED
), 0L); 
 165     // if we set the value of one radio button we also must clear all the other 
 166     // buttons in the same group: Windows doesn't do it automatically 
 169         const wxWindowList
& siblings 
= GetParent()->GetChildren(); 
 170         wxWindowList::compatibility_iterator nodeThis 
= siblings
.Find(this); 
 171         wxCHECK_RET( nodeThis
, _T("radio button not a child of its parent?") ); 
 173         // if it's not the first item of the group ... 
 174         if ( !HasFlag(wxRB_GROUP
) ) 
 176             // ... turn off all radio buttons before it 
 177             for ( wxWindowList::compatibility_iterator nodeBefore 
= nodeThis
->GetPrevious(); 
 179                   nodeBefore 
= nodeBefore
->GetPrevious() ) 
 181                 wxRadioButton 
*btn 
= wxDynamicCast(nodeBefore
->GetData(), 
 185                     // the radio buttons in a group must be consecutive, so 
 186                     // there are no more of them 
 190                 btn
->SetValue(false); 
 192                 if ( btn
->HasFlag(wxRB_GROUP
) ) 
 194                     // even if there are other radio buttons before this one, 
 195                     // they're not in the same group with us 
 201         // ... and also turn off all buttons after this one 
 202         for ( wxWindowList::compatibility_iterator nodeAfter 
= nodeThis
->GetNext(); 
 204               nodeAfter 
= nodeAfter
->GetNext() ) 
 206             wxRadioButton 
*btn 
= wxDynamicCast(nodeAfter
->GetData(), 
 209             if ( !btn 
|| btn
->HasFlag(wxRB_GROUP
) ) 
 211                 // no more buttons or the first button of the next group 
 215             btn
->SetValue(false); 
 220 bool wxRadioButton::GetValue() const 
 222     wxASSERT_MSG( m_isChecked 
== 
 223                     (::SendMessage(GetHwnd(), BM_GETCHECK
, 0, 0L) != 0), 
 224                   _T("wxRadioButton::m_isChecked is out of sync?") ); 
 229 // ---------------------------------------------------------------------------- 
 230 // wxRadioButton event processing 
 231 // ---------------------------------------------------------------------------- 
 233 void wxRadioButton::Command (wxCommandEvent
& event
) 
 235     SetValue(event
.m_commandInt 
!= 0); 
 236     ProcessCommand(event
); 
 239 bool wxRadioButton::MSWCommand(WXUINT param
, WXWORD 
WXUNUSED(id
)) 
 241     if ( param 
!= BN_CLICKED 
) 
 246         // we have to do this for BS_RADIOBUTTON anyhow and, strangely enough, 
 247         // sometimes this is needed even for BS_AUTORADIOBUTTON (when we 
 248         // receive focus the button gets BN_CLICKED but stays unchecked!) 
 251         wxCommandEvent 
event(wxEVT_COMMAND_RADIOBUTTON_SELECTED
, GetId()); 
 252         event
.SetEventObject( this ); 
 253         event
.SetInt(true); // always checked 
 255         ProcessCommand(event
); 
 261 // ---------------------------------------------------------------------------- 
 262 // wxRadioButton geometry 
 263 // ---------------------------------------------------------------------------- 
 265 wxSize 
wxRadioButton::DoGetBestSize() const 
 267     static int s_radioSize 
= 0; 
 272         dc
.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
)); 
 274         s_radioSize 
= dc
.GetCharHeight(); 
 277     wxString str 
= GetLabel(); 
 282         GetTextExtent(str
, &wRadio
, &hRadio
); 
 283         wRadio 
+= s_radioSize 
+ GetCharWidth(); 
 285         if ( hRadio 
< s_radioSize 
) 
 286             hRadio 
= s_radioSize
; 
 290         wRadio 
= s_radioSize
; 
 291         hRadio 
= s_radioSize
; 
 294     return wxSize(wRadio
, hRadio
); 
 297 #endif // wxUSE_RADIOBTN