1/////////////////////////////////////////////////////////////////////////////
2// Name:        src/os2/radiobox.cpp
3// Purpose:     wxRadioBox
4// Author:      David Webster
5// Modified by:
6// Created:     10/12/99
7// RCS-ID:      $Id: radiobox.cpp 39615 2006-06-07 13:26:00Z 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#if wxUSE_RADIOBOX
16
17#include "wx/radiobox.h"
18
19#ifndef WX_PRECOMP
20    #include <stdio.h>
21    #include "wx/wxchar.h"
22    #include "wx/string.h"
23    #include "wx/bitmap.h"
24    #include "wx/brush.h"
25#endif
26
27#include "wx/os2/private.h"
28
29IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
30
31// ---------------------------------------------------------------------------
32// private functions
33// ---------------------------------------------------------------------------
34
35// wnd proc for radio buttons
36MRESULT EXPENTRY wxRadioBtnWndProc( HWND hWnd
37                                   ,UINT uMessage
38                                   ,MPARAM wParam
39                                   ,MPARAM lParam
40                                  );
41MRESULT EXPENTRY wxRadioBoxWndProc( HWND   hWnd
42                                   ,UINT   uMessage
43                                   ,MPARAM wParam
44                                   ,MPARAM lParam
45                                  );
46
47// ---------------------------------------------------------------------------
48// global vars
49// ---------------------------------------------------------------------------
50
51extern void  wxAssociateWinWithHandle( HWND         hWnd
52                                      ,wxWindowOS2* pWin
53                                     );
54extern void wxRemoveHandleAssociation( wxWindowOS2 *pWin );
55// the pointer to standard radio button & box wnd procs
56static WXFARPROC                    fnWndProcRadioBtn = NULL;
57static WXFARPROC                    fnWndProcRadioBox = NULL;
58
59// ===========================================================================
60// implementation
61// ===========================================================================
62
63// ---------------------------------------------------------------------------
64// wxRadioBox
65// ---------------------------------------------------------------------------
66
67// Radio box item
68wxRadioBox::wxRadioBox()
69{
70    m_nSelectedButton = -1;
71    m_nNoItems = 0;
72    m_ahRadioButtons = NULL;
73    m_pnRadioWidth = NULL;
74    m_pnRadioHeight = NULL;
75} // end of wxRadioBox::wxRadioBox
76
77wxRadioBox::~wxRadioBox()
78{
79    m_isBeingDeleted = true;
80
81    if (m_hWnd)
82        wxRemoveHandleAssociation(this);
83    if (m_ahRadioButtons)
84    {
85        for (unsigned int i = 0; i < m_nNoItems; i++)
86        {
87            wxWindow* pWin = wxFindWinFromHandle((WXHWND)m_ahRadioButtons[i]);
88            wxRemoveHandleAssociation(pWin);
89
90            ::WinDestroyWindow((HWND)m_ahRadioButtons[i]);
91    }
92        delete[] m_ahRadioButtons;
93    }
94    if (m_pnRadioWidth)
95        delete[] m_pnRadioWidth;
96    if (m_pnRadioHeight)
97        delete[] m_pnRadioHeight;
98} // end of wxRadioBox::~wxRadioBox
99
100void wxRadioBox::Command ( wxCommandEvent& rEvent )
101{
102    SetSelection (rEvent.GetInt());
103    ProcessCommand(rEvent);
104} // end of wxRadioBox::Command
105
106bool wxRadioBox::ContainsHWND( WXHWND hWnd ) const
107{
108    unsigned int nCount = GetCount();
109    unsigned int i;
110
111    for (i = 0; i < nCount; i++)
112    {
113        if (GetRadioButtons()[i] == hWnd)
114            return true;
115    }
116    return false;
117} // end of wxRadioBox::ContainsHWND
118
119bool wxRadioBox::Create( wxWindow* pParent,
120                         wxWindowID vId,
121                         const wxString& rsTitle,
122                         const wxPoint& rPos,
123                         const wxSize& rSize,
124                         const wxArrayString& asChoices,
125                         int nMajorDim,
126                         long lStyle,
127                         const wxValidator& rVal,
128                         const wxString& rsName )
129{
130    wxCArrayString chs(asChoices);
131
132    return Create(pParent, vId, rsTitle, rPos, rSize, chs.GetCount(),
133                  chs.GetStrings(), nMajorDim, lStyle, rVal, rsName);
134}
135
136bool wxRadioBox::Create( wxWindow* pParent,
137                         wxWindowID vId,
138                         const wxString& rsTitle,
139                         const wxPoint& rPos,
140                         const wxSize& rSize,
141                         int nNum,
142                         const wxString asChoices[],
143                         int nMajorDim,
144                         long lStyle,
145                         const wxValidator& rVal,
146                         const wxString& rsName )
147{
148    wxColour vColour(*wxBLACK);
149    LONG     lColor;
150    HWND     hWndParent = GetHwndOf(pParent);
151
152    m_backgroundColour = pParent->GetBackgroundColour();
153    m_nSelectedButton = -1;
154    m_nNoItems = 0;
155
156    //
157    // Common initialization
158    //
159    if (!CreateControl( pParent
160                       ,vId
161                       ,rPos
162                       ,rSize
163                       ,lStyle
164                       ,rVal
165                       ,rsName
166                      ))
167        return false;
168    if (!OS2CreateControl( wxT("STATIC")
169                          ,SS_GROUPBOX
170                          ,rPos
171                          ,rSize
172                          ,rsTitle
173                         ))
174        return false;
175
176    wxAssociateWinWithHandle(m_hWnd, this);
177
178    //
179    // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows
180    //
181    m_nNoItems = (unsigned int)nNum;
182    SetMajorDim(nMajorDim == 0 ? nNum : nMajorDim, lStyle);
183
184    m_ahRadioButtons = new WXHWND[nNum];
185    m_pnRadioWidth   = new int[nNum];
186    m_pnRadioHeight  = new int[nNum];
187
188    for (int i = 0; i < nNum; i++)
189    {
190        m_pnRadioWidth[i] = m_pnRadioHeight[i] = -1;
191        long                        lStyleBtn = BS_AUTORADIOBUTTON | WS_VISIBLE;
192        int                         nNewId = NewControlId();
193
194        if (i == 0)
195            lStyleBtn |= WS_GROUP | WS_TABSTOP;
196
197        wxString                    sLabel = ::wxPMTextToLabel(asChoices[i]);
198
199        HWND                        hWndBtn = (WXHWND)::WinCreateWindow ( hWndParent,
200                                                                          WC_BUTTON,
201                                                                          sLabel.c_str(),
202                                                                          lStyleBtn,
203                                                                          0, 0, 0, 0,
204                                                                          hWndParent,
205                                                                          HWND_BOTTOM,
206                                                                          (HMENU)nNewId,
207                                                                          NULL,
208                                                                          NULL
209                                                                        );
210        if (!hWndBtn)
211        {
212            return false;
213        }
214        lColor = (LONG)vColour.GetPixel();
215        ::WinSetPresParam( hWndBtn
216                          ,PP_FOREGROUNDCOLOR
217                          ,sizeof(LONG)
218                          ,(PVOID)&lColor
219                         );
220
221        lColor = (LONG)m_backgroundColour.GetPixel();
222        ::WinSetPresParam( hWndBtn
223                          ,PP_BACKGROUNDCOLOR
224                          ,sizeof(LONG)
225                          ,(PVOID)&lColor
226                         );
227        m_ahRadioButtons[i] = (WXHWND)hWndBtn;
228        SubclassRadioButton((WXHWND)hWndBtn);
229        wxAssociateWinWithHandle(hWndBtn, this);
230        wxOS2SetFont( hWndBtn
231                     ,*wxSMALL_FONT
232                    );
233        ::WinSetWindowULong(hWndBtn, QWL_USER, (ULONG)this);
234        m_aSubControls.Add(nNewId);
235    }
236
237    //
238    // Create a dummy control to end the group.
239    //
240    (void)::WinCreateWindow ( hWndParent,
241                              WC_BUTTON,
242                              "",
243                              WS_GROUP,
244                              0, 0, 0, 0,
245                              hWndParent,
246                              HWND_TOP,
247                              (HMENU)NewControlId(),
248                              NULL,
249                              NULL
250                            );
251    fnWndProcRadioBox = (WXFARPROC)::WinSubclassWindow( GetHwnd()
252                                                       ,(PFNWP)wxRadioBoxWndProc
253                                                      );
254    ::WinSetWindowULong(GetHwnd(), QWL_USER, (ULONG)this);
255    lColor = (LONG)vColour.GetPixel();
256    ::WinSetPresParam( m_hWnd
257                      ,PP_FOREGROUNDCOLOR
258                      ,sizeof(LONG)
259                      ,(PVOID)&lColor
260                     );
261
262    lColor = (LONG)m_backgroundColour.GetPixel();
263    ::WinSetPresParam( m_hWnd
264                      ,PP_BACKGROUNDCOLOR
265                      ,sizeof(LONG)
266                      ,(PVOID)&lColor
267                     );
268    SetXComp(0);
269    SetYComp(0);
270    SetSelection(0);
271    SetSize( rPos.x
272            ,rPos.y
273            ,rSize.x
274            ,rSize.y
275           );
276    return true;
277} // end of wxRadioBox::Create
278
279wxSize wxRadioBox::DoGetBestSize() const
280{
281    return (GetTotalButtonSize(GetMaxButtonSize()));
282} // end of wxRadioBox::DoGetBestSize
283
284void wxRadioBox::DoSetSize(
285  int                               nX
286, int                               nY
287, int                               nWidth
288, int                               nHeight
289, int                               nSizeFlags
290)
291{
292    //
293    // Input parameters assume wxWidgets coordinate system
294    //
295    int                             nCurrentX;
296    int                             nCurrentY;
297    int                             nWidthOld;
298    int                             nHeightOld;
299    int                             nXx = nX;
300    int                             nYy = nY;
301    int                             nXOffset = nXx;
302    int                             nYOffset = nYy;
303    int                             nCx1;
304    int                             nCy1;
305    wxSize                          vMaxSize = GetMaxButtonSize();
306    int                             nMaxWidth;
307    int                             nMaxHeight;
308    wxSize                          vTotSize;
309    int                             nTotWidth;
310    int                             nTotHeight;
311    int                             nStartX;
312    int                             nStartY;
313    wxFont                          vFont = GetFont();
314
315    m_nSizeFlags = nSizeFlags;
316    GetPosition( &nCurrentX
317                ,&nCurrentY
318               );
319    GetSize( &nWidthOld
320            ,&nHeightOld
321           );
322
323    if (nX == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
324        nXx = nCurrentX;
325    if (nY == wxDefaultCoord && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
326        nYy = nCurrentY;
327    if (nYy < 0)
328        nYy = 0;
329    if (nXx < 0)
330        nXx = 0;
331
332    wxGetCharSize( m_hWnd
333                  ,&nCx1
334                  ,&nCy1
335                  ,&vFont
336                 );
337
338    //
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.
341    //
342    vMaxSize   = GetMaxButtonSize();
343    nMaxWidth  = vMaxSize.x;
344    nMaxHeight = vMaxSize.y;
345
346    vTotSize   = GetTotalButtonSize(vMaxSize);
347    nTotWidth  = vTotSize.x;
348    nTotHeight = vTotSize.y;
349
350    //
351    // Only change our width/height if asked for
352    //
353    if (nWidth == -1)
354    {
355        if (nSizeFlags & wxSIZE_AUTO_WIDTH )
356            nWidth = nTotWidth;
357        else
358            nWidth = nWidthOld;
359    }
360
361    if (nHeight == -1)
362    {
363        if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
364            nHeight = nTotHeight;
365        else
366            nHeight = nHeightOld;
367    }
368
369    //
370    // Now convert to OS/2 coordinate system
371    //
372    wxWindowOS2*                    pParent = (wxWindowOS2*)GetParent();
373    if (pParent)
374        nYy = GetOS2ParentHeight(pParent) - nYy - nHeight;
375    else
376    {
377        RECTL                       vRect;
378        ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
379        nYy = vRect.yTop - nYy - nHeight;
380    }
381    nYOffset = nYy + nHeight;
382    ::WinSetWindowPos( GetHwnd()
383                      ,HWND_TOP
384                      ,(LONG)nXx
385                      ,(LONG)nYy
386                      ,(LONG)nWidth
387                      ,(LONG)nHeight
388                      ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
389                     );
390
391    //
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.
397    //
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.
402    //
403    nXOffset += nCx1;
404    nYOffset -= (nMaxHeight + ((3*nCy1)/2));
405
406    nStartX = nXOffset;
407    nStartY = nYOffset;
408
409    for (unsigned int i = 0; i < m_nNoItems; i++)
410    {
411        //
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)
415        //
416        bool bIsLastInTheRow;
417
418        if (m_windowStyle & wxRA_SPECIFY_COLS)
419        {
420            //
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
423            //
424            int                  n = i + 1;
425
426            bIsLastInTheRow = ((n % GetMajorDim()) == 0) || (n == (int)m_nNoItems);
427        }
428        else // winRA_SPECIFY_ROWS
429        {
430            //
431            // Item is the last in the row if it is in the last columns
432            //
433            bIsLastInTheRow = i >= (m_nNoItems/GetMajorDim()) * GetMajorDim();
434        }
435
436        //
437        // Is this the start of new row/column?
438        //
439        if (i && (i % GetMajorDim() == 0))
440        {
441            if (m_windowStyle & wxRA_SPECIFY_ROWS)
442            {
443                //
444                // Start of new column
445                //
446                nYOffset = nStartY;
447                nXOffset += nMaxWidth + nCx1;
448            }
449            else // start of new row
450            {
451                nXOffset = nStartX;
452                nYOffset -= nMaxHeight;
453                if (m_pnRadioWidth[0] > 0L)
454                    nYOffset -= nCy1/2;
455            }
456        }
457
458        int                      nWidthBtn;
459
460        if (bIsLastInTheRow)
461        {
462            //
463            // Make the button go to the end of radio box
464            //
465            nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
466            if (nWidthBtn < nMaxWidth)
467                nWidthBtn = nMaxWidth;
468        }
469        else
470        {
471            //
472            // Normal button, always of the same size
473            //
474            nWidthBtn = nMaxWidth;
475        }
476
477        //
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)
482        //
483        ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
484                          ,HWND_BOTTOM
485                          ,(LONG)nXOffset
486                          ,(LONG)nYOffset
487                          ,(LONG)nWidthBtn
488                          ,(LONG)nMaxHeight
489                          ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
490                         );
491        //
492        // Where do we put the next button?
493        //
494        if (m_windowStyle & wxRA_SPECIFY_ROWS)
495        {
496            //
497            // Below this one
498            //
499            nYOffset -= nMaxHeight;
500            if (m_pnRadioWidth[0] > 0)
501                nYOffset -= nCy1/2;
502        }
503        else
504        {
505            //
506            // To the right of this one
507            //
508            nXOffset += nWidthBtn + nCx1;
509        }
510    }
511} // end of wxRadioBox::DoSetSize
512
513bool wxRadioBox::Enable(unsigned int nItem, bool bEnable)
514{
515    wxCHECK_MSG( IsValid(nItem), false,
516                 wxT("invalid item in wxRadioBox::Enable()") );
517
518    ::WinEnableWindow((HWND) m_ahRadioButtons[nItem], bEnable);
519    return true;
520} // end of wxRadioBox::Enable
521
522bool wxRadioBox::Enable(bool bEnable)
523{
524    if ( !wxControl::Enable(bEnable) )
525        return false;
526    for (unsigned int i = 0; i < m_nNoItems; i++)
527        ::WinEnableWindow((HWND)m_ahRadioButtons[i], bEnable);
528    return true;
529} // end of wxRadioBox::Enable
530
531unsigned int wxRadioBox::GetCount() const
532{
533    return m_nNoItems;
534} // end of wxRadioBox::GetCount
535
536wxString wxRadioBox::GetLabel(int nItem) const
537{
538    wxCHECK_MSG( IsValid(nItem), wxEmptyString, wxT("invalid radiobox index") );
539
540    return wxGetWindowText(m_ahRadioButtons[nItem]);
541} // end of wxRadioBox::GetLabel
542
543wxSize wxRadioBox::GetMaxButtonSize() const
544{
545    int nWidthMax = 0;
546    int nHeightMax = 0;
547
548    for (unsigned int i = 0 ; i < m_nNoItems; i++)
549    {
550        int nWidth;
551        int nHeight;
552
553        if (m_pnRadioWidth[i] < 0L)
554        {
555            GetTextExtent( wxGetWindowText(m_ahRadioButtons[i])
556                          ,&nWidth
557                          ,&nHeight
558                         );
559
560            //
561            // Adjust the size to take into account the radio box itself
562            // FIXME this is totally bogus!
563            //
564            nWidth  += RADIO_SIZE;
565            nHeight *= 3;
566            nHeight /= 2;
567        }
568        else
569        {
570            nWidth  = m_pnRadioWidth[i];
571            nHeight = m_pnRadioHeight[i];
572        }
573        if (nWidthMax < nWidth )
574            nWidthMax = nWidth;
575        if (nHeightMax < nHeight )
576            nHeightMax = nHeight;
577    }
578    wxSize maxsize( nWidthMax, nHeightMax);
579    return maxsize;
580} // end of wxRadioBox::GetMaxButtonSize
581
582// Get single selection, for single choice list items
583int wxRadioBox::GetSelection() const
584{
585    return m_nSelectedButton;
586} // end of wxRadioBox::GetSelection
587
588void wxRadioBox::GetSize( int* pnWidth, int* pnHeight ) const
589{
590    RECT vRect;
591
592    vRect.xLeft   = -1;
593    vRect.xRight  = -1;
594    vRect.yTop    = -1;
595    vRect.yBottom = -1;
596
597    if (m_hWnd)
598        wxFindMaxSize( m_hWnd, &vRect );
599
600    for (unsigned int i = 0; i < m_nNoItems; i++)
601        wxFindMaxSize( m_ahRadioButtons[i], &vRect );
602
603    if (pnWidth)
604        *pnWidth  = vRect.xRight - vRect.xLeft;
605    if (pnHeight)
606        *pnHeight = vRect.yTop - vRect.yBottom;
607} // end of wxRadioBox::GetSize
608
609// Find string for position
610wxString wxRadioBox::GetString(unsigned int nNum) const
611{
612    wxCHECK_MSG( IsValid(nNum), wxEmptyString, wxT("invalid radiobox index") );
613    return wxGetWindowText(m_ahRadioButtons[nNum]);
614} // end of wxRadioBox::GetString
615
616// For single selection items only
617wxString wxRadioBox::GetStringSelection() const
618{
619    wxString sResult;
620    int nSel = GetSelection();
621
622    if (nSel != wxNOT_FOUND)
623        sResult = GetString(nSel);
624
625    return sResult;
626} // end of wxRadioBox::GetStringSelection
627
628wxSize wxRadioBox::GetTotalButtonSize( const wxSize& rSizeBtn ) const
629{
630    int    nCx1;
631    int    nCy1;
632    int    nHeight;
633    int    nWidth;
634    int    nWidthLabel = 0;
635
636    nCx1 = GetCharWidth();
637    nCy1 = GetCharHeight();
638    nHeight = GetRowCount() * rSizeBtn.y + (2 * nCy1);
639    nWidth  = GetColumnCount() * (rSizeBtn.x + nCx1) + nCx1;
640
641    //
642    // And also wide enough for its label
643    //
644    wxString sStr = wxGetWindowText(GetHwnd());
645    if (!sStr.empty())
646    {
647        GetTextExtent( sStr
648                      ,&nWidthLabel
649                      ,NULL
650                     );
651        nWidthLabel += 2*nCx1;
652    }
653    if (nWidthLabel > nWidth)
654        nWidth = nWidthLabel;
655
656    wxSize total( nWidth, nHeight );
657    return total;
658} // end of wxRadioBox::GetTotalButtonSize
659
660WXHBRUSH wxRadioBox::OnCtlColor( WXHDC    hwinDC,
661                                 WXHWND   WXUNUSED(hWnd),
662                                 WXUINT   WXUNUSED(uCtlColor),
663                                 WXUINT   WXUNUSED(uMessage),
664                                 WXWPARAM WXUNUSED(wParam),
665                                 WXLPARAM WXUNUSED(lParam) )
666{
667    HPS hPS = (HPS)hwinDC; // pass in a PS handle in OS/2
668
669    if (GetParent()->GetTransparentBackground())
670        ::GpiSetBackMix(hPS, BM_LEAVEALONE);
671    else
672        ::GpiSetBackMix(hPS, BM_OVERPAINT);
673
674    wxColour vColBack = GetBackgroundColour();
675
676    ::GpiSetBackColor(hPS, vColBack.GetPixel());
677    ::GpiSetColor(hPS, vColBack.GetPixel());
678
679    wxBrush* pBrush = wxTheBrushList->FindOrCreateBrush( vColBack, wxSOLID );
680    return ((WXHBRUSH)pBrush->GetResourceHandle());
681} // end of wxRadioBox::OnCtlColor
682
683bool wxRadioBox::OS2Command( WXUINT uCmd,
684                             WXWORD wId)
685{
686    int nSelectedButton = -1;
687
688    if (uCmd == BN_CLICKED)
689    {
690        if (wId == GetId())
691            return true;
692
693        for (unsigned int i = 0; i < m_nNoItems; i++)
694        {
695            if (wId == wxGetWindowId(m_ahRadioButtons[i]))
696            {
697                nSelectedButton = i;
698                break;
699            }
700        }
701        if (nSelectedButton == -1)
702        {
703            //
704            // Just ignore it
705            //
706            return false;
707        }
708        if (nSelectedButton != m_nSelectedButton)
709        {
710            m_nSelectedButton = nSelectedButton;
711            SendNotificationEvent();
712        }
713        return true;
714    }
715    else
716        return false;
717} // end of wxRadioBox::OS2Command
718
719void wxRadioBox::SendNotificationEvent()
720{
721    wxCommandEvent vEvent(
722                       wxEVT_COMMAND_RADIOBOX_SELECTED,
723                       m_windowId
724                   );
725
726    vEvent.SetInt( m_nSelectedButton );
727    vEvent.SetString( GetString(m_nSelectedButton) );
728    vEvent.SetEventObject(this);
729    ProcessCommand(vEvent);
730} // end of wxRadioBox::SendNotificationEvent
731
732void wxRadioBox::SetFocus()
733{
734    if (m_nNoItems > 0)
735    {
736        if (m_nSelectedButton == -1)
737            ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[0]);
738        else
739            ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[m_nSelectedButton]);
740    }
741} // end of wxRadioBox::SetFocus
742
743bool wxRadioBox::SetFont(const wxFont& rFont)
744{
745    if (!wxControl::SetFont(rFont))
746    {
747        //
748        // Nothing to do
749        //
750        return false;
751    }
752    //
753    // Also set the font of our radio buttons
754    //
755    for (unsigned int n = 0; n < m_nNoItems; n++)
756    {
757        HWND hWndBtn = (HWND)m_ahRadioButtons[n];
758
759        wxOS2SetFont( hWndBtn, rFont );
760        ::WinInvalidateRect(hWndBtn, NULL, FALSE);
761    }
762    return true;
763} // end of wxRadioBox::SetFont
764
765void wxRadioBox::SetSelection(
766  int                               nNum
767)
768{
769    wxCHECK_RET( IsValid(nNum), wxT("invalid radiobox index") );
770
771    if ( IsValid(m_nSelectedButton) )
772        ::WinSendMsg((HWND)m_ahRadioButtons[m_nSelectedButton], BM_SETCHECK, (MPARAM)0, (MPARAM)0);
773
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
778
779void wxRadioBox::SetString(unsigned int nItem, const wxString& rsLabel)
780{
781    wxCHECK_RET( IsValid(nItem), wxT("invalid radiobox index") );
782
783    m_pnRadioWidth[nItem] = m_pnRadioHeight[nItem] = -1;
784    ::WinSetWindowText((HWND)m_ahRadioButtons[nItem], (PSZ)rsLabel.c_str());
785} // end of wxRadioBox::SetString
786
787bool wxRadioBox::SetStringSelection(const wxString& rsStr)
788{
789    int nSel = FindString(rsStr);
790
791    if (nSel > -1)
792    {
793        SetSelection(nSel);
794        return true;
795    }
796    else
797        return false;
798} // end of wxRadioBox::SetStringSelection
799
800bool wxRadioBox::Show(bool bShow)
801{
802    if (!wxControl::Show(bShow))
803        return false;
804
805    for (unsigned int i = 0; i < m_nNoItems; i++)
806    {
807        ::WinShowWindow((HWND)m_ahRadioButtons[i], (BOOL)bShow);
808    }
809    return true;
810} // end of wxRadioBox::Show
811
812// Show a specific button
813bool wxRadioBox::Show(unsigned int nItem, bool bShow)
814{
815    wxCHECK_MSG( IsValid(nItem), false,
816                 wxT("invalid item in wxRadioBox::Show()") );
817
818    ::WinShowWindow((HWND)m_ahRadioButtons[nItem], bShow);
819
820    return true;
821} // end of wxRadioBox::Show
822
823void wxRadioBox::SubclassRadioButton(
824  WXHWND                            hWndBtn
825)
826{
827    fnWndProcRadioBtn = (WXFARPROC)::WinSubclassWindow(hWndBtn, (PFNWP)wxRadioBtnWndProc);
828} // end of wxRadioBox::SubclassRadioButton
829
830MRESULT wxRadioBox::WindowProc(
831  WXUINT                            uMsg
832, WXWPARAM                          wParam
833, WXLPARAM                          lParam
834)
835{
836    return (wxControl::OS2WindowProc( uMsg
837                                     ,wParam
838                                     ,lParam
839                                    ));
840} // end of wxRadioBox::WindowProc
841
842// ---------------------------------------------------------------------------
843// window proc for radio buttons
844// ---------------------------------------------------------------------------
845
846MRESULT wxRadioBtnWndProc(
847  HWND                              hWnd
848, UINT                              uMessage
849, MPARAM                            wParam
850, MPARAM                            lParam
851)
852{
853    switch (uMessage)
854    {
855        case WM_CHAR:
856            {
857                USHORT                  uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
858
859                if (!(uKeyFlags & KC_KEYUP)) // Key Down event
860                {
861                    if (uKeyFlags & KC_VIRTUALKEY)
862                    {
863                        wxRadioBox*             pRadiobox = (wxRadioBox *)::WinQueryWindowULong( hWnd
864                                                                                                ,QWL_USER
865                                                                                               );
866                        USHORT                  uVk = SHORT2FROMMP((MPARAM)lParam);
867                        bool                    bProcessed = true;
868                        wxDirection             eDir;
869
870                        switch(uVk)
871                        {
872                            case VK_LEFT:
873                                eDir = wxLEFT;
874                                break;
875
876                            case VK_RIGHT:
877                                eDir = wxRIGHT;
878                                break;
879
880                            case VK_DOWN:
881                                eDir = wxDOWN;
882                                break;
883
884                            case VK_UP:
885                                eDir = wxUP;
886                                break;
887
888                            default:
889                                bProcessed = false;
890
891                                //
892                                // Just to suppress the compiler warning
893                                //
894                                eDir = wxALL;
895                        }
896
897                        if (bProcessed)
898                        {
899                            int             nSelOld = pRadiobox->GetSelection();
900                            int             nSelNew = pRadiobox->GetNextItem( nSelOld
901                                                                             ,eDir
902                                                                             ,pRadiobox->GetWindowStyleFlag()
903                                                                            );
904
905                            if (nSelNew != nSelOld)
906                            {
907                                pRadiobox->SetSelection(nSelNew);
908
909                                //
910                                // Emulate the button click
911                                //
912                                pRadiobox->SendNotificationEvent();
913                                return 0;
914                            }
915                        }
916                    }
917                }
918            }
919            break;
920    }
921
922    return fnWndProcRadioBtn( hWnd
923                             ,(ULONG)uMessage
924                             ,(MPARAM)wParam
925                             ,(MPARAM)lParam
926                            );
927} // end of wxRadioBtnWndProc
928
929MRESULT EXPENTRY wxRadioBoxWndProc( HWND hWnd,
930                                    UINT uMessage,
931                                    MPARAM wParam,
932                                    MPARAM lParam )
933{
934    return (fnWndProcRadioBox( hWnd,
935                               (ULONG)uMessage,
936                               (MPARAM)wParam,
937                               (MPARAM)lParam )
938           );
939} // end of wxRadioBoxWndProc
940
941#endif // wxUSE_RADIOBOX
942