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"
18 #include "wx/wxchar.h"
19 #include "wx/string.h"
20 #include "wx/bitmap.h"
22 #include "wx/radiobox.h"
25 #include "wx/os2/private.h"
27 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
29 // ---------------------------------------------------------------------------
31 // ---------------------------------------------------------------------------
33 // wnd proc for radio buttons
34 MRESULT EXPENTRY
wxRadioBtnWndProc( HWND hWnd
39 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
45 // ---------------------------------------------------------------------------
47 // ---------------------------------------------------------------------------
49 extern void wxAssociateWinWithHandle( HWND hWnd
52 extern void wxRemoveHandleAssociation( wxWindowOS2
*pWin
);
53 // the pointer to standard radio button & box wnd procs
54 static WXFARPROC fnWndProcRadioBtn
= NULL
;
55 static WXFARPROC fnWndProcRadioBox
= NULL
;
57 // ===========================================================================
59 // ===========================================================================
61 // ---------------------------------------------------------------------------
63 // ---------------------------------------------------------------------------
66 wxRadioBox::wxRadioBox()
68 m_nSelectedButton
= -1;
70 m_ahRadioButtons
= NULL
;
71 m_pnRadioWidth
= NULL
;
72 m_pnRadioHeight
= NULL
;
73 } // end of wxRadioBox::wxRadioBox
75 wxRadioBox::~wxRadioBox()
77 m_isBeingDeleted
= true;
80 wxRemoveHandleAssociation(this);
83 for (int i
= 0; i
< m_nNoItems
; i
++)
85 wxWindow
* pWin
= wxFindWinFromHandle((WXHWND
)m_ahRadioButtons
[i
]);
86 wxRemoveHandleAssociation(pWin
);
88 ::WinDestroyWindow((HWND
)m_ahRadioButtons
[i
]);
90 delete[] m_ahRadioButtons
;
93 delete[] m_pnRadioWidth
;
95 delete[] m_pnRadioHeight
;
96 } // end of wxRadioBox::~wxRadioBox
98 void wxRadioBox::Command (
99 wxCommandEvent
& rEvent
102 SetSelection (rEvent
.GetInt());
103 ProcessCommand(rEvent
);
104 } // end of wxRadioBox::Command
106 bool wxRadioBox::ContainsHWND(
110 size_t nCount
= GetCount();
113 for (i
= 0; i
< nCount
; i
++)
115 if (GetRadioButtons()[i
] == hWnd
)
119 } // end of wxRadioBox::ContainsHWND
121 bool wxRadioBox::Create(
124 , const wxString
& rsTitle
125 , const wxPoint
& rPos
126 , const wxSize
& rSize
127 , const wxArrayString
& asChoices
130 , const wxValidator
& rVal
131 , const wxString
& rsName
134 wxCArrayString
chs(asChoices
);
136 return Create(pParent
, vId
, rsTitle
, rPos
, rSize
, chs
.GetCount(),
137 chs
.GetStrings(), nMajorDim
, lStyle
, rVal
, rsName
);
140 bool wxRadioBox::Create(
143 , const wxString
& rsTitle
144 , const wxPoint
& rPos
145 , const wxSize
& rSize
147 , const wxString asChoices
[]
150 , const wxValidator
& rVal
151 , const wxString
& rsName
156 HWND hWndParent
= GetHwndOf(pParent
);
158 vColour
.Set(wxString(wxT("BLACK")));
159 m_backgroundColour
= pParent
->GetBackgroundColour();
160 m_nSelectedButton
= -1;
164 // Common initialization
166 if (!CreateControl( pParent
175 if (!OS2CreateControl( wxT("STATIC")
183 wxAssociateWinWithHandle(m_hWnd
, this);
186 // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows
189 SetMajorDim(nMajorDim
== 0 ? nNum
: nMajorDim
, lStyle
);
191 m_ahRadioButtons
= new WXHWND
[nNum
];
192 m_pnRadioWidth
= new int[nNum
];
193 m_pnRadioHeight
= new int[nNum
];
195 for (int i
= 0; i
< nNum
; i
++)
197 m_pnRadioWidth
[i
] = m_pnRadioHeight
[i
] = -1;
198 long lStyleBtn
= BS_AUTORADIOBUTTON
| WS_VISIBLE
;
199 int nNewId
= NewControlId();
202 lStyleBtn
|= WS_GROUP
| WS_TABSTOP
;
204 wxString sLabel
= ::wxPMTextToLabel(asChoices
[i
]);
206 HWND hWndBtn
= (WXHWND
)::WinCreateWindow ( hWndParent
,
221 lColor
= (LONG
)vColour
.GetPixel();
222 ::WinSetPresParam( hWndBtn
228 lColor
= (LONG
)m_backgroundColour
.GetPixel();
229 ::WinSetPresParam( hWndBtn
234 m_ahRadioButtons
[i
] = (WXHWND
)hWndBtn
;
235 SubclassRadioButton((WXHWND
)hWndBtn
);
236 wxAssociateWinWithHandle(hWndBtn
, this);
237 wxOS2SetFont( hWndBtn
240 ::WinSetWindowULong(hWndBtn
, QWL_USER
, (ULONG
)this);
241 m_aSubControls
.Add(nNewId
);
245 // Create a dummy control to end the group.
247 (void)::WinCreateWindow ( hWndParent
,
254 (HMENU
)NewControlId(),
258 fnWndProcRadioBox
= (WXFARPROC
)::WinSubclassWindow( GetHwnd()
259 ,(PFNWP
)wxRadioBoxWndProc
261 ::WinSetWindowULong(GetHwnd(), QWL_USER
, (ULONG
)this);
262 lColor
= (LONG
)vColour
.GetPixel();
263 ::WinSetPresParam( m_hWnd
269 lColor
= (LONG
)m_backgroundColour
.GetPixel();
270 ::WinSetPresParam( m_hWnd
284 } // end of wxRadioBox::Create
286 wxSize
wxRadioBox::DoGetBestSize() const
288 return (GetTotalButtonSize(GetMaxButtonSize()));
289 } // end of wxRadioBox::DoGetBestSize
291 void wxRadioBox::DoSetSize(
300 // Input parameters assume wxWidgets coordinate system
312 wxSize vMaxSize
= GetMaxButtonSize();
320 wxFont vFont
= GetFont();
322 m_nSizeFlags
= nSizeFlags
;
323 GetPosition( &nCurrentX
330 if (nX
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
332 if (nY
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
339 wxGetCharSize( m_hWnd
346 // Attempt to have a look coherent with other platforms: We compute the
347 // biggest toggle dim, then we align all items according this value.
349 vMaxSize
= GetMaxButtonSize();
350 nMaxWidth
= vMaxSize
.x
;
351 nMaxHeight
= vMaxSize
.y
;
353 vTotSize
= GetTotalButtonSize(vMaxSize
);
354 nTotWidth
= vTotSize
.x
;
355 nTotHeight
= vTotSize
.y
;
358 // Only change our width/height if asked for
362 if (nSizeFlags
& wxSIZE_AUTO_WIDTH
)
370 if (nSizeFlags
& wxSIZE_AUTO_HEIGHT
)
371 nHeight
= nTotHeight
;
373 nHeight
= nHeightOld
;
377 // Now convert to OS/2 coordinate system
379 wxWindowOS2
* pParent
= (wxWindowOS2
*)GetParent();
381 nYy
= GetOS2ParentHeight(pParent
) - nYy
- nHeight
;
385 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
386 nYy
= vRect
.yTop
- nYy
- nHeight
;
388 nYOffset
= nYy
+ nHeight
;
389 ::WinSetWindowPos( GetHwnd()
395 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
399 // Now position all the buttons: the current button will be put at
400 // wxPoint(x_offset, y_offset) and the new row/column will start at
401 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
402 // maxHeight) except for the buttons in the last column which should extend
403 // to the right border of radiobox and thus can be wider than this.
405 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
406 // left to right order and m_majorDim is the number of columns while
407 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
408 // m_majorDim is the number of rows.
411 nYOffset
-= (nMaxHeight
+ ((3*nCy1
)/2));
416 for (int i
= 0; i
< m_nNoItems
; i
++)
419 // The last button in the row may be wider than the other ones as the
420 // radiobox may be wider than the sum of the button widths (as it
421 // happens, for example, when the radiobox label is very long)
423 bool bIsLastInTheRow
;
425 if (m_windowStyle
& wxRA_SPECIFY_COLS
)
428 // Item is the last in its row if it is a multiple of the number of
429 // columns or if it is just the last item
433 bIsLastInTheRow
= ((n
% GetMajorDim()) == 0) || (n
== m_nNoItems
);
435 else // winRA_SPECIFY_ROWS
438 // Item is the last in the row if it is in the last columns
440 bIsLastInTheRow
= i
>= (m_nNoItems
/GetMajorDim()) * GetMajorDim();
444 // Is this the start of new row/column?
446 if (i
&& (i
% GetMajorDim() == 0))
448 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
451 // Start of new column
454 nXOffset
+= nMaxWidth
+ nCx1
;
456 else // start of new row
459 nYOffset
-= nMaxHeight
;
460 if (m_pnRadioWidth
[0] > 0L)
470 // Make the button go to the end of radio box
472 nWidthBtn
= nStartX
+ nWidth
- nXOffset
- (2 * nCx1
);
473 if (nWidthBtn
< nMaxWidth
)
474 nWidthBtn
= nMaxWidth
;
479 // Normal button, always of the same size
481 nWidthBtn
= nMaxWidth
;
485 // Make all buttons of the same, maximal size - like this they
486 // cover the radiobox entirely and the radiobox tooltips are always
487 // shown (otherwise they are not when the mouse pointer is in the
488 // radiobox part not belonging to any radiobutton)
490 ::WinSetWindowPos( (HWND
)m_ahRadioButtons
[i
]
496 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
499 // Where do we put the next button?
501 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
506 nYOffset
-= nMaxHeight
;
507 if (m_pnRadioWidth
[0] > 0)
513 // To the right of this one
515 nXOffset
+= nWidthBtn
+ nCx1
;
518 } // end of wxRadioBox::DoSetSize
520 bool wxRadioBox::Enable(int nItem
, bool bEnable
)
522 wxCHECK_MSG( IsValid(nItem
), false,
523 wxT("invalid item in wxRadioBox::Enable()") );
525 ::WinEnableWindow((HWND
) m_ahRadioButtons
[nItem
], bEnable
);
527 } // end of wxRadioBox::Enable
529 bool wxRadioBox::Enable(
533 if ( !wxControl::Enable(bEnable
) )
535 for (int i
= 0; i
< m_nNoItems
; i
++)
536 ::WinEnableWindow((HWND
)m_ahRadioButtons
[i
], bEnable
);
538 } // end of wxRadioBox::Enable
540 int wxRadioBox::GetCount() const
543 } // end of wxRadioBox::GetCount
545 wxString
wxRadioBox::GetLabel(int nItem
) const
547 wxCHECK_MSG( IsValid(nItem
), wxEmptyString
, wxT("invalid radiobox index") );
549 return wxGetWindowText(m_ahRadioButtons
[nItem
]);
550 } // end of wxRadioBox::GetLabel
552 wxSize
wxRadioBox::GetMaxButtonSize() const
557 for (int i
= 0 ; i
< m_nNoItems
; i
++)
562 if (m_pnRadioWidth
[i
] < 0L)
564 GetTextExtent( wxGetWindowText(m_ahRadioButtons
[i
])
570 // Adjust the size to take into account the radio box itself
571 // FIXME this is totally bogus!
573 nWidth
+= RADIO_SIZE
;
579 nWidth
= m_pnRadioWidth
[i
];
580 nHeight
= m_pnRadioHeight
[i
];
582 if (nWidthMax
< nWidth
)
584 if (nHeightMax
< nHeight
)
585 nHeightMax
= nHeight
;
587 wxSize
maxsize( nWidthMax
, nHeightMax
);
589 } // end of wxRadioBox::GetMaxButtonSize
591 // Get single selection, for single choice list items
592 int wxRadioBox::GetSelection() const
594 return m_nSelectedButton
;
595 } // end of wxRadioBox::GetSelection
597 void wxRadioBox::GetSize( int* pnWidth
, int* pnHeight
) const
607 wxFindMaxSize( m_hWnd
611 for (int i
= 0; i
< m_nNoItems
; i
++)
612 wxFindMaxSize( m_ahRadioButtons
[i
]
617 *pnWidth
= vRect
.xRight
- vRect
.xLeft
;
619 *pnHeight
= vRect
.yTop
- vRect
.yBottom
;
620 } // end of wxRadioBox::GetSize
622 // Find string for position
623 wxString
wxRadioBox::GetString(
627 wxCHECK_MSG( IsValid(nNum
), wxString(""), wxT("invalid radiobox index") );
628 return wxGetWindowText(m_ahRadioButtons
[nNum
]);
629 } // end of wxRadioBox::GetString
631 // For single selection items only
632 wxString
wxRadioBox::GetStringSelection() const
635 int nSel
= GetSelection();
638 sResult
= GetString(nSel
);
640 } // end of wxRadioBox::GetStringSelection
642 wxSize
wxRadioBox::GetTotalButtonSize( const wxSize
& rSizeBtn
) const
650 nCx1
= GetCharWidth();
651 nCy1
= GetCharHeight();
652 nHeight
= GetRowCount() * rSizeBtn
.y
+ (2 * nCy1
);
653 nWidth
= GetColumnCount() * (rSizeBtn
.x
+ nCx1
) + nCx1
;
656 // And also wide enough for its label
658 wxString sStr
= wxGetWindowText(GetHwnd());
665 nWidthLabel
+= 2*nCx1
;
667 if (nWidthLabel
> nWidth
)
668 nWidth
= nWidthLabel
;
670 wxSize
total( nWidth
, nHeight
);
672 } // end of wxRadioBox::GetTotalButtonSize
674 WXHBRUSH
wxRadioBox::OnCtlColor( WXHDC hwinDC
,
675 WXHWND
WXUNUSED(hWnd
),
676 WXUINT
WXUNUSED(uCtlColor
),
677 WXUINT
WXUNUSED(uMessage
),
678 WXWPARAM
WXUNUSED(wParam
),
679 WXLPARAM
WXUNUSED(lParam
) )
681 HPS hPS
= (HPS
)hwinDC
; // pass in a PS handle in OS/2
683 if (GetParent()->GetTransparentBackground())
684 ::GpiSetBackMix(hPS
, BM_LEAVEALONE
);
686 ::GpiSetBackMix(hPS
, BM_OVERPAINT
);
688 wxColour vColBack
= GetBackgroundColour();
690 ::GpiSetBackColor(hPS
, vColBack
.GetPixel());
691 ::GpiSetColor(hPS
, vColBack
.GetPixel());
693 wxBrush
* pBrush
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID
);
694 return ((WXHBRUSH
)pBrush
->GetResourceHandle());
695 } // end of wxRadioBox::OnCtlColor
697 bool wxRadioBox::OS2Command( WXUINT uCmd
,
700 int nSelectedButton
= -1;
702 if (uCmd
== BN_CLICKED
)
707 for (int i
= 0; i
< m_nNoItems
; i
++)
709 if (wId
== wxGetWindowId(m_ahRadioButtons
[i
]))
715 if (nSelectedButton
== -1)
722 if (nSelectedButton
!= m_nSelectedButton
)
724 m_nSelectedButton
= nSelectedButton
;
725 SendNotificationEvent();
731 } // end of wxRadioBox::OS2Command
733 void wxRadioBox::SendNotificationEvent()
735 wxCommandEvent
vEvent( wxEVT_COMMAND_RADIOBOX_SELECTED
739 vEvent
.SetInt( m_nSelectedButton
);
740 vEvent
.SetString( GetString(m_nSelectedButton
) );
741 vEvent
.SetEventObject(this);
742 ProcessCommand(vEvent
);
743 } // end of wxRadioBox::SendNotificationEvent
745 void wxRadioBox::SetFocus()
749 if (m_nSelectedButton
== -1)
750 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[0]);
752 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[m_nSelectedButton
]);
754 } // end of wxRadioBox::SetFocus
756 bool wxRadioBox::SetFont(
760 if (!wxControl::SetFont(rFont
))
768 // Also set the font of our radio buttons
770 for (int n
= 0; n
< (int)m_nNoItems
; n
++)
772 HWND hWndBtn
= (HWND
)m_ahRadioButtons
[n
];
774 wxOS2SetFont( hWndBtn
777 ::WinInvalidateRect(hWndBtn
, NULL
, FALSE
);
780 } // end of wxRadioBox::SetFont
782 void wxRadioBox::SetSelection(
786 wxCHECK_RET( IsValid(nNum
), wxT("invalid radiobox index") );
788 if ( IsValid(m_nSelectedButton
) )
789 ::WinSendMsg((HWND
)m_ahRadioButtons
[m_nSelectedButton
], BM_SETCHECK
, (MPARAM
)0, (MPARAM
)0);
791 ::WinSendMsg((HWND
)m_ahRadioButtons
[nNum
], BM_SETCHECK
, (MPARAM
)1, (MPARAM
)0);
792 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[nNum
]);
793 m_nSelectedButton
= nNum
;
794 } // end of wxRadioBox::SetSelection
796 void wxRadioBox::SetString(
798 , const wxString
& rsLabel
801 wxCHECK_RET( IsValid(nItem
), wxT("invalid radiobox index") );
803 m_pnRadioWidth
[nItem
] = m_pnRadioHeight
[nItem
] = -1;
804 ::WinSetWindowText((HWND
)m_ahRadioButtons
[nItem
], (PSZ
)rsLabel
.c_str());
805 } // end of wxRadioBox::SetString
807 bool wxRadioBox::SetStringSelection(const wxString
& rsStr
)
809 int nSel
= FindString(rsStr
);
818 } // end of wxRadioBox::SetStringSelection
820 bool wxRadioBox::Show(
824 if (!wxControl::Show(bShow
))
827 for (int i
= 0; i
< m_nNoItems
; i
++)
829 ::WinShowWindow((HWND
)m_ahRadioButtons
[i
], (BOOL
)bShow
);
832 } // end of wxRadioBox::Show
834 // Show a specific button
835 bool wxRadioBox::Show(
840 wxCHECK_MSG( IsValid(nItem
), false,
841 wxT("invalid item in wxRadioBox::Show()") );
843 ::WinShowWindow((HWND
)m_ahRadioButtons
[nItem
], bShow
);
846 } // end of wxRadioBox::Show
848 void wxRadioBox::SubclassRadioButton(
852 fnWndProcRadioBtn
= (WXFARPROC
)::WinSubclassWindow(hWndBtn
, (PFNWP
)wxRadioBtnWndProc
);
853 } // end of wxRadioBox::SubclassRadioButton
855 MRESULT
wxRadioBox::WindowProc(
861 return (wxControl::OS2WindowProc( uMsg
865 } // end of wxRadioBox::WindowProc
867 // ---------------------------------------------------------------------------
868 // window proc for radio buttons
869 // ---------------------------------------------------------------------------
871 MRESULT
wxRadioBtnWndProc(
882 USHORT uKeyFlags
= SHORT1FROMMP((MPARAM
)wParam
);
884 if (!(uKeyFlags
& KC_KEYUP
)) // Key Down event
886 if (uKeyFlags
& KC_VIRTUALKEY
)
888 wxRadioBox
* pRadiobox
= (wxRadioBox
*)::WinQueryWindowULong( hWnd
891 USHORT uVk
= SHORT2FROMMP((MPARAM
)lParam
);
892 bool bProcessed
= true;
917 // Just to suppress the compiler warning
924 int nSelOld
= pRadiobox
->GetSelection();
925 int nSelNew
= pRadiobox
->GetNextItem( nSelOld
927 ,pRadiobox
->GetWindowStyleFlag()
930 if (nSelNew
!= nSelOld
)
932 pRadiobox
->SetSelection(nSelNew
);
935 // Emulate the button click
937 pRadiobox
->SendNotificationEvent();
947 return fnWndProcRadioBtn( hWnd
952 } // end of wxRadioBtnWndProc
954 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
,
959 return (fnWndProcRadioBox( hWnd
,
964 } // end of wxRadioBoxWndProc