1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/radiobox.cpp 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  17 #include "wx/radiobox.h" 
  22     #include "wx/string.h" 
  23     #include "wx/bitmap.h" 
  27 #include "wx/os2/private.h" 
  29 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
) 
  31 // --------------------------------------------------------------------------- 
  33 // --------------------------------------------------------------------------- 
  35 // wnd proc for radio buttons 
  36 MRESULT EXPENTRY 
wxRadioBtnWndProc( HWND hWnd
 
  41 MRESULT EXPENTRY 
wxRadioBoxWndProc( HWND   hWnd
 
  47 // --------------------------------------------------------------------------- 
  49 // --------------------------------------------------------------------------- 
  51 extern void  wxAssociateWinWithHandle( HWND         hWnd
 
  54 extern void wxRemoveHandleAssociation( wxWindowOS2 
*pWin 
); 
  55 // the pointer to standard radio button & box wnd procs 
  56 static WXFARPROC                    fnWndProcRadioBtn 
= NULL
; 
  57 static WXFARPROC                    fnWndProcRadioBox 
= NULL
; 
  59 // =========================================================================== 
  61 // =========================================================================== 
  63 // --------------------------------------------------------------------------- 
  65 // --------------------------------------------------------------------------- 
  68 wxRadioBox::wxRadioBox() 
  70     m_nSelectedButton 
= -1; 
  72     m_ahRadioButtons 
= NULL
; 
  73     m_pnRadioWidth 
= NULL
; 
  74     m_pnRadioHeight 
= NULL
; 
  75 } // end of wxRadioBox::wxRadioBox 
  77 wxRadioBox::~wxRadioBox() 
  82         wxRemoveHandleAssociation(this); 
  85         for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
  87             wxWindow
* pWin 
= wxFindWinFromHandle((WXHWND
)m_ahRadioButtons
[i
]); 
  88             wxRemoveHandleAssociation(pWin
); 
  90             ::WinDestroyWindow((HWND
)m_ahRadioButtons
[i
]); 
  92         delete[] m_ahRadioButtons
; 
  95         delete[] m_pnRadioWidth
; 
  97         delete[] m_pnRadioHeight
; 
  98 } // end of wxRadioBox::~wxRadioBox 
 100 void wxRadioBox::Command ( wxCommandEvent
& rEvent 
) 
 102     SetSelection (rEvent
.GetInt()); 
 103     ProcessCommand(rEvent
); 
 104 } // end of wxRadioBox::Command 
 106 bool wxRadioBox::ContainsHWND( WXHWND hWnd 
) const 
 108     unsigned int nCount 
= GetCount(); 
 111     for (i 
= 0; i 
< nCount
; i
++) 
 113         if (GetRadioButtons()[i
] == hWnd
) 
 117 } // end of wxRadioBox::ContainsHWND 
 119 bool wxRadioBox::Create( wxWindow
* pParent
, 
 121                          const wxString
& rsTitle
, 
 124                          const wxArrayString
& asChoices
, 
 127                          const wxValidator
& rVal
, 
 128                          const wxString
& rsName 
) 
 130     wxCArrayString 
chs(asChoices
); 
 132     return Create(pParent
, vId
, rsTitle
, rPos
, rSize
, chs
.GetCount(), 
 133                   chs
.GetStrings(), nMajorDim
, lStyle
, rVal
, rsName
); 
 136 bool wxRadioBox::Create( wxWindow
* pParent
, 
 138                          const wxString
& rsTitle
, 
 142                          const wxString asChoices
[], 
 145                          const wxValidator
& rVal
, 
 146                          const wxString
& rsName 
) 
 148     wxColour 
vColour(*wxBLACK
); 
 150     HWND     hWndParent 
= GetHwndOf(pParent
); 
 152     m_backgroundColour 
= pParent
->GetBackgroundColour(); 
 153     m_nSelectedButton 
