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/wxchar.h"
18 #include "wx/string.h"
19 #include "wx/bitmap.h"
21 #include "wx/radiobox.h"
24 #include "wx/os2/private.h"
26 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
28 // ---------------------------------------------------------------------------
30 // ---------------------------------------------------------------------------
32 // wnd proc for radio buttons
33 MRESULT EXPENTRY
wxRadioBtnWndProc( HWND hWnd
38 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
44 // ---------------------------------------------------------------------------
46 // ---------------------------------------------------------------------------
48 extern void wxAssociateWinWithHandle( HWND hWnd
51 extern void wxRemoveHandleAssociation( wxWindowOS2
*pWin
);
52 // the pointer to standard radio button & box wnd procs
53 static WXFARPROC fnWndProcRadioBtn
= NULL
;
54 static WXFARPROC fnWndProcRadioBox
= NULL
;
56 // ===========================================================================
58 // ===========================================================================
60 // ---------------------------------------------------------------------------
62 // ---------------------------------------------------------------------------
65 wxRadioBox::wxRadioBox()
67 m_nSelectedButton
= -1;
69 m_ahRadioButtons
= NULL
;
70 m_pnRadioWidth
= NULL
;
71 m_pnRadioHeight
= NULL
;
72 } // end of wxRadioBox::wxRadioBox
74 wxRadioBox::~wxRadioBox()
76 m_isBeingDeleted
= true;
79 wxRemoveHandleAssociation(this);
82 for (int i
= 0; i
< m_nNoItems
; i
++)
84 wxWindow
* pWin
= wxFindWinFromHandle((WXHWND
)m_ahRadioButtons
[i
]);
85 wxRemoveHandleAssociation(pWin
);
87 ::WinDestroyWindow((HWND
)m_ahRadioButtons
[i
]);
89 delete[] m_ahRadioButtons
;
92 delete[] m_pnRadioWidth
;
94 delete[] m_pnRadioHeight
;
95 } // end of wxRadioBox::~wxRadioBox
97 void wxRadioBox::Command (
98 wxCommandEvent
& rEvent
101 SetSelection (rEvent
.GetInt());
102 ProcessCommand(rEvent
);
103 } // end of wxRadioBox::Command
105 bool wxRadioBox::ContainsHWND(
109 size_t nCount
= GetCount();
112 for (i
= 0; i
< nCount
; i
++)
114 if (GetRadioButtons()[i
] == hWnd
)
118 } // end of wxRadioBox::ContainsHWND
120 bool wxRadioBox::Create(
123 , const wxString
& rsTitle
124 , const wxPoint
& rPos
125 , const wxSize
& rSize
126 , const wxArrayString
& asChoices
129 , const wxValidator
& rVal
130 , const wxString
& rsName
133 wxCArrayString
chs(asChoices
);
135 return Create(pParent
, vId
, rsTitle
, rPos
, rSize
, chs
.GetCount(),
136 chs
.GetStrings(), nMajorDim
, lStyle
, rVal
, rsName
);
139 bool wxRadioBox::Create(
142 , const wxString
& rsTitle
143 , const wxPoint
& rPos
144 , const wxSize
& rSize
146 , const wxString asChoices
[]
149 , const wxValidator
& rVal
150 , const wxString
& rsName
155 HWND hWndParent
= GetHwndOf(pParent
);
157 vColour
.Set(wxString(wxT("BLACK")));
158 m_backgroundColour
= pParent
->GetBackgroundColour();
159 m_nSelectedButton
= -1;
163 // Common initialization
165 if (!CreateControl( pParent
174 if (!OS2CreateControl( wxT("STATIC")
182 wxAssociateWinWithHandle(m_hWnd
, this);
185 // Now we can set m_nNoItems and let SetMajorDim set m_numCols/m_numRows
188 SetMajorDim(nMajorDim
== 0 ? nNum
: nMajorDim
, lStyle
);
190 m_ahRadioButtons
= new WXHWND
[nNum
];
191 m_pnRadioWidth
= new int[nNum
];
192 m_pnRadioHeight
= new int[nNum
];
194 for (int i
= 0; i
< nNum
; i
++)
196 m_pnRadioWidth
[i
] = m_pnRadioHeight
[i
] = -1;
197 long lStyleBtn
= BS_AUTORADIOBUTTON
| WS_VISIBLE
;
198 int nNewId
= NewControlId();
201 lStyleBtn
|= WS_GROUP
| WS_TABSTOP
;
203 wxString sLabel
= ::wxPMTextToLabel(asChoices
[i
]);
205 HWND hWndBtn
= (WXHWND
)::WinCreateWindow ( hWndParent
,
220 lColor
= (LONG
)vColour
.GetPixel();
221 ::WinSetPresParam( hWndBtn
227 lColor
= (LONG
)m_backgroundColour
.GetPixel();
228 ::WinSetPresParam( hWndBtn
233 m_ahRadioButtons
[i
] = (WXHWND
)hWndBtn
;
234 SubclassRadioButton((WXHWND
)hWndBtn
);
235 wxAssociateWinWithHandle(hWndBtn
, this);
236 wxOS2SetFont( hWndBtn
239 ::WinSetWindowULong(hWndBtn
, QWL_USER
, (ULONG
)this);
240 m_aSubControls
.Add(nNewId
);
244 // Create a dummy control to end the group.
246 (void)::WinCreateWindow ( hWndParent
,
253 (HMENU
)NewControlId(),
257 fnWndProcRadioBox
= (WXFARPROC
)::WinSubclassWindow( GetHwnd()
258 ,(PFNWP
)wxRadioBoxWndProc
260 ::WinSetWindowULong(GetHwnd(), QWL_USER
, (ULONG
)this);
261 lColor
= (LONG
)vColour
.GetPixel();
262 ::WinSetPresParam( m_hWnd
268 lColor
= (LONG
)m_backgroundColour
.GetPixel();
269 ::WinSetPresParam( m_hWnd
283 } // end of wxRadioBox::Create
285 wxSize
wxRadioBox::DoGetBestSize() const
287 return (GetTotalButtonSize(GetMaxButtonSize()));
288 } // end of wxRadioBox::DoGetBestSize
290 void wxRadioBox::DoSetSize(
299 // Input parameters assume wxWidgets coordinate system
311 wxSize vMaxSize
= GetMaxButtonSize();
319 wxFont vFont
= GetFont();
321 m_nSizeFlags
= nSizeFlags
;
322 GetPosition( &nCurrentX
329 if (nX
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
331 if (nY
== wxDefaultCoord
&& !(nSizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
338 wxGetCharSize( m_hWnd
345 // Attempt to have a look coherent with other platforms: We compute the
346 // biggest toggle dim, then we align all items according this value.
348 vMaxSize
= GetMaxButtonSize();
349 nMaxWidth
= vMaxSize
.x
;
350 nMaxHeight
= vMaxSize
.y
;
352 vTotSize
= GetTotalButtonSize(vMaxSize
);
353 nTotWidth
= vTotSize
.x
;
354 nTotHeight
= vTotSize
.y
;
357 // Only change our width/height if asked for
361 if (nSizeFlags
& wxSIZE_AUTO_WIDTH
)
369 if (nSizeFlags
& wxSIZE_AUTO_HEIGHT
)
370 nHeight
= nTotHeight
;
372 nHeight
= nHeightOld
;
376 // Now convert to OS/2 coordinate system
378 wxWindowOS2
* pParent
= (wxWindowOS2
*)GetParent();
380 nYy
= GetOS2ParentHeight(pParent
) - nYy
- nHeight
;
384 ::WinQueryWindowRect(HWND_DESKTOP
, &vRect
);
385 nYy
= vRect
.yTop
- nYy
- nHeight
;
387 nYOffset
= nYy
+ nHeight
;
388 ::WinSetWindowPos( GetHwnd()
394 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
398 // Now position all the buttons: the current button will be put at
399 // wxPoint(x_offset, y_offset) and the new row/column will start at
400 // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
401 // maxHeight) except for the buttons in the last column which should extend
402 // to the right border of radiobox and thus can be wider than this.
404 // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
405 // left to right order and m_majorDim is the number of columns while
406 // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
407 // m_majorDim is the number of rows.
410 nYOffset
-= (nMaxHeight
+ ((3*nCy1
)/2));
415 for (int i
= 0; i
< m_nNoItems
; i
++)
418 // The last button in the row may be wider than the other ones as the
419 // radiobox may be wider than the sum of the button widths (as it
420 // happens, for example, when the radiobox label is very long)
422 bool bIsLastInTheRow
;
424 if (m_windowStyle
& wxRA_SPECIFY_COLS
)
427 // Item is the last in its row if it is a multiple of the number of
428 // columns or if it is just the last item
432 bIsLastInTheRow
= ((n
% GetMajorDim()) == 0) || (n
== m_nNoItems
);
434 else // winRA_SPECIFY_ROWS
437 // Item is the last in the row if it is in the last columns
439 bIsLastInTheRow
= i
>= (m_nNoItems
/GetMajorDim()) * GetMajorDim();
443 // Is this the start of new row/column?
445 if (i
&& (i
% GetMajorDim() == 0))
447 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
450 // Start of new column
453 nXOffset
+= nMaxWidth
+ nCx1
;
455 else // start of new row
458 nYOffset
-= nMaxHeight
;
459 if (m_pnRadioWidth
[0] > 0L)
469 // Make the button go to the end of radio box
471 nWidthBtn
= nStartX
+ nWidth
- nXOffset
- (2 * nCx1
);
472 if (nWidthBtn
< nMaxWidth
)
473 nWidthBtn
= nMaxWidth
;
478 // Normal button, always of the same size
480 nWidthBtn
= nMaxWidth
;
484 // Make all buttons of the same, maximal size - like this they
485 // cover the radiobox entirely and the radiobox tooltips are always
486 // shown (otherwise they are not when the mouse pointer is in the
487 // radiobox part not belonging to any radiobutton)
489 ::WinSetWindowPos( (HWND
)m_ahRadioButtons
[i
]
495 ,SWP_ZORDER
| SWP_SIZE
| SWP_MOVE
| SWP_SHOW
498 // Where do we put the next button?
500 if (m_windowStyle
& wxRA_SPECIFY_ROWS
)
505 nYOffset
-= nMaxHeight
;
506 if (m_pnRadioWidth
[0] > 0)
512 // To the right of this one
514 nXOffset
+= nWidthBtn
+ nCx1
;
517 } // end of wxRadioBox::DoSetSize
519 bool wxRadioBox::Enable(int nItem
, bool bEnable
)
521 wxCHECK_MSG( IsValid(nItem
), false,
522 wxT("invalid item in wxRadioBox::Enable()") );
524 ::WinEnableWindow((HWND
) m_ahRadioButtons
[nItem
], bEnable
);
526 } // end of wxRadioBox::Enable
528 bool wxRadioBox::Enable(
532 if ( !wxControl::Enable(bEnable
) )
534 for (int i
= 0; i
< m_nNoItems
; i
++)
535 ::WinEnableWindow((HWND
)m_ahRadioButtons
[i
], bEnable
);
537 } // end of wxRadioBox::Enable
539 int wxRadioBox::GetCount() const
542 } // end of wxRadioBox::GetCount
544 wxString
wxRadioBox::GetLabel(int nItem
) const
546 wxCHECK_MSG( IsValid(nItem
), wxEmptyString
, wxT("invalid radiobox index") );
548 return wxGetWindowText(m_ahRadioButtons
[nItem
]);
549 } // end of wxRadioBox::GetLabel
551 wxSize
wxRadioBox::GetMaxButtonSize() const
556 for (int i
= 0 ; i
< m_nNoItems
; i
++)
561 if (m_pnRadioWidth
[i
] < 0L)
563 GetTextExtent( wxGetWindowText(m_ahRadioButtons
[i
])
569 // Adjust the size to take into account the radio box itself
570 // FIXME this is totally bogus!
572 nWidth
+= RADIO_SIZE
;
578 nWidth
= m_pnRadioWidth
[i
];
579 nHeight
= m_pnRadioHeight
[i
];
581 if (nWidthMax
< nWidth
)
583 if (nHeightMax
< nHeight
)
584 nHeightMax
= nHeight
;
586 wxSize
maxsize( nWidthMax
, nHeightMax
);
588 } // end of wxRadioBox::GetMaxButtonSize
590 // Get single selection, for single choice list items
591 int wxRadioBox::GetSelection() const
593 return m_nSelectedButton
;
594 } // end of wxRadioBox::GetSelection
596 void wxRadioBox::GetSize( int* pnWidth
, int* pnHeight
) const
606 wxFindMaxSize( m_hWnd
610 for (int i
= 0; i
< m_nNoItems
; i
++)
611 wxFindMaxSize( m_ahRadioButtons
[i
]
616 *pnWidth
= vRect
.xRight
- vRect
.xLeft
;
618 *pnHeight
= vRect
.yTop
- vRect
.yBottom
;
619 } // end of wxRadioBox::GetSize
621 // Find string for position
622 wxString
wxRadioBox::GetString( int nNum
) const
624 wxCHECK_MSG( IsValid(nNum
), wxEmptyString
, wxT("invalid radiobox index") );
625 return wxGetWindowText(m_ahRadioButtons
[nNum
]);
626 } // end of wxRadioBox::GetString
628 // For single selection items only
629 wxString
wxRadioBox::GetStringSelection() const
632 int nSel
= GetSelection();
635 sResult
= GetString(nSel
);
637 } // end of wxRadioBox::GetStringSelection
639 wxSize
wxRadioBox::GetTotalButtonSize( const wxSize
& rSizeBtn
) const
647 nCx1
= GetCharWidth();
648 nCy1
= GetCharHeight();
649 nHeight
= GetRowCount() * rSizeBtn
.y
+ (2 * nCy1
);
650 nWidth
= GetColumnCount() * (rSizeBtn
.x
+ nCx1
) + nCx1
;
653 // And also wide enough for its label
655 wxString sStr
= wxGetWindowText(GetHwnd());
662 nWidthLabel
+= 2*nCx1
;
664 if (nWidthLabel
> nWidth
)
665 nWidth
= nWidthLabel
;
667 wxSize
total( nWidth
, nHeight
);
669 } // end of wxRadioBox::GetTotalButtonSize
671 WXHBRUSH
wxRadioBox::OnCtlColor( WXHDC hwinDC
,
672 WXHWND
WXUNUSED(hWnd
),
673 WXUINT
WXUNUSED(uCtlColor
),
674 WXUINT
WXUNUSED(uMessage
),
675 WXWPARAM
WXUNUSED(wParam
),
676 WXLPARAM
WXUNUSED(lParam
) )
678 HPS hPS
= (HPS
)hwinDC
; // pass in a PS handle in OS/2
680 if (GetParent()->GetTransparentBackground())
681 ::GpiSetBackMix(hPS
, BM_LEAVEALONE
);
683 ::GpiSetBackMix(hPS
, BM_OVERPAINT
);
685 wxColour vColBack
= GetBackgroundColour();
687 ::GpiSetBackColor(hPS
, vColBack
.GetPixel());
688 ::GpiSetColor(hPS
, vColBack
.GetPixel());
690 wxBrush
* pBrush
= wxTheBrushList
->FindOrCreateBrush( vColBack
, wxSOLID
);
691 return ((WXHBRUSH
)pBrush
->GetResourceHandle());
692 } // end of wxRadioBox::OnCtlColor
694 bool wxRadioBox::OS2Command( WXUINT uCmd
,
697 int nSelectedButton
= -1;
699 if (uCmd
== BN_CLICKED
)
704 for (int i
= 0; i
< m_nNoItems
; i
++)
706 if (wId
== wxGetWindowId(m_ahRadioButtons
[i
]))
712 if (nSelectedButton
== -1)
719 if (nSelectedButton
!= m_nSelectedButton
)
721 m_nSelectedButton
= nSelectedButton
;
722 SendNotificationEvent();
728 } // end of wxRadioBox::OS2Command
730 void wxRadioBox::SendNotificationEvent()
732 wxCommandEvent
vEvent( wxEVT_COMMAND_RADIOBOX_SELECTED
736 vEvent
.SetInt( m_nSelectedButton
);
737 vEvent
.SetString( GetString(m_nSelectedButton
) );
738 vEvent
.SetEventObject(this);
739 ProcessCommand(vEvent
);
740 } // end of wxRadioBox::SendNotificationEvent
742 void wxRadioBox::SetFocus()
746 if (m_nSelectedButton
== -1)
747 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[0]);
749 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[m_nSelectedButton
]);
751 } // end of wxRadioBox::SetFocus
753 bool wxRadioBox::SetFont(
757 if (!wxControl::SetFont(rFont
))
765 // Also set the font of our radio buttons
767 for (int n
= 0; n
< (int)m_nNoItems
; n
++)
769 HWND hWndBtn
= (HWND
)m_ahRadioButtons
[n
];
771 wxOS2SetFont( hWndBtn
774 ::WinInvalidateRect(hWndBtn
, NULL
, FALSE
);
777 } // end of wxRadioBox::SetFont
779 void wxRadioBox::SetSelection(
783 wxCHECK_RET( IsValid(nNum
), wxT("invalid radiobox index") );
785 if ( IsValid(m_nSelectedButton
) )
786 ::WinSendMsg((HWND
)m_ahRadioButtons
[m_nSelectedButton
], BM_SETCHECK
, (MPARAM
)0, (MPARAM
)0);
788 ::WinSendMsg((HWND
)m_ahRadioButtons
[nNum
], BM_SETCHECK
, (MPARAM
)1, (MPARAM
)0);
789 ::WinSetFocus(HWND_DESKTOP
, (HWND
)m_ahRadioButtons
[nNum
]);
790 m_nSelectedButton
= nNum
;
791 } // end of wxRadioBox::SetSelection
793 void wxRadioBox::SetString(
795 , const wxString
& rsLabel
798 wxCHECK_RET( IsValid(nItem
), wxT("invalid radiobox index") );
800 m_pnRadioWidth
[nItem
] = m_pnRadioHeight
[nItem
] = -1;
801 ::WinSetWindowText((HWND
)m_ahRadioButtons
[nItem
], (PSZ
)rsLabel
.c_str());
802 } // end of wxRadioBox::SetString
804 bool wxRadioBox::SetStringSelection(const wxString
& rsStr
)
806 int nSel
= FindString(rsStr
);
815 } // end of wxRadioBox::SetStringSelection
817 bool wxRadioBox::Show(
821 if (!wxControl::Show(bShow
))
824 for (int i
= 0; i
< m_nNoItems
; i
++)
826 ::WinShowWindow((HWND
)m_ahRadioButtons
[i
], (BOOL
)bShow
);
829 } // end of wxRadioBox::Show
831 // Show a specific button
832 bool wxRadioBox::Show(
837 wxCHECK_MSG( IsValid(nItem
), false,
838 wxT("invalid item in wxRadioBox::Show()") );
840 ::WinShowWindow((HWND
)m_ahRadioButtons
[nItem
], bShow
);
843 } // end of wxRadioBox::Show
845 void wxRadioBox::SubclassRadioButton(
849 fnWndProcRadioBtn
= (WXFARPROC
)::WinSubclassWindow(hWndBtn
, (PFNWP
)wxRadioBtnWndProc
);
850 } // end of wxRadioBox::SubclassRadioButton
852 MRESULT
wxRadioBox::WindowProc(
858 return (wxControl::OS2WindowProc( uMsg
862 } // end of wxRadioBox::WindowProc
864 // ---------------------------------------------------------------------------
865 // window proc for radio buttons
866 // ---------------------------------------------------------------------------
868 MRESULT
wxRadioBtnWndProc(
879 USHORT uKeyFlags
= SHORT1FROMMP((MPARAM
)wParam
);
881 if (!(uKeyFlags
& KC_KEYUP
)) // Key Down event
883 if (uKeyFlags
& KC_VIRTUALKEY
)
885 wxRadioBox
* pRadiobox
= (wxRadioBox
*)::WinQueryWindowULong( hWnd
888 USHORT uVk
= SHORT2FROMMP((MPARAM
)lParam
);
889 bool bProcessed
= true;
914 // Just to suppress the compiler warning
921 int nSelOld
= pRadiobox
->GetSelection();
922 int nSelNew
= pRadiobox
->GetNextItem( nSelOld
924 ,pRadiobox
->GetWindowStyleFlag()
927 if (nSelNew
!= nSelOld
)
929 pRadiobox
->SetSelection(nSelNew
);
932 // Emulate the button click
934 pRadiobox
->SendNotificationEvent();
944 return fnWndProcRadioBtn( hWnd
949 } // end of wxRadioBtnWndProc
951 MRESULT EXPENTRY
wxRadioBoxWndProc( HWND hWnd
,
956 return (fnWndProcRadioBox( hWnd
,
961 } // end of wxRadioBoxWndProc