diff --git a/docs/latex/wx/radiobut.tex b/docs/latex/wx/radiobut.tex index 9146afe3c0..c9b5f647ed 100644 --- a/docs/latex/wx/radiobut.tex +++ b/docs/latex/wx/radiobut.tex @@ -19,6 +19,9 @@ exclusive options. It has a text label next to a (usually) round button. \twocolwidtha{5cm} \begin{twocollist}\itemsep=0pt \twocolitem{\windowstyle{wxRB\_GROUP}}{Marks the beginning of a new group of radio buttons.} +\twocolitem{\windowstyle{wxRB\_SINGLE}}{If your radio buttons are not +consecutive siblings, they cannot form a group under Windows and you should use +this style to indicate that each of them is handled individually.} \end{twocollist} See also \helpref{window styles overview}{windowstyles}. diff --git a/include/wx/defs.h b/include/wx/defs.h index f0ce9ccc28..5bc8c61f9b 100644 --- a/include/wx/defs.h +++ b/include/wx/defs.h @@ -1099,6 +1099,7 @@ enum wxBorder * wxRadioButton style flag */ #define wxRB_GROUP 0x0004 +#define wxRB_SINGLE 0x0008 /* * wxGauge flags diff --git a/src/msw/radiobut.cpp b/src/msw/radiobut.cpp index f038fd099a..f3a54ab99d 100644 --- a/src/msw/radiobut.cpp +++ b/src/msw/radiobut.cpp @@ -66,9 +66,22 @@ bool wxRadioButton::Create(wxWindow *parent, if ( !CreateControl(parent, id, pos, size, style, validator, name) ) return FALSE; - long msStyle = HasFlag(wxRB_GROUP) ? WS_GROUP : 0; + long msStyle = WS_TABSTOP; + if ( HasFlag(wxRB_GROUP) ) + msStyle |= WS_GROUP; - msStyle |= BS_AUTORADIOBUTTON; + /* + wxRB_SINGLE is a temporary workaround for the following problem: if you + have 2 radiobuttons in the same group but which are not consecutive in + the dialog, Windows can enter an infinite loop! The simplest way to + reproduce it is to create radio button, then a panel and then another + radio button: then checking the last button hangs the app. + + Ideally, we'd detect (and avoid) such situation automatically but for + now, as I don't know how to do it, just allow the user to create + BS_RADIOBUTTON buttons for such situations. + */ + msStyle |= HasFlag(wxRB_SINGLE) ? BS_RADIOBUTTON : BS_AUTORADIOBUTTON; if ( HasFlag(wxCLIP_SIBLINGS) ) msStyle |= WS_CLIPSIBLINGS; @@ -93,7 +106,7 @@ bool wxRadioButton::Create(wxWindow *parent, void wxRadioButton::SetValue(bool value) { // BST_CHECKED is defined as 1, BST_UNCHECKED as 0, so we can just pass - // value as is (we don't sue BST_XXX here as they're not defined for Win16) + // value as is (we don't use BST_XXX here as they're not defined for Win16) (void)::SendMessage(GetHwnd(), BM_SETCHECK, (WPARAM)value, 0L); } @@ -123,7 +136,7 @@ void wxRadioButton::SetFocus() // generates BN_CLICKED which leads to showing another dialog and so on // without end! // - // to aviod this, we drop the pseudo BN_CLICKED events generated when the + // to avoid this, we drop the pseudo BN_CLICKED events generated when the // button gains focus m_focusJustSet = TRUE; @@ -142,9 +155,20 @@ bool wxRadioButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) } else // a real clicked event { + bool isChecked = GetValue(); + + if ( HasFlag(wxRB_SINGLE) ) + { + // when we use a "manual" radio button, we have to check the button + // ourselves -- but it's reset to unchecked state by the user code + // (presumably when another button is pressed) + if ( !isChecked ) + SetValue(TRUE); + } + wxCommandEvent event(wxEVT_COMMAND_RADIOBUTTON_SELECTED, GetId()); event.SetEventObject( this ); - event.SetInt( GetValue() ); + event.SetInt(isChecked); ProcessCommand(event); } @@ -200,7 +224,7 @@ long wxRadioButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) return ret; } - return wxControl::MSWWindowProc(nMsg, wParam, lParam); + return wxControl::MSWWindowProc(nMsg, wParam, lParam); } #endif // wxUSE_RADIOBTN