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"
19 #include "wx/wxchar.h"
20 #include "wx/string.h"
21 #include "wx/bitmap.h"
23 #include "wx/radiobox.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()
78 m_isBeingDeleted
= true;
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
)
149 HWND hWndParent
= GetHwndOf(pParent
);
151 vColour
.Set(wxString(wxT("BLACK")));
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
], (PSZ
)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