1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/radiobox.cpp
4 // Author: David Webster
7 // Copyright: (c) David Webster
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
16 #include "wx/radiobox.h"
21 #include "wx/string.h"
22 #include "wx/bitmap.h"
26 #include "wx/os2/private.h"
28 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
30 // ---------------------------------------------------------------------------
32 // ---------------------------------------------------------------------------
34 // wnd proc for radio buttons
35 MRESULT EXPENTRY
wxRadioBtnWndProc( HWND hWnd
40 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
46 // ---------------------------------------------------------------------------
48 // ---------------------------------------------------------------------------
50 extern void wxAssociateWinWithHandle( HWND hWnd
53 extern void wxRemoveHandleAssociation( wxWindowOS2
*pWin
);
54 // the pointer to standard radio button & box wnd procs
55 static WXFARPROC fnWndProcRadioBtn
= NULL
;
56 static WXFARPROC fnWndProcRadioBox
= NULL
;
58 // ===========================================================================
60 // ===========================================================================
62 // ---------------------------------------------------------------------------
64 // ---------------------------------------------------------------------------
67 wxRadioBox::wxRadioBox()
69 m_nSelectedButton
= -1;
71 m_ahRadioButtons
= NULL
;
72 m_pnRadioWidth
= NULL
;
73 m_pnRadioHeight
= NULL
;
74 } // end of wxRadioBox::wxRadioBox
76 wxRadioBox::~wxRadioBox()
81 wxRemoveHandleAssociation(this);
84 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
86 wxWindow
* pWin
= wxFindWinFromHandle((WXHWND
)m_ahRadioButtons
[i
]);
87 wxRemoveHandleAssociation(pWin
);
89 ::WinDestroyWindow((HWND
)m_ahRadioButtons
[i
]);
91 delete[] m_ahRadioButtons
;
94 delete[] m_pnRadioWidth
;
96 delete[] m_pnRadioHeight
;
97 } // end of wxRadioBox::~wxRadioBox
99 void wxRadioBox::Command ( wxCommandEvent
& rEvent
)
101 SetSelection (rEvent
.GetInt());
102 ProcessCommand(rEvent
);
103 } // end of wxRadioBox::Command
105 bool wxRadioBox::ContainsHWND( WXHWND hWnd
) const
107 unsigned int nCount
= GetCount();
110 for (i
= 0; i
< nCount
; i
++)
112 if (GetRadioButtons()[i
] == hWnd
)
116 } // end of wxRadioBox::ContainsHWND
118 bool wxRadioBox::Create( wxWindow
* pParent
,
120 const wxString
& rsTitle
,
123 const wxArrayString
& asChoices
,
126 const wxValidator
& rVal
,
127 const wxString
& rsName
)
129 wxCArrayString
chs(asChoices
);
131 return Create(pParent
, vId
, rsTitle
, rPos
, rSize
, chs
.GetCount(),
132 chs
.GetStrings(), nMajorDim
, lStyle
, rVal
, rsName
);
135 bool wxRadioBox::Create( wxWindow
* pParent
,
137 const wxString
& rsTitle
,
141 const wxString asChoices
[],
144 const wxValidator
& rVal
,
145 const wxString
& rsName
)
147 wxColour
vColour(*wxBLACK
);
149 HWND hWndParent
= GetHwndOf(pParent
);
151 m_backgroundColour
= pParent
->GetBackgroundColour();
152 m_nSelectedButton
= -1;
156 // Common initialization
158 if (!CreateControl( pParent
167 if (!OS2CreateControl( wxT("STATIC")
175 wxAssociateWinWithHandle(m_hWnd
, this);
178 // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows
180 m_nNoItems
= (unsigned int)nNum
;
181 SetMajorDim(nMajorDim
== 0 ? nNum
: nMajorDim
, lStyle
);
183 m_ahRadioButtons
= new WXHWND
[nNum
];
184 m_pnRadioWidth
= new int[nNum
];
185 m_pnRadioHeight
= new int[nNum
];
187 for (int i
= 0; i
< nNum
; i
++)
189 m_pnRadioWidth
[i
] = m_pnRadioHeight
[i
] = -1;
190 long lStyleBtn
= BS_AUTORADIOBUTTON
| WS_VISIBLE
;
191 int nNewId
= NewControlId();
194 lStyleBtn
|= WS_GROUP
| WS_TABSTOP
;
196 wxString sLabel
= ::wxPMTextToLabel(asChoices
[i
]);
198 HWND hWndBtn
= (WXHWND
)::WinCreateWindow ( hWndParent
,
213 lColor
= (LONG
)vColour
.GetPixel();
214 ::WinSetPresParam( hWndBtn
220 lColor
= (LONG
)m_backgroundColour
.GetPixel();
221 ::WinSetPresParam( hWndBtn
226 m_ahRadioButtons
[i
] = (WXHWND
)hWndBtn
;
227 SubclassRadioButton((WXHWND
)hWndBtn
);
228 wxAssociateWinWithHandle(hWndBtn
, this);
229 wxOS2SetFont( hWndBtn
232 ::WinSetWindowULong(hWndBtn
, QWL_USER
, (ULONG
)this);
233 m_aSubControls
.Add(nNewId
);
237 // Create a dummy control to end the group.
239 (void)::WinCreateWindow ( hWndParent
,
246 (HMENU
)NewControlId(),
250 fnWndProcRadioBox
= (WXFARPROC
)::WinSubclassWindow( GetHwnd()
251 ,(PFNWP
)wxRadioBoxWndProc
253 ::WinSetWindowULong(GetHwnd(), QWL_USER
, (ULONG
)this);
254 lColor
= (LONG
)vColour
.GetPixel();
255 ::WinSetPresParam( m_hWnd
261 lColor
= (LONG
)m_backgroundColour
.GetPixel();
262 ::WinSetPresParam( m_hWnd
276 } // end of wxRadioBox::Create
278 wxSize
wxRadioBox::DoGetBestSize() const
280 return (GetTotalButtonSize(GetMaxButtonSize()));
281 } // end of wxRadioBox::DoGetBestSize
283 void wxRadioBox::DoSetSize(
292 // Input parameters assume wxWidgets coordinate system
304 wxSize vMaxSize
= GetMaxButtonSize();
312 wxFont vFont
= GetFont();
314 m_nSizeFlags
= nSizeFlags
;
315 GetPosition( &nCurrentX
322 if (nX
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
324 if (nY
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
331 wxGetCharSize( m_hWnd
338 // Attempt to have a look coherent with other platforms: We compute the
339 // biggest toggle dim, then we align all items according this value.
341 vMaxSize
= GetMaxButtonSize();
342 nMaxWidth
= vMaxSize
.x
;
343 nMaxHeight
= vMaxSize
.y
;
345 vTotSize
= GetTotalButtonSize(vMaxSize
);
346 nTotWidth
= vTotSize
.x
;
347 nTotHeight
= vTotSize
.y
;
350 // Only change our width/height if asked for
354 if (nSizeFlags
& wxSIZE_AUTO_WIDTH
)
362 if (nSizeFlags
& wxSIZE_AUTO_HEIGHT
)
363 nHeight
= nTotHeight
;
365 nHeight
= nHeightOld
;
369 // Now convert to OS/2 coordinate system
371 wxWindowOS2
* pParent
= (wxWindowOS2
*)GetParent();
373 nYy
= GetOS2ParentHeight(pParent
) - nYy
- nHeight
;
377 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
378 nYy
= vRect
.yTop
- nYy
- nHeight
;
380 nYOffset
= nYy
+ nHeight
;
381 ::WinSetWindowPos( GetHwnd()
387 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
391 // Now position all the buttons: the current button will be put at
392 // wxPoint(x_offset, y_offset) and the new row/column will start at
393 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
394 // maxHeight) except for the buttons in the last column which should extend
395 // to the right border of radiobox and thus can be wider than this.
397 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
398 // left to right order and m_majorDim is the number of columns while
399 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
400 // m_majorDim is the number of rows.
403 nYOffset
-= (nMaxHeight
+ ((3*nCy1
)/2));
408 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
411 // The last button in the row may be wider than the other ones as the
412 // radiobox may be wider than the sum of the button widths (as it
413 // happens, for example, when the radiobox label is very long)
415 bool bIsLastInTheRow
;
417 if (m_windowStyle
& wxRA_SPECIFY_COLS
)
420 // Item is the last in its row if it is a multiple of the number of
421 // columns or if it is just the last item
425 bIsLastInTheRow
= ((n
% GetMajorDim()) == 0) || (n
== (int)m_nNoItems
);
427 else // winRA_SPECIFY_ROWS
430 // Item is the last in the row if it is in the last columns
432 bIsLastInTheRow
= i
>= (m_nNoItems
/GetMajorDim()) * GetMajorDim();
436 // Is this the start of new row/column?
438 if (i
&& (i
% GetMajorDim() == 0))
440 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
443 // Start of new column
446 nXOffset
+= nMaxWidth
+ nCx1
;
448 else // start of new row
451 nYOffset
-= nMaxHeight
;
452 if (m_pnRadioWidth
[0] > 0L)
462 // Make the button go to the end of radio box
464 nWidthBtn
= nStartX
+ nWidth
- nXOffset
- (2 * nCx1
);
465 if (nWidthBtn
< nMaxWidth
)
466 nWidthBtn
= nMaxWidth
;
471 // Normal button, always of the same size
473 nWidthBtn
= nMaxWidth
;
477 // Make all buttons of the same, maximal size - like this they
478 // cover the radiobox entirely and the radiobox tooltips are always
479 // shown (otherwise they are not when the mouse pointer is in the
480 // radiobox part not belonging to any radiobutton)
482 ::WinSetWindowPos( (HWND
)m_ahRadioButtons
[i
]
488 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
491 // Where do we put the next button?
493 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
498 nYOffset
-= nMaxHeight
;
499 if (m_pnRadioWidth
[0] > 0)
505 // To the right of this one
507 nXOffset
+= nWidthBtn
+ nCx1
;
510 } // end of wxRadioBox::DoSetSize
512 bool wxRadioBox::Enable(unsigned int nItem
, bool bEnable
)
514 wxCHECK_MSG( IsValid(nItem
), false,
515 wxT("invalid item in wxRadioBox::Enable()") );
517 ::WinEnableWindow((HWND
) m_ahRadioButtons
[nItem
], bEnable
);
519 } // end of wxRadioBox::Enable
521 bool wxRadioBox::Enable(bool bEnable
)
523 if ( !wxControl::Enable(bEnable
) )
525 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
526 ::WinEnableWindow((HWND
)m_ahRadioButtons
[i
], bEnable
);
528 } // end of wxRadioBox::Enable
530 unsigned int wxRadioBox::GetCount() const
533 } // end of wxRadioBox::GetCount
535 wxString
wxRadioBox::GetLabel(int nItem
) const
537 wxCHECK_MSG( IsValid(nItem
), wxEmptyString
, wxT("invalid radiobox index") );
539 return wxGetWindowText(m_ahRadioButtons
[nItem
]);
540 } // end of wxRadioBox::GetLabel
542 wxSize
wxRadioBox::GetMaxButtonSize() const
547 for (unsigned int i
= 0 ; i
< m_nNoItems
; i
++)
552 if (m_pnRadioWidth
[i
] < 0L)
554 GetTextExtent( wxGetWindowText(m_ahRadioButtons
[i
])
560 // Adjust the size to take into account the radio box itself
561 // FIXME this is totally bogus!
563 nWidth
+= RADIO_SIZE
;
569 nWidth
= m_pnRadioWidth
[i
];
570 nHeight
= m_pnRadioHeight
[i
];
572 if (nWidthMax
< nWidth
)
574 if (nHeightMax
< nHeight
)
575 nHeightMax
= nHeight
;
577 wxSize
maxsize( nWidthMax
, nHeightMax
);
579 } // end of wxRadioBox::GetMaxButtonSize
581 // Get single selection, for single choice list items
582 int wxRadioBox::GetSelection() const
584 return m_nSelectedButton
;
585 } // end of wxRadioBox::GetSelection
587 void wxRadioBox::GetSize( int* pnWidth
, int* pnHeight
) const
597 wxFindMaxSize( m_hWnd
, &vRect
);
599 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
600 wxFindMaxSize( m_ahRadioButtons
[i
], &vRect
);
603 *pnWidth
= vRect
.xRight
- vRect
.xLeft
;
605 *pnHeight
= vRect
.yTop
- vRect
.yBottom
;
606 } // end of wxRadioBox::GetSize
608 // Find string for position
609 wxString
wxRadioBox::GetString(unsigned int nNum
) const
611 wxCHECK_MSG( IsValid(nNum
), wxEmptyString
, wxT("invalid radiobox index") );
612 return wxGetWindowText(m_ahRadioButtons
[nNum
]);
613 } // end of wxRadioBox::GetString
615 // For single selection items only
616 wxString
wxRadioBox::GetStringSelection() const
619 int nSel
= GetSelection();
621 if (nSel
!= wxNOT_FOUND
)
622 sResult
= GetString(nSel
);
625 } // end of wxRadioBox::GetStringSelection
627 wxSize
wxRadioBox::GetTotalButtonSize( const wxSize
& rSizeBtn
) const
635 nCx1
= GetCharWidth();
636 nCy1
= GetCharHeight();
637 nHeight
= GetRowCount() * rSizeBtn
.y
+ (2 * nCy1
);
638 nWidth
= GetColumnCount() * (rSizeBtn
.x
+ nCx1
) + nCx1
;
641 // And also wide enough for its label
643 wxString sStr
= wxGetWindowText(GetHwnd());
650 nWidthLabel
+= 2*nCx1
;
652 if (nWidthLabel
> nWidth
)
653 nWidth
= nWidthLabel
;
655 wxSize
total( nWidth
, nHeight
);
657 } // end of wxRadioBox::GetTotalButtonSize
659 WXHBRUSH
wxRadioBox::OnCtlColor( WXHDC hwinDC
,
660 WXHWND
WXUNUSED(hWnd
),
661 WXUINT
WXUNUSED(uCtlColor
),
662 WXUINT
WXUNUSED(uMessage
),
663 WXWPARAM
WXUNUSED(wParam
),
664 WXLPARAM
WXUNUSED(lParam
) )
666 HPS hPS
= (HPS
)hwinDC
; // pass in a PS handle in OS/2
668 if (GetParent()->GetTransparentBackground())
669 ::GpiSetBackMix(hPS
, BM_LEAVEALONE
);
671 ::GpiSetBackMix(hPS
, BM_OVERPAINT
);
673 wxColour vColBack
= GetBackgroundColour();
675 ::GpiSetBackColor(hPS
, vColBack
.GetPixel());
676 ::GpiSetColor(hPS
, vColBack
.GetPixel());
678 wxBrush
* pBrush
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID
);
679 return ((WXHBRUSH
)pBrush
->GetResourceHandle());
680 } // end of wxRadioBox::OnCtlColor
682 bool wxRadioBox::OS2Command( WXUINT uCmd
,
685 int nSelectedButton
= -1;
687 if (uCmd
== BN_CLICKED
)
692 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
694 if (wId
== wxGetWindowId(m_ahRadioButtons
[i
]))
700 if (nSelectedButton
== -1)
707 if (nSelectedButton
!= m_nSelectedButton
)
709 m_nSelectedButton
= nSelectedButton
;
710 SendNotificationEvent();
716 } // end of wxRadioBox::OS2Command
718 void wxRadioBox::SendNotificationEvent()
720 wxCommandEvent
vEvent(
725 vEvent
.SetInt( m_nSelectedButton
);
726 vEvent
.SetString( GetString(m_nSelectedButton
) );
727 vEvent
.SetEventObject(this);
728 ProcessCommand(vEvent
);
729 } // end of wxRadioBox::SendNotificationEvent
731 void wxRadioBox::SetFocus()
735 if (m_nSelectedButton
== -1)
736 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[0]);
738 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[m_nSelectedButton
]);
740 } // end of wxRadioBox::SetFocus
742 bool wxRadioBox::SetFont(const wxFont
& rFont
)
744 if (!wxControl::SetFont(rFont
))
752 // Also set the font of our radio buttons
754 for (unsigned int n
= 0; n
< m_nNoItems
; n
++)
756 HWND hWndBtn
= (HWND
)m_ahRadioButtons
[n
];
758 wxOS2SetFont( hWndBtn
, rFont
);
759 ::WinInvalidateRect(hWndBtn
, NULL
, FALSE
);
762 } // end of wxRadioBox::SetFont
764 void wxRadioBox::SetSelection(
768 wxCHECK_RET( IsValid(nNum
), wxT("invalid radiobox index") );
770 if ( IsValid(m_nSelectedButton
) )
771 ::WinSendMsg((HWND
)m_ahRadioButtons
[m_nSelectedButton
], BM_SETCHECK
, (MPARAM
)0, (MPARAM
)0);
773 ::WinSendMsg((HWND
)m_ahRadioButtons
[nNum
], BM_SETCHECK
, (MPARAM
)1, (MPARAM
)0);
774 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[nNum
]);
775 m_nSelectedButton
= nNum
;
776 } // end of wxRadioBox::SetSelection
778 void wxRadioBox::SetString(unsigned int nItem
, const wxString
& rsLabel
)
780 wxCHECK_RET( IsValid(nItem
), wxT("invalid radiobox index") );
782 m_pnRadioWidth
[nItem
] = m_pnRadioHeight
[nItem
] = -1;
783 ::WinSetWindowText((HWND
)m_ahRadioButtons
[nItem
], rsLabel
.c_str());
784 } // end of wxRadioBox::SetString
786 bool wxRadioBox::SetStringSelection(const wxString
& rsStr
)
788 int nSel
= FindString(rsStr
);
797 } // end of wxRadioBox::SetStringSelection
799 bool wxRadioBox::Show(bool bShow
)
801 if (!wxControl::Show(bShow
))
804 for (unsigned int i
= 0; i
< m_nNoItems
; i
++)
806 ::WinShowWindow((HWND
)m_ahRadioButtons
[i
], (BOOL
)bShow
);
809 } // end of wxRadioBox::Show
811 // Show a specific button
812 bool wxRadioBox::Show(unsigned int nItem
, bool bShow
)
814 wxCHECK_MSG( IsValid(nItem
), false,
815 wxT("invalid item in wxRadioBox::Show()") );
817 ::WinShowWindow((HWND
)m_ahRadioButtons
[nItem
], bShow
);
820 } // end of wxRadioBox::Show
822 void wxRadioBox::SubclassRadioButton(
826 fnWndProcRadioBtn
= (WXFARPROC
)::WinSubclassWindow(hWndBtn
, (PFNWP
)wxRadioBtnWndProc
);
827 } // end of wxRadioBox::SubclassRadioButton
829 MRESULT
wxRadioBox::WindowProc(
835 return (wxControl::OS2WindowProc( uMsg
839 } // end of wxRadioBox::WindowProc
841 // ---------------------------------------------------------------------------
842 // window proc for radio buttons
843 // ---------------------------------------------------------------------------
845 MRESULT
wxRadioBtnWndProc(
856 USHORT uKeyFlags
= SHORT1FROMMP((MPARAM
)wParam
);
858 if (!(uKeyFlags
& KC_KEYUP
)) // Key Down event
860 if (uKeyFlags
& KC_VIRTUALKEY
)
862 wxRadioBox
* pRadiobox
= (wxRadioBox
*)::WinQueryWindowULong( hWnd
865 USHORT uVk
= SHORT2FROMMP((MPARAM
)lParam
);
866 bool bProcessed
= true;
891 // Just to suppress the compiler warning
898 int nSelOld
= pRadiobox
->GetSelection();
899 int nSelNew
= pRadiobox
->GetNextItem( nSelOld
901 ,pRadiobox
->GetWindowStyleFlag()
904 if (nSelNew
!= nSelOld
)
906 pRadiobox
->SetSelection(nSelNew
);
909 // Emulate the button click
911 pRadiobox
->SendNotificationEvent();
921 return fnWndProcRadioBtn( hWnd
926 } // end of wxRadioBtnWndProc
928 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
,
933 return (fnWndProcRadioBox( hWnd
,
938 } // end of wxRadioBoxWndProc
940 #endif // wxUSE_RADIOBOX