= -1; 
 157     // Common initialization 
 159     if (!CreateControl( pParent
 
 168     if (!OS2CreateControl( wxT("STATIC") 
 176     wxAssociateWinWithHandle(m_hWnd
, this); 
 179     // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows 
 181     m_nNoItems 
= (unsigned int)nNum
; 
 182     SetMajorDim(nMajorDim 
== 0 ? nNum 
: nMajorDim
, lStyle
); 
 184     m_ahRadioButtons 
= new WXHWND
[nNum
]; 
 185     m_pnRadioWidth   
= new int[nNum
]; 
 186     m_pnRadioHeight  
= new int[nNum
]; 
 188     for (int i 
= 0; i 
< nNum
; i
++) 
 190         m_pnRadioWidth
[i
] = m_pnRadioHeight
[i
] = -1; 
 191         long                        lStyleBtn 
= BS_AUTORADIOBUTTON 
| WS_VISIBLE
; 
 192         int                         nNewId 
= NewControlId(); 
 195             lStyleBtn 
|= WS_GROUP 
| WS_TABSTOP
; 
 197         wxString                    sLabel 
= ::wxPMTextToLabel(asChoices
[i
]); 
 199         HWND                        hWndBtn 
= (WXHWND
)::WinCreateWindow ( hWndParent
, 
 214         lColor 
= (LONG
)vColour
.GetPixel(); 
 215         ::WinSetPresParam( hWndBtn
 
 221         lColor 
= (LONG
)m_backgroundColour
.GetPixel(); 
 222         ::WinSetPresParam( hWndBtn
 
 227         m_ahRadioButtons
[i
] = (WXHWND
)hWndBtn
; 
 228         SubclassRadioButton((WXHWND
)hWndBtn
); 
 229         wxAssociateWinWithHandle(hWndBtn
, this); 
 230         wxOS2SetFont( hWndBtn
 
 233         ::WinSetWindowULong(hWndBtn
, QWL_USER
, (ULONG
)this); 
 234         m_aSubControls
.Add(nNewId
); 
 238     // Create a dummy control to end the group. 
 240     (void)::WinCreateWindow ( hWndParent
, 
 247                               (HMENU
)NewControlId(), 
 251     fnWndProcRadioBox 
= (WXFARPROC
)::WinSubclassWindow( GetHwnd() 
 252                                                        ,(PFNWP
)wxRadioBoxWndProc
 
 254     ::WinSetWindowULong(GetHwnd(), QWL_USER
, (ULONG
)this); 
 255     lColor 
= (LONG
)vColour
.GetPixel(); 
 256     ::WinSetPresParam( m_hWnd
 
 262     lColor 
= (LONG
)m_backgroundColour
.GetPixel(); 
 263     ::WinSetPresParam( m_hWnd
 
 277 } // end of wxRadioBox::Create 
 279 wxSize 
wxRadioBox::DoGetBestSize() const 
 281     return (GetTotalButtonSize(GetMaxButtonSize())); 
 282 } // end of wxRadioBox::DoGetBestSize 
 284 void wxRadioBox::DoSetSize( 
 293     // Input parameters assume wxWidgets coordinate system 
 305     wxSize                          vMaxSize 
= GetMaxButtonSize(); 
 313     wxFont                          vFont 
= GetFont(); 
 315     m_nSizeFlags 
= nSizeFlags
; 
 316     GetPosition( &nCurrentX
 
 323     if (nX 
== wxDefaultCoord 
&& !(nSizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 325     if (nY 
== wxDefaultCoord 
&& !(nSizeFlags 
& wxSIZE_ALLOW_MINUS_ONE
)) 
 332     wxGetCharSize( m_hWnd
 
 339     // Attempt to have a look coherent with other platforms: We compute the 
 340     // biggest toggle dim, then we align all items according this value. 
 342     vMaxSize   
= GetMaxButtonSize(); 
 343     nMaxWidth  
= vMaxSize
.x
; 
 344     nMaxHeight 
= vMaxSize
.y
; 
 346     vTotSize   
= GetTotalButtonSize(vMaxSize
); 
 347     nTotWidth  
= vTotSize
.x
; 
 348     nTotHeight 
= vTotSize
.y
; 
 351     // Only change our width/height if asked for 
 355         if (nSizeFlags 
& wxSIZE_AUTO_WIDTH 
) 
 363         if (nSizeFlags 
& wxSIZE_AUTO_HEIGHT
) 
 364             nHeight 
= nTotHeight
; 
 366             nHeight 
= nHeightOld
; 
 370     // Now convert to OS/2 coordinate system 
 372     wxWindowOS2
*                    pParent 
= (wxWindowOS2
*)GetParent(); 
 374         nYy 
= GetOS2ParentHeight(pParent
) - nYy 
- nHeight
; 
 378         ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
); 
 379         nYy 
= vRect
.yTop 
- nYy 
- nHeight
; 
 381     nYOffset 
= nYy 
+ nHeight
; 
 382     ::WinSetWindowPos( GetHwnd() 
 388                       ,SWP_ZORDER 
| SWP_SIZE 
| SWP_MOVE 
| SWP_SHOW
 
 392     // Now position all the buttons: the current button will be put at 
 393     // wxPoint(x_offset, y_offset) and the new row/column will start at 
 394     // startX/startY. The size of all buttons will be the same wxSize(maxWidth, 
 395     // maxHeight) except for the buttons in the last column which should extend 
 396     // to the right border of radiobox and thus can be wider than this. 
 398     // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in 
 399     // left to right order and m_majorDim is the number of columns while 
 400     // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and 
 401     // m_majorDim is the number of rows. 
 404     nYOffset 
-= (nMaxHeight 
+ ((3*nCy1
)/2)); 
 409     for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
 412         // The last button in the row may be wider than the other ones as the 
 413         // radiobox may be wider than the sum of the button widths (as it 
 414         // happens, for example, when the radiobox label is very long) 
 416         bool bIsLastInTheRow
; 
 418         if (m_windowStyle 
& wxRA_SPECIFY_COLS
) 
 421             // Item is the last in its row if it is a multiple of the number of 
 422             // columns or if it is just the last item 
 426             bIsLastInTheRow 
= ((n 
% GetMajorDim()) == 0) || (n 
== (int)m_nNoItems
); 
 428         else // winRA_SPECIFY_ROWS 
 431             // Item is the last in the row if it is in the last columns 
 433             bIsLastInTheRow 
= i 
>= (m_nNoItems
/GetMajorDim()) * GetMajorDim(); 
 437         // Is this the start of new row/column? 
 439         if (i 
&& (i 
% GetMajorDim() == 0)) 
 441             if (m_windowStyle 
& wxRA_SPECIFY_ROWS
) 
 444                 // Start of new column 
 447                 nXOffset 
+= nMaxWidth 
+ nCx1
; 
 449             else // start of new row 
 452                 nYOffset 
-= nMaxHeight
; 
 453                 if (m_pnRadioWidth
[0] > 0L) 
 463             // Make the button go to the end of radio box 
 465             nWidthBtn 
= nStartX 
+ nWidth 
- nXOffset 
- (2 * nCx1
); 
 466             if (nWidthBtn 
< nMaxWidth
) 
 467                 nWidthBtn 
= nMaxWidth
; 
 472             // Normal button, always of the same size 
 474             nWidthBtn 
= nMaxWidth
; 
 478         // Make all buttons of the same, maximal size - like this they 
 479         // cover the radiobox entirely and the radiobox tooltips are always 
 480         // shown (otherwise they are not when the mouse pointer is in the 
 481         // radiobox part not belonging to any radiobutton) 
 483         ::WinSetWindowPos( (HWND
)m_ahRadioButtons
[i
] 
 489                           ,SWP_ZORDER 
| SWP_SIZE 
| SWP_MOVE 
| SWP_SHOW
 
 492         // Where do we put the next button? 
 494         if (m_windowStyle 
& wxRA_SPECIFY_ROWS
) 
 499             nYOffset 
-= nMaxHeight
; 
 500             if (m_pnRadioWidth
[0] > 0) 
 506             // To the right of this one 
 508             nXOffset 
+= nWidthBtn 
+ nCx1
; 
 511 } // end of wxRadioBox::DoSetSize 
 513 bool wxRadioBox::Enable(unsigned int nItem
, bool bEnable
) 
 515     wxCHECK_MSG( IsValid(nItem
), false, 
 516                  wxT("invalid item in wxRadioBox::Enable()") ); 
 518     ::WinEnableWindow((HWND
) m_ahRadioButtons
[nItem
], bEnable
); 
 520 } // end of wxRadioBox::Enable 
 522 bool wxRadioBox::Enable(bool bEnable
) 
 524     if ( !wxControl::Enable(bEnable
) ) 
 526     for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
 527         ::WinEnableWindow((HWND
)m_ahRadioButtons
[i
], bEnable
); 
 529 } // end of wxRadioBox::Enable 
 531 unsigned int wxRadioBox::GetCount() const 
 534 } // end of wxRadioBox::GetCount 
 536 wxString 
wxRadioBox::GetLabel(int nItem
) const 
 538     wxCHECK_MSG( IsValid(nItem
), wxEmptyString
, wxT("invalid radiobox index") ); 
 540     return wxGetWindowText(m_ahRadioButtons
[nItem
]); 
 541 } // end of wxRadioBox::GetLabel 
 543 wxSize 
wxRadioBox::GetMaxButtonSize() const 
 548     for (unsigned int i 
= 0 ; i 
< m_nNoItems
; i
++) 
 553         if (m_pnRadioWidth
[i
] < 0L) 
 555             GetTextExtent( wxGetWindowText(m_ahRadioButtons
[i
]) 
 561             // Adjust the size to take into account the radio box itself 
 562             // FIXME this is totally bogus! 
 564             nWidth  
+= RADIO_SIZE
; 
 570             nWidth  
= m_pnRadioWidth
[i
]; 
 571             nHeight 
= m_pnRadioHeight
[i
]; 
 573         if (nWidthMax 
< nWidth 
) 
 575         if (nHeightMax 
< nHeight 
) 
 576             nHeightMax 
= nHeight
; 
 578     wxSize 
maxsize( nWidthMax
, nHeightMax
); 
 580 } // end of wxRadioBox::GetMaxButtonSize 
 582 // Get single selection, for single choice list items 
 583 int wxRadioBox::GetSelection() const 
 585     return m_nSelectedButton
; 
 586 } // end of wxRadioBox::GetSelection 
 588 void wxRadioBox::GetSize( int* pnWidth
, int* pnHeight 
) const 
 598         wxFindMaxSize( m_hWnd
, &vRect 
); 
 600     for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
 601         wxFindMaxSize( m_ahRadioButtons
[i
], &vRect 
); 
 604         *pnWidth  
= vRect
.xRight 
- vRect
.xLeft
; 
 606         *pnHeight 
= vRect
.yTop 
- vRect
.yBottom
; 
 607 } // end of wxRadioBox::GetSize 
 609 // Find string for position 
 610 wxString 
wxRadioBox::GetString(unsigned int nNum
) const 
 612     wxCHECK_MSG( IsValid(nNum
), wxEmptyString
, wxT("invalid radiobox index") ); 
 613     return wxGetWindowText(m_ahRadioButtons
[nNum
]); 
 614 } // end of wxRadioBox::GetString 
 616 // For single selection items only 
 617 wxString 
wxRadioBox::GetStringSelection() const 
 620     int nSel 
= GetSelection(); 
 622     if (nSel 
!= wxNOT_FOUND
) 
 623         sResult 
= GetString(nSel
); 
 626 } // end of wxRadioBox::GetStringSelection 
 628 wxSize 
wxRadioBox::GetTotalButtonSize( const wxSize
& rSizeBtn 
) const 
 636     nCx1 
= GetCharWidth(); 
 637     nCy1 
= GetCharHeight(); 
 638     nHeight 
= GetRowCount() * rSizeBtn
.y 
+ (2 * nCy1
); 
 639     nWidth  
= GetColumnCount() * (rSizeBtn
.x 
+ nCx1
) + nCx1
; 
 642     // And also wide enough for its label 
 644     wxString sStr 
= wxGetWindowText(GetHwnd()); 
 651         nWidthLabel 
+= 2*nCx1
; 
 653     if (nWidthLabel 
> nWidth
) 
 654         nWidth 
= nWidthLabel
; 
 656     wxSize 
total( nWidth
, nHeight 
); 
 658 } // end of wxRadioBox::GetTotalButtonSize 
 660 WXHBRUSH 
wxRadioBox::OnCtlColor( WXHDC    hwinDC
, 
 661                                  WXHWND   
WXUNUSED(hWnd
), 
 662                                  WXUINT   
WXUNUSED(uCtlColor
), 
 663                                  WXUINT   
WXUNUSED(uMessage
), 
 664                                  WXWPARAM 
WXUNUSED(wParam
), 
 665                                  WXLPARAM 
WXUNUSED(lParam
) ) 
 667     HPS hPS 
= (HPS
)hwinDC
; // pass in a PS handle in OS/2 
 669     if (GetParent()->GetTransparentBackground()) 
 670         ::GpiSetBackMix(hPS
, BM_LEAVEALONE
); 
 672         ::GpiSetBackMix(hPS
, BM_OVERPAINT
); 
 674     wxColour vColBack 
= GetBackgroundColour(); 
 676     ::GpiSetBackColor(hPS
, vColBack
.GetPixel()); 
 677     ::GpiSetColor(hPS
, vColBack
.GetPixel()); 
 679     wxBrush
* pBrush 
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID 
); 
 680     return ((WXHBRUSH
)pBrush
->GetResourceHandle()); 
 681 } // end of wxRadioBox::OnCtlColor 
 683 bool wxRadioBox::OS2Command( WXUINT uCmd
, 
 686     int nSelectedButton 
= -1; 
 688     if (uCmd 
== BN_CLICKED
) 
 693         for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
 695             if (wId 
== wxGetWindowId(m_ahRadioButtons
[i
])) 
 701         if (nSelectedButton 
== -1) 
 708         if (nSelectedButton 
!= m_nSelectedButton
) 
 710             m_nSelectedButton 
= nSelectedButton
; 
 711             SendNotificationEvent(); 
 717 } // end of wxRadioBox::OS2Command 
 719 void wxRadioBox::SendNotificationEvent() 
 721     wxCommandEvent 
vEvent( 
 722                        wxEVT_COMMAND_RADIOBOX_SELECTED
, 
 726     vEvent
.SetInt( m_nSelectedButton 
); 
 727     vEvent
.SetString( GetString(m_nSelectedButton
) ); 
 728     vEvent
.SetEventObject(this); 
 729     ProcessCommand(vEvent
); 
 730 } // end of wxRadioBox::SendNotificationEvent 
 732 void wxRadioBox::SetFocus() 
 736         if (m_nSelectedButton 
== -1) 
 737             ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[0]); 
 739             ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[m_nSelectedButton
]); 
 741 } // end of wxRadioBox::SetFocus 
 743 bool wxRadioBox::SetFont(const wxFont
& rFont
) 
 745     if (!wxControl::SetFont(rFont
)) 
 753     // Also set the font of our radio buttons 
 755     for (unsigned int n 
= 0; n 
< m_nNoItems
; n
++) 
 757         HWND hWndBtn 
= (HWND
)m_ahRadioButtons
[n
]; 
 759         wxOS2SetFont( hWndBtn
, rFont 
); 
 760         ::WinInvalidateRect(hWndBtn
, NULL
, FALSE
); 
 763 } // end of wxRadioBox::SetFont 
 765 void wxRadioBox::SetSelection( 
 769     wxCHECK_RET( IsValid(nNum
), wxT("invalid radiobox index") ); 
 771     if ( IsValid(m_nSelectedButton
) ) 
 772         ::WinSendMsg((HWND
)m_ahRadioButtons
[m_nSelectedButton
], BM_SETCHECK
, (MPARAM
)0, (MPARAM
)0); 
 774     ::WinSendMsg((HWND
)m_ahRadioButtons
[nNum
], BM_SETCHECK
, (MPARAM
)1, (MPARAM
)0); 
 775     ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[nNum
]); 
 776     m_nSelectedButton 
