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"
21 #include "wx/wxchar.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()
79 m_isBeingDeleted
= true;
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
)
150 HWND hWndParent
= GetHwndOf(pParent
);
152 vColour
.Set(wxString(wxT("BLACK")));
153 m_backgroundColour
= pParent
->GetBackgroundColour();
154 m_nSelectedButton
= -1;
158 // Common initialization
160 if (!CreateControl( pParent
169 if (!OS2CreateControl( wxT("STATIC")
177 wxAssociateWinWithHandle(m_hWnd
, this);
180 // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows
182 m_nNoItems
= (unsigned int)nNum
;
183 SetMajorDim(nMajorDim
== 0 ? nNum
: nMajorDim
, lStyle
);
185 m_ahRadioButtons
= new WXHWND
[nNum
];
186 m_pnRadioWidth
= new int[nNum
];
187 m_pnRadioHeight
= new int[nNum
];
189 for (int i
= 0; i
< nNum
; i
++)
191 m_pnRadioWidth
[i
] = m_pnRadioHeight
[i
] = -1;
192 long lStyleBtn
= BS_AUTORADIOBUTTON
| WS_VISIBLE
;
193 int nNewId
= NewControlId();
196 lStyleBtn
|= WS_GROUP
| WS_TABSTOP
;
198 wxString sLabel
= ::wxPMTextToLabel(asChoices
[i
]);
200 HWND hWndBtn
= (WXHWND
)::WinCreateWindow ( hWndParent
,
215 lColor
= (LONG
)vColour
.GetPixel();
216 ::WinSetPresParam( hWndBtn
222 lColor
= (LONG
)m_backgroundColour
.GetPixel();
223 ::WinSetPresParam( hWndBtn
228 m_ahRadioButtons
[i
] = (WXHWND
)hWndBtn
;
229 SubclassRadioButton((WXHWND
)hWndBtn
);
230 wxAssociateWinWithHandle(hWndBtn
, this);
231 wxOS2SetFont( hWndBtn
234 ::WinSetWindowULong(hWndBtn
, QWL_USER
, (ULONG
)this);
235 m_aSubControls
.Add(nNewId
);
239 // Create a dummy control to end the group.
241 (void)::WinCreateWindow ( hWndParent
,
248 (HMENU
)NewControlId(),
252 fnWndProcRadioBox
= (WXFARPROC
)::WinSubclassWindow( GetHwnd()
253 ,(PFNWP
)wxRadioBoxWndProc
255 ::WinSetWindowULong(GetHwnd(), QWL_USER
, (ULONG
)this);
256 lColor
= (LONG
)vColour
.GetPixel();
257 ::WinSetPresParam( m_hWnd
263 lColor
= (LONG
)m_backgroundColour
.GetPixel();
264 ::WinSetPresParam( m_hWnd
278 } // end of wxRadioBox::Create
280 wxSize
wxRadioBox::DoGetBestSize() const
282 return (GetTotalButtonSize(GetMaxButtonSize()));
283 } // end of wxRadioBox::DoGetBestSize
285 void wxRadioBox::DoSetSize(
294 // Input parameters assume wxWidgets coordinate system
306 wxSize vMaxSize
= GetMaxButtonSize();
314 wxFont vFont
= GetFont();
316 m_nSizeFlags
= nSizeFlags
;
317 GetPosition( &nCurrentX
324 if (nX
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
326 if (nY
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
333 wxGetCharSize( m_hWnd
340 // Attempt to have a look coherent with other platforms: We compute the
341 // biggest toggle dim, then we align all items according this value.
343 vMaxSize
= GetMaxButtonSize();
344 nMaxWidth
= vMaxSize
.x
;
345 nMaxHeight
= vMaxSize
.y
;
347 vTotSize
= GetTotalButtonSize(vMaxSize
);
348 nTotWidth
= vTotSize
.x
;
349 nTotHeight
= vTotSize
.y
;
352 // Only change our width/height if asked for
356 if (nSizeFlags
& wxSIZE_AUTO_WIDTH
)
364 if (nSizeFlags
& wxSIZE_AUTO_HEIGHT
)
365 nHeight
= nTotHeight
;
367 nHeight
= nHeightOld
;
371 // Now convert to OS/2 coordinate system
373 wxWindowOS2
* pParent
= (wxWindowOS2
*)GetParent();
375 nYy
= GetOS2ParentHeight(pParent
) - nYy
- nHeight
;
379 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
380 nYy
= vRect
.yTop
- nYy
- nHeight
;
382 nYOffset
= nYy
+ nHeight
;
383 ::WinSetWindowPos( GetHwnd()
389 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
393 // Now position all the buttons: the current button will be put at
394 // wxPoint(x_offset, y_offset) and the new row/column will start at
395 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
396 // maxHeight) except for the buttons in the last column which should extend
397 // to the right border of radiobox and thus can be wider than this.
399 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
400 // left to right order and m_majorDim is the number of columns while
401 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
402 // m_majorDim is the number of rows.
405 nYOffset
-= (nMaxHeight
+ ((3*nCy1
)/2));
410 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
413 // The last button in the row may be wider than the other ones as the
414 // radiobox may be wider than the sum of the button widths (as it
415 // happens, for example, when the radiobox label is very long)
417 bool bIsLastInTheRow
;
419 if (m_windowStyle
& wxRA_SPECIFY_COLS
)
422 // Item is the last in its row if it is a multiple of the number of
423 // columns or if it is just the last item
427 bIsLastInTheRow
= ((n
% GetMajorDim()) == 0) || (n
== (int)m_nNoItems
);
429 else // winRA_SPECIFY_ROWS
432 // Item is the last in the row if it is in the last columns
434 bIsLastInTheRow
= i
>= (m_nNoItems
/GetMajorDim()) * GetMajorDim();
438 // Is this the start of new row/column?
440 if (i
&& (i
% GetMajorDim() == 0))
442 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
445 // Start of new column
448 nXOffset
+= nMaxWidth
+ nCx1
;
450 else // start of new row
453 nYOffset
-= nMaxHeight
;
454 if (m_pnRadioWidth
[0] > 0L)
464 // Make the button go to the end of radio box
466 nWidthBtn
= nStartX
+ nWidth
- nXOffset
- (2 * nCx1
);
467 if (nWidthBtn
< nMaxWidth
)
468 nWidthBtn
= nMaxWidth
;
473 // Normal button, always of the same size
475 nWidthBtn
= nMaxWidth
;
479 // Make all buttons of the same, maximal size - like this they
480 // cover the radiobox entirely and the radiobox tooltips are always
481 // shown (otherwise they are not when the mouse pointer is in the
482 // radiobox part not belonging to any radiobutton)
484 ::WinSetWindowPos( (HWND
)m_ahRadioButtons
[i
]
490 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
493 // Where do we put the next button?
495 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
500 nYOffset
-= nMaxHeight
;
501 if (m_pnRadioWidth
[0] > 0)
507 // To the right of this one
509 nXOffset
+= nWidthBtn
+ nCx1
;
512 } // end of wxRadioBox::DoSetSize
514 bool wxRadioBox::Enable(unsigned int nItem
, bool bEnable
)
516 wxCHECK_MSG( IsValid(nItem
), false,
517 wxT("invalid item in wxRadioBox::Enable()") );
519 ::WinEnableWindow((HWND
) m_ahRadioButtons
[nItem
], bEnable
);
521 } // end of wxRadioBox::Enable
523 bool wxRadioBox::Enable(bool bEnable
)
525 if ( !wxControl::Enable(bEnable
) )
527 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
528 ::WinEnableWindow((HWND
)m_ahRadioButtons
[i
], bEnable
);
530 } // end of wxRadioBox::Enable
532 unsigned int wxRadioBox::GetCount() const
535 } // end of wxRadioBox::GetCount
537 wxString
wxRadioBox::GetLabel(int nItem
) const
539 wxCHECK_MSG( IsValid(nItem
), wxEmptyString
, wxT("invalid radiobox index") );
541 return wxGetWindowText(m_ahRadioButtons
[nItem
]);
542 } // end of wxRadioBox::GetLabel
544 wxSize
wxRadioBox::GetMaxButtonSize() const
549 for (unsigned int i
= 0 ; i
< m_nNoItems
; i
++)
554 if (m_pnRadioWidth
[i
] < 0L)
556 GetTextExtent( wxGetWindowText(m_ahRadioButtons
[i
])
562 // Adjust the size to take into account the radio box itself
563 // FIXME this is totally bogus!
565 nWidth
+= RADIO_SIZE
;
571 nWidth
= m_pnRadioWidth
[i
];
572 nHeight
= m_pnRadioHeight
[i
];
574 if (nWidthMax
< nWidth
)
576 if (nHeightMax
< nHeight
)
577 nHeightMax
= nHeight
;
579 wxSize
maxsize( nWidthMax
, nHeightMax
);
581 } // end of wxRadioBox::GetMaxButtonSize
583 // Get single selection, for single choice list items
584 int wxRadioBox::GetSelection() const
586 return m_nSelectedButton
;
587 } // end of wxRadioBox::GetSelection
589 void wxRadioBox::GetSize( int* pnWidth
, int* pnHeight
) const
599 wxFindMaxSize( m_hWnd
, &vRect
);
601 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
602 wxFindMaxSize( m_ahRadioButtons
[i
], &vRect
);
605 *pnWidth
= vRect
.xRight
- vRect
.xLeft
;
607 *pnHeight
= vRect
.yTop
- vRect
.yBottom
;
608 } // end of wxRadioBox::GetSize
610 // Find string for position
611 wxString
wxRadioBox::GetString(unsigned int nNum
) const
613 wxCHECK_MSG( IsValid(nNum
), wxEmptyString
, wxT("invalid radiobox index") );
614 return wxGetWindowText(m_ahRadioButtons
[nNum
]);
615 } // end of wxRadioBox::GetString
617 // For single selection items only
618 wxString
wxRadioBox::GetStringSelection() const
621 int nSel
= GetSelection();
623 if (nSel
!= wxNOT_FOUND
)
624 sResult
= GetString(nSel
);
627 } // end of wxRadioBox::GetStringSelection
629 wxSize
wxRadioBox::GetTotalButtonSize( const wxSize
& rSizeBtn
) const
637 nCx1
= GetCharWidth();
638 nCy1
= GetCharHeight();
639 nHeight
= GetRowCount() * rSizeBtn
.y
+ (2 * nCy1
);
640 nWidth
= GetColumnCount() * (rSizeBtn
.x
+ nCx1
) + nCx1
;
643 // And also wide enough for its label
645 wxString sStr
= wxGetWindowText(GetHwnd());
652 nWidthLabel
+= 2*nCx1
;
654 if (nWidthLabel
> nWidth
)
655 nWidth
= nWidthLabel
;
657 wxSize
total( nWidth
, nHeight
);
659 } // end of wxRadioBox::GetTotalButtonSize
661 WXHBRUSH
wxRadioBox::OnCtlColor( WXHDC hwinDC
,
662 WXHWND
WXUNUSED(hWnd
),
663 WXUINT
WXUNUSED(uCtlColor
),
664 WXUINT
WXUNUSED(uMessage
),
665 WXWPARAM
WXUNUSED(wParam
),
666 WXLPARAM
WXUNUSED(lParam
) )
668 HPS hPS
= (HPS
)hwinDC
; // pass in a PS handle in OS/2
670 if (GetParent()->GetTransparentBackground())
671 ::GpiSetBackMix(hPS
, BM_LEAVEALONE
);
673 ::GpiSetBackMix(hPS
, BM_OVERPAINT
);
675 wxColour vColBack
= GetBackgroundColour();
677 ::GpiSetBackColor(hPS
, vColBack
.GetPixel());
678 ::GpiSetColor(hPS
, vColBack
.GetPixel());
680 wxBrush
* pBrush
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID
);
681 return ((WXHBRUSH
)pBrush
->GetResourceHandle());
682 } // end of wxRadioBox::OnCtlColor
684 bool wxRadioBox::OS2Command( WXUINT uCmd
,
687 int nSelectedButton
= -1;
689 if (uCmd
== BN_CLICKED
)
694 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
696 if (wId
== wxGetWindowId(m_ahRadioButtons
[i
]))
702 if (nSelectedButton
== -1)
709 if (nSelectedButton
!= m_nSelectedButton
)
711 m_nSelectedButton
= nSelectedButton
;
712 SendNotificationEvent();
718 } // end of wxRadioBox::OS2Command
720 void wxRadioBox::SendNotificationEvent()
722 wxCommandEvent
vEvent(
723 wxEVT_COMMAND_RADIOBOX_SELECTED
,
727 vEvent
.SetInt( m_nSelectedButton
);
728 vEvent
.SetString( GetString(m_nSelectedButton
) );
729 vEvent
.SetEventObject(this);
730 ProcessCommand(vEvent
);
731 } // end of wxRadioBox::SendNotificationEvent
733 void wxRadioBox::SetFocus()
737 if (m_nSelectedButton
== -1)
738 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[0]);
740 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[m_nSelectedButton
]);
742 } // end of wxRadioBox::SetFocus
744 bool wxRadioBox::SetFont(const wxFont
& rFont
)
746 if (!wxControl::SetFont(rFont
))
754 // Also set the font of our radio buttons
756 for (unsigned int n
= 0; n
< m_nNoItems
; n
++)
758 HWND hWndBtn
= (HWND
)m_ahRadioButtons
[n
];
760 wxOS2SetFont( hWndBtn
, rFont
);
761 ::WinInvalidateRect(hWndBtn
, NULL
, FALSE
);
764 } // end of wxRadioBox::SetFont
766 void wxRadioBox::SetSelection(
770 wxCHECK_RET( IsValid(nNum
), wxT("invalid radiobox index") );
772 if ( IsValid(m_nSelectedButton
) )
773 ::WinSendMsg((HWND
)m_ahRadioButtons
[m_nSelectedButton
], BM_SETCHECK
, (MPARAM
)0, (MPARAM
)0);
775 ::WinSendMsg((HWND
)m_ahRadioButtons
[nNum
], BM_SETCHECK
, (MPARAM
)1, (MPARAM
)0);
776 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[nNum
]);
777 m_nSelectedButton
= nNum
;
778 } // end of wxRadioBox::SetSelection
780 void wxRadioBox::SetString(unsigned int nItem
, const wxString
& rsLabel
)
782 wxCHECK_RET( IsValid(nItem
), wxT("invalid radiobox index") );
784 m_pnRadioWidth
[nItem
] = m_pnRadioHeight
[nItem
] = -1;
785 ::WinSetWindowText((HWND
)m_ahRadioButtons
[nItem
], (PSZ
)rsLabel
.c_str());
786 } // end of wxRadioBox::SetString
788 bool wxRadioBox::SetStringSelection(const wxString
& rsStr
)
790 int nSel
= FindString(rsStr
);
799 } // end of wxRadioBox::SetStringSelection
801 bool wxRadioBox::Show(bool bShow
)
803 if (!wxControl::Show(bShow
))
806 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
808 ::WinShowWindow((HWND
)m_ahRadioButtons
[i
], (BOOL
)bShow
);
811 } // end of wxRadioBox::Show
813 // Show a specific button
814 bool wxRadioBox::Show(unsigned int nItem
, bool bShow
)
816 wxCHECK_MSG( IsValid(nItem
), false,
817 wxT("invalid item in wxRadioBox::Show()") );
819 ::WinShowWindow((HWND
)m_ahRadioButtons
[nItem
], bShow
);
822 } // end of wxRadioBox::Show
824 void wxRadioBox::SubclassRadioButton(
828 fnWndProcRadioBtn
= (WXFARPROC
)::WinSubclassWindow(hWndBtn
, (PFNWP
)wxRadioBtnWndProc
);
829 } // end of wxRadioBox::SubclassRadioButton
831 MRESULT
wxRadioBox::WindowProc(
837 return (wxControl::OS2WindowProc( uMsg
841 } // end of wxRadioBox::WindowProc
843 // ---------------------------------------------------------------------------
844 // window proc for radio buttons
845 // ---------------------------------------------------------------------------
847 MRESULT
wxRadioBtnWndProc(
858 USHORT uKeyFlags
= SHORT1FROMMP((MPARAM
)wParam
);
860 if (!(uKeyFlags
& KC_KEYUP
)) // Key Down event
862 if (uKeyFlags
& KC_VIRTUALKEY
)
864 wxRadioBox
* pRadiobox
= (wxRadioBox
*)::WinQueryWindowULong( hWnd
867 USHORT uVk
= SHORT2FROMMP((MPARAM
)lParam
);
868 bool bProcessed
= true;
893 // Just to suppress the compiler warning
900 int nSelOld
= pRadiobox
->GetSelection();
901 int nSelNew
= pRadiobox
->GetNextItem( nSelOld
903 ,pRadiobox
->GetWindowStyleFlag()
906 if (nSelNew
!= nSelOld
)
908 pRadiobox
->SetSelection(nSelNew
);
911 // Emulate the button click
913 pRadiobox
->SendNotificationEvent();
923 return fnWndProcRadioBtn( hWnd
928 } // end of wxRadioBtnWndProc
930 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
,
935 return (fnWndProcRadioBox( hWnd
,
940 } // end of wxRadioBoxWndProc
942 #endif // wxUSE_RADIOBOX