1///////////////////////////////////////////////////////////////////////////// 2// Name: src/os2/radiobut.cpp 3// Purpose: wxRadioButton 4// Author: David Webster 5// Modified by: 6// Created: 10/12/99 7// RCS-ID: $Id: radiobut.cpp 39567 2006-06-05 16:46:15Z ABX $ 8// Copyright: (c) David Webster 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12// For compilers that support precompilation, includes "wx.h". 13#include "wx/wxprec.h" 14 15#ifdef __BORLANDC__ 16 #pragma hdrstop 17#endif 18 19#include "wx/radiobut.h" 20 21#ifndef WX_PRECOMP 22 #include <stdio.h> 23 #include "wx/brush.h" 24 #include "wx/dcscreen.h" 25 #include "wx/settings.h" 26#endif 27 28#include "wx/os2/private.h" 29 30IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl) 31 32extern void wxAssociateWinWithHandle( HWND hWnd 33 ,wxWindowOS2* pWin 34 ); 35 36void wxRadioButton::Init() 37{ 38 m_bFocusJustSet = false; 39} // end of wxRadioButton::Init 40 41void wxRadioButton::Command ( wxCommandEvent& rEvent ) 42{ 43 SetValue ((rEvent.GetInt() != 0) ); 44 ProcessCommand (rEvent); 45} // end of wxRadioButton::Command 46 47bool wxRadioButton::Create( wxWindow* pParent, 48 wxWindowID vId, 49 const wxString& rsLabel, 50 const wxPoint& rPos, 51 const wxSize& rSize, 52 long lStyle, 53 const wxValidator& rValidator, 54 const wxString& rsName ) 55{ 56 if ( !CreateControl( pParent 57 ,vId 58 ,rPos 59 ,rSize 60 ,lStyle 61 ,rValidator 62 ,rsName)) 63 return false; 64 65 long lSstyle = WS_TABSTOP; 66 67 if (HasFlag(wxRB_GROUP)) 68 lSstyle |= WS_GROUP; 69 70 // 71 // wxRB_SINGLE is a temporary workaround for the following problem: if you 72 // have 2 radiobuttons in the same group but which are not consecutive in 73 // the dialog, Windows can enter an infinite loop! The simplest way to 74 // reproduce it is to create radio button, then a panel and then another 75 // radio button: then checking the last button hangs the app. 76 // 77 // Ideally, we'd detect (and avoid) such situation automatically but for 78 // now, as I don't know how to do it, just allow the user to create 79 // BS_RADIOBUTTON buttons for such situations. 80 // 81 lSstyle |= HasFlag(wxRB_SINGLE) ? BS_RADIOBUTTON : BS_AUTORADIOBUTTON; 82 83 if (HasFlag(wxCLIP_SIBLINGS)) 84 lSstyle |= WS_CLIPSIBLINGS; 85 86 if (!OS2CreateControl( _T("BUTTON") 87 ,lSstyle 88 ,rPos 89 ,rSize 90 ,rsLabel 91 ,0 92 )) 93 return false; 94 95 wxAssociateWinWithHandle(m_hWnd, this); 96 if (HasFlag(wxRB_GROUP)) 97 SetValue(true); 98 99 SetFont(*wxSMALL_FONT); 100 SetSize( rPos.x, rPos.y, rSize.x, rSize.y ); 101 return true; 102} // end of wxRadioButton::Create 103 104wxSize wxRadioButton::DoGetBestSize() const 105{ 106 // We should probably compute snRadioSize but it seems to be a constant 107 // independent of its label's font size and not made available by OS/2. 108 static int snRadioSize = RADIO_SIZE; 109 110 wxString sStr = wxGetWindowText(GetHwnd()); 111 int nRadioWidth; 112 int nRadioHeight; 113 114 if (!sStr.empty()) 115 { 116 GetTextExtent( sStr 117 ,&nRadioWidth 118 ,&nRadioHeight 119 ); 120 nRadioWidth += snRadioSize; 121 if (nRadioHeight < snRadioSize) 122 nRadioHeight = snRadioSize; 123 } 124 else 125 { 126 nRadioWidth = snRadioSize; 127 nRadioHeight = snRadioSize; 128 } 129 return wxSize( nRadioWidth 130 ,nRadioHeight 131 ); 132} // end of wxRadioButton::DoGetBestSize 133 134// 135// Get single selection, for single choice list items 136// 137bool wxRadioButton::GetValue() const 138{ 139 return((::WinSendMsg((HWND) GetHWND(), BM_QUERYCHECK, (MPARAM)0L, (MPARAM)0L) != 0)); 140} // end of wxRadioButton::GetValue 141 142bool wxRadioButton::OS2Command( WXUINT wParam, WXWORD WXUNUSED(wId) ) 143{ 144 if (wParam != BN_CLICKED) 145 return false; 146 147 if (m_bFocusJustSet) 148 { 149 // 150 // See above: we want to ignore this event 151 // 152 m_bFocusJustSet = false; 153 } 154 else 155 { 156 bool bIsChecked = GetValue(); 157 158 if (HasFlag(wxRB_SINGLE)) 159 { 160 // 161 // When we use a "manual" radio button, we have to check the button 162 // ourselves -- but it's reset to unchecked state by the user code 163 // (presumably when another button is pressed) 164 // 165 if (!bIsChecked ) 166 SetValue(true); 167 } 168 wxCommandEvent rEvent( wxEVT_COMMAND_RADIOBUTTON_SELECTED, m_windowId ); 169 rEvent.SetEventObject(this); 170 ProcessCommand(rEvent); 171 } 172 return true; 173} // end of wxRadioButton::OS2Command 174 175void wxRadioButton::SetFocus() 176{ 177 // when the radio button receives a WM_SETFOCUS message it generates a 178 // BN_CLICKED which is totally unexpected and leads to catastrophic results 179 // if you pop up a dialog from the radio button event handler as, when the 180 // dialog is dismissed, the focus is returned to the radio button which 181 // generates BN_CLICKED which leads to showing another dialog and so on 182 // without end! 183 // 184 // to avoid this, we drop the pseudo BN_CLICKED events generated when the 185 // button gains focus 186 m_bFocusJustSet = true; 187 188 wxControl::SetFocus(); 189} 190 191void wxRadioButton::SetLabel( const wxString& rsLabel ) 192{ 193 wxString sLabel = ::wxPMTextToLabel(rsLabel); 194 ::WinSetWindowText((HWND)GetHWND(), (const char *)sLabel.c_str()); 195} // end of wxRadioButton::SetLabel 196 197void wxRadioButton::SetValue( bool bValue ) 198{ 199 ::WinSendMsg((HWND)GetHWND(), BM_SETCHECK, (MPARAM)bValue, (MPARAM)0); 200 if (bValue) 201 { 202 const wxWindowList& rSiblings = GetParent()->GetChildren(); 203 wxWindowList::compatibility_iterator nodeThis = rSiblings.Find(this); 204 205 wxCHECK_RET(nodeThis, _T("radio button not a child of its parent?")); 206 207 // 208 // If it's not the first item of the group ... 209 // 210 if ( !HasFlag(wxRB_GROUP) ) 211 { 212 // 213 // ...turn off all radio buttons before this one 214 // 215 for ( wxWindowList::compatibility_iterator nodeBefore = nodeThis->GetPrevious(); 216 nodeBefore; 217 nodeBefore = nodeBefore->GetPrevious() ) 218 { 219 wxRadioButton* pBtn = wxDynamicCast( nodeBefore->GetData() 220 ,wxRadioButton 221 ); 222 if (!pBtn) 223 { 224 // 225 // The radio buttons in a group must be consecutive, so there 226 // are no more of them 227 // 228 break; 229 } 230 pBtn->SetValue(false); 231 if (pBtn->HasFlag(wxRB_GROUP)) 232 { 233 // 234 // Even if there are other radio buttons before this one, 235 // they're not in the same group with us 236 // 237 break; 238 } 239 } 240 } 241 242 // 243 // ... and all after this one 244 // 245 for (wxWindowList::compatibility_iterator nodeAfter = nodeThis->GetNext(); 246 nodeAfter; 247 nodeAfter = nodeAfter->GetNext()) 248 { 249 wxRadioButton* pBtn = wxDynamicCast( nodeAfter->GetData() 250 ,wxRadioButton 251 ); 252 253 if (!pBtn || pBtn->HasFlag(wxRB_GROUP) ) 254 { 255 // 256 // No more buttons or the first button of the next group 257 // 258 break; 259 } 260 pBtn->SetValue(false); 261 } 262 } 263} // end of wxRadioButton::SetValue 264 265MRESULT wxRadioButton::OS2WindowProc( 266 WXUINT uMsg 267, WXWPARAM wParam 268, WXLPARAM lParam 269) 270{ 271 if (uMsg == WM_SETFOCUS) 272 { 273 m_bFocusJustSet = true; 274 275 MRESULT mRc = wxControl::OS2WindowProc( uMsg 276 ,wParam 277 ,lParam 278 ); 279 280 m_bFocusJustSet = false; 281 return mRc; 282 } 283 return wxControl::OS2WindowProc( uMsg 284 ,wParam 285 ,lParam 286 ); 287} // end of wxRadioButton::OS2WindowProc 288