= nNum
; 
 777 } // end of wxRadioBox::SetSelection 
 779 void wxRadioBox::SetString(unsigned int nItem
, const wxString
& rsLabel
) 
 781     wxCHECK_RET( IsValid(nItem
), wxT("invalid radiobox index") ); 
 783     m_pnRadioWidth
[nItem
] = m_pnRadioHeight
[nItem
] = -1; 
 784     ::WinSetWindowText((HWND
)m_ahRadioButtons
[nItem
], rsLabel
.c_str()); 
 785 } // end of wxRadioBox::SetString 
 787 bool wxRadioBox::SetStringSelection(const wxString
& rsStr
) 
 789     int nSel 
= FindString(rsStr
); 
 798 } // end of wxRadioBox::SetStringSelection 
 800 bool wxRadioBox::Show(bool bShow
) 
 802     if (!wxControl::Show(bShow
)) 
 805     for (unsigned int i 
= 0; i 
< m_nNoItems
; i
++) 
 807         ::WinShowWindow((HWND
)m_ahRadioButtons
[i
], (BOOL
)bShow
); 
 810 } // end of wxRadioBox::Show 
 812 // Show a specific button 
 813 bool wxRadioBox::Show(unsigned int nItem
, bool bShow
) 
 815     wxCHECK_MSG( IsValid(nItem
), false, 
 816                  wxT("invalid item in wxRadioBox::Show()") ); 
 818     ::WinShowWindow((HWND
)m_ahRadioButtons
[nItem
], bShow
); 
 821 } // end of wxRadioBox::Show 
 823 void wxRadioBox::SubclassRadioButton( 
 827     fnWndProcRadioBtn 
= (WXFARPROC
)::WinSubclassWindow(hWndBtn
, (PFNWP
)wxRadioBtnWndProc
); 
 828 } // end of wxRadioBox::SubclassRadioButton 
 830 MRESULT 
wxRadioBox::WindowProc( 
 836     return (wxControl::OS2WindowProc( uMsg
 
 840 } // end of wxRadioBox::WindowProc 
 842 // --------------------------------------------------------------------------- 
 843 // window proc for radio buttons 
 844 // --------------------------------------------------------------------------- 
 846 MRESULT 
wxRadioBtnWndProc( 
 857                 USHORT                  uKeyFlags 
= SHORT1FROMMP((MPARAM
)wParam
); 
 859                 if (!(uKeyFlags 
& KC_KEYUP
)) // Key Down event 
 861                     if (uKeyFlags 
& KC_VIRTUALKEY
) 
 863                         wxRadioBox
*             pRadiobox 
= (wxRadioBox 
*)::WinQueryWindowULong( hWnd
 
 866                         USHORT                  uVk 
= SHORT2FROMMP((MPARAM
)lParam
); 
 867                         bool                    bProcessed 
= true; 
 892                                 // Just to suppress the compiler warning 
 899                             int             nSelOld 
= pRadiobox
->GetSelection(); 
 900                             int             nSelNew 
= pRadiobox
->GetNextItem( nSelOld
 
 902                                                                              ,pRadiobox
->GetWindowStyleFlag() 
 905                             if (nSelNew 
!= nSelOld
) 
 907                                 pRadiobox
->SetSelection(nSelNew
); 
 910                                 // Emulate the button click 
 912                                 pRadiobox
->SendNotificationEvent(); 
 922     return fnWndProcRadioBtn( hWnd
 
 927 } // end of wxRadioBtnWndProc 
 929 MRESULT EXPENTRY 
wxRadioBoxWndProc( HWND hWnd
, 
 934     return (fnWndProcRadioBox( hWnd
, 
 939 } // end of wxRadioBoxWndProc 
 941 #endif // wxUSE_RADIOBOX