1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "radiobox.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
26 #include "wx/radiobox.h"
29 #include "wx/msw/private.h"
31 #if !USE_SHARED_LIBRARY
32 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox
, wxControl
)
35 bool wxRadioBox::MSWCommand(WXUINT param
, WXWORD id
)
37 if (param
== BN_CLICKED
)
41 for (i
= 0; i
< m_noItems
; i
++)
42 if (id
== GetWindowLong((HWND
) m_radioButtons
[i
], GWL_ID
))
46 for (i
= 0; i
< m_noItems
; i
++)
47 if (id
== GetWindowWord((HWND
) m_radioButtons
[i
], GWW_ID
))
51 wxCommandEvent
event(wxEVT_COMMAND_RADIOBOX_SELECTED
, m_windowId
);
52 event
.SetInt( m_selectedButton
);
53 event
.SetEventObject( this );
54 ProcessCommand(event
);
60 #if WXWIN_COMPATIBILITY
61 wxRadioBox::wxRadioBox(wxWindow
*parent
, wxFunction func
, const char *title
,
62 int x
, int y
, int width
, int height
,
63 int n
, char **choices
,
64 int majorDim
, long style
, const char *name
)
66 wxString
*choices2
= new wxString
[n
];
67 for ( int i
= 0; i
< n
; i
++) choices2
[i
] = choices
[i
];
68 Create(parent
, -1, title
, wxPoint(x
, y
), wxSize(width
, height
), n
, choices2
, majorDim
, style
,
69 wxDefaultValidator
, name
);
77 wxRadioBox::wxRadioBox(void)
79 m_selectedButton
= -1;
82 m_radioButtons
= NULL
;
85 m_radioHeight
= NULL
;
88 bool wxRadioBox::Create(wxWindow
*parent
, wxWindowID id
, const wxString
& title
,
89 const wxPoint
& pos
, const wxSize
& size
,
90 int n
, const wxString choices
[],
91 int majorDim
, long style
,
92 const wxValidator
& val
, const wxString
& name
)
94 m_selectedButton
= -1;
100 parent
->AddChild(this);
101 m_backgroundColour
= parent
->GetDefaultBackgroundColour() ;
102 m_foregroundColour
= parent
->GetDefaultForegroundColour() ;
104 m_windowStyle
= (long&)style
;
112 m_windowId
= NewControlId();
116 m_noRowsOrCols
= majorDim
;
119 else // Seemed to make sense to put this 'else' here... (RD)
120 m_majorDim
= majorDim
;
122 long msStyle
= GROUP_FLAGS
;
125 WXDWORD exStyle
= Determine3DEffects(0, &want3D
) ;
126 // Even with extended styles, need to combine with WS_BORDER
127 // for them to look right.
128 if (want3D
&& ((m_windowStyle
& wxSIMPLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
129 (m_windowStyle
& wxSUNKEN_BORDER
) || (m_windowStyle
& wxDOUBLE_BORDER
)))
130 msStyle
|= WS_BORDER
;
133 m_hWnd
= (WXHWND
) CreateWindowEx((DWORD
) exStyle
, GROUP_CLASS
, (title
== "" ? NULL
: (const char *)title
),
136 (HWND
) parent
->GetHWND(), (HMENU
) m_windowId
, wxGetInstance(), NULL
) ;
138 HWND the_handle
= (HWND
) parent
->GetHWND() ;
143 Ctl3dSubclassCtl((HWND
) m_hWnd
);
148 SetFont(* parent
->GetFont());
150 // Subclass again for purposes of dialog editing mode
151 SubclassWin((WXHWND
)m_hWnd
);
153 /* Label will be the same as button font now.
156 labelFont->RealizeResource();
157 if (labelFont->GetResourceHandle())
158 SendMessage(ms_handle,WM_SETFONT,
159 (WPARAM)labelFont->GetResourceHandle(),0L);
163 // Some radio boxes test consecutive id.
164 (void)NewControlId() ;
165 m_radioButtons
= new WXHWND
[n
];
166 m_radioWidth
= new int[n
] ;
167 m_radioHeight
= new int[n
] ;
169 for (i
= 0; i
< n
; i
++)
171 m_radioWidth
[i
] = m_radioHeight
[i
] = -1 ;
173 if (i
== 0 && style
==0)
174 groupStyle
= WS_GROUP
;
175 long newId
= NewControlId();
176 long msStyle
= groupStyle
| RADIO_FLAGS
;
178 m_radioButtons
[i
] = (WXHWND
) CreateWindowEx(exStyle
, RADIO_CLASS
, choices
[i
],
180 the_handle
, (HMENU
)newId
, wxGetInstance(), NULL
);
184 Ctl3dSubclassCtl((HWND
) m_hWnd
);
190 SendMessage((HWND
)m_radioButtons
[i
],WM_SETFONT
,
191 (WPARAM
)GetFont()->GetResourceHandle(),0L);
193 m_subControls
.Append((wxObject
*)newId
);
196 // Create a dummy radio control to end the group.
197 (void)CreateWindowEx(0, RADIO_CLASS
, "", WS_GROUP
|RADIO_FLAGS
, 0,0,0,0, the_handle
, (HMENU
)NewControlId(), wxGetInstance(), NULL
);
201 SetSize(x
, y
, width
, height
);
207 bool wxRadioBox::Create(wxWindow
*parent
, wxWindowID id
, const wxString
& title
,
208 const wxPoint
& pos
, const wxSize
& size
,
209 int n
, const wxBitmap
*choices
[],
210 int majorDim
, long style
,
211 const wxValidator
& val
, const wxString
& name
)
213 m_selectedButton
= -1;
220 parent
->AddChild(this);
221 m_backgroundColour
= parent
->GetDefaultBackgroundColour() ;
222 m_foregroundColour
= parent
->GetDefaultForegroundColour() ;
224 m_windowStyle
= (long&)style
;
232 m_windowId
= NewControlId();
237 m_noRowsOrCols
= majorDim
;
240 m_majorDim
= majorDim
;
243 long msStyle
= GROUP_FLAGS
;
246 WXDWORD exStyle
= Determine3DEffects(0, &want3D
) ;
247 // Even with extended styles, need to combine with WS_BORDER
248 // for them to look right.
249 if (want3D
&& ((m_windowStyle
& wxSIMPLE_BORDER
) || (m_windowStyle
& wxRAISED_BORDER
) ||
250 (m_windowStyle
& wxSUNKEN_BORDER
) || (m_windowStyle
& wxDOUBLE_BORDER
)))
251 msStyle
|= WS_BORDER
;
253 m_hWnd
= (WXHWND
) CreateWindowEx((DWORD
) exStyle
, GROUP_CLASS
, (title
== "" ? NULL
: (const char *)title
),
256 (HWND
) parent
->GetHWND(), (HMENU
) m_windowId
, wxGetInstance(), NULL
) ;
261 labelFont->RealizeResource();
262 if (labelFont->GetResourceHandle())
263 SendMessage(ms_handle,WM_SETFONT,
264 (WPARAM)labelFont->GetResourceHandle(),0L);
267 the_handle
= (HWND
) parent
->GetHWND();
272 Ctl3dSubclassCtl((HWND
) m_hWnd
);
277 SetFont(* parent
->GetFont());
279 // Subclass again for purposes of dialog editing mode
280 SubclassWin((WXHWND
)m_hWnd
);
282 (void)NewControlId() ;
283 m_radioButtons
= new WXHWND
[n
];
284 m_radioWidth
= new int[n
] ;
285 m_radioHeight
= new int[n
] ;
288 for (i
= 0; i
< n
; i
++)
291 if (i
== 0 && style
==0)
292 groupStyle
= WS_GROUP
;
293 long newId
= NewControlId();
294 m_radioWidth
[i
] = ((wxBitmap
*)choices
[i
])->GetWidth();
295 m_radioHeight
[i
] = ((wxBitmap
*)choices
[i
])->GetHeight();
297 sprintf(tmp
,"Toggle%d",i
) ;
298 long msStyle
= groupStyle
| RADIO_FLAGS
;
299 m_radioButtons
[i
] = (WXHWND
) CreateWindowEx(exStyle
, RADIO_CLASS
, tmp
,
301 the_handle
, (HMENU
)newId
, wxhInstance
, NULL
);
305 Ctl3dSubclassCtl((HWND
) m_hWnd
);
309 m_subControls
.Append((wxObject
*)newId
);
311 // Create a dummy radio control to end the group.
312 (void)CreateWindowEx(0, RADIO_CLASS
, "", WS_GROUP
|RADIO_FLAGS
, 0,0,0,0, the_handle
, (HMENU
)NewControlId(), wxGetInstance(), NULL
);
316 SetSize(x
, y
, width
, height
);
322 wxRadioBox::~wxRadioBox(void)
324 m_isBeingDeleted
= TRUE
;
329 for (i
= 0; i
< m_noItems
; i
++)
330 DestroyWindow((HWND
) m_radioButtons
[i
]);
331 delete[] m_radioButtons
;
334 delete[] m_radioWidth
;
336 delete[] m_radioHeight
;
338 ::DestroyWindow((HWND
) m_hWnd
) ;
343 wxString
wxRadioBox::GetLabel(int item
) const
345 GetWindowText((HWND
)m_radioButtons
[item
], wxBuffer
, 300);
346 return wxString(wxBuffer
);
349 void wxRadioBox::SetLabel(int item
, const wxString
& label
)
351 m_radioWidth
[item
] = m_radioHeight
[item
] = -1 ;
352 SetWindowText((HWND
)m_radioButtons
[item
], (const char *)label
);
355 void wxRadioBox::SetLabel(int item
, wxBitmap
*bitmap
)
358 m_radioWidth[item] = bitmap->GetWidth() + FB_MARGIN ;
359 m_radioHeight[item] = bitmap->GetHeight() + FB_MARGIN ;
363 int wxRadioBox::FindString(const wxString
& s
) const
366 for (i
= 0; i
< m_noItems
; i
++)
368 GetWindowText((HWND
) m_radioButtons
[i
], wxBuffer
, 1000);
375 void wxRadioBox::SetSelection(int N
)
377 if ((N
< 0) || (N
>= m_noItems
))
380 // Following necessary for Win32s, because Win32s translate BM_SETCHECK
381 if (m_selectedButton
>= 0 && m_selectedButton
< m_noItems
)
382 SendMessage((HWND
) m_radioButtons
[m_selectedButton
], BM_SETCHECK
, 0, 0L);
384 SendMessage((HWND
) m_radioButtons
[N
], BM_SETCHECK
, 1, 0L);
385 m_selectedButton
= N
;
388 // Get single selection, for single choice list items
389 int wxRadioBox::GetSelection(void) const
391 return m_selectedButton
;
394 // Find string for position
395 wxString
wxRadioBox::GetString(int N
) const
397 GetWindowText((HWND
) m_radioButtons
[N
], wxBuffer
, 1000);
398 return wxString(wxBuffer
);
401 void wxRadioBox::SetSize(int x
, int y
, int width
, int height
, int sizeFlags
)
403 int currentX
, currentY
;
404 GetPosition(¤tX
, ¤tY
);
408 if (x
== -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
410 if (y
== -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
413 AdjustForParentClientOrigin(xx
, yy
, sizeFlags
);
419 int current_width
, cyf
;
422 wxGetCharSize(m_hWnd
, &cx1
, &cy1
, GetFont());
423 // Attempt to have a look coherent with other platforms:
424 // We compute the biggest toggle dim, then we align all
425 // items according this value.
430 for (i
= 0 ; i
< m_noItems
; i
++)
434 if (m_radioWidth
[i
]<0)
436 // It's a labelled toggle
437 GetWindowText((HWND
) m_radioButtons
[i
], buf
, 300);
438 GetTextExtent(buf
, ¤t_width
, &cyf
,NULL
,NULL
, GetFont());
439 eachWidth
= (int)(current_width
+ RADIO_SIZE
);
440 eachHeight
= (int)((3*cyf
)/2);
444 eachWidth
= m_radioWidth
[i
] ;
445 eachHeight
= m_radioHeight
[i
] ;
447 if (maxWidth
<eachWidth
) maxWidth
= eachWidth
;
448 if (maxHeight
<eachHeight
) maxHeight
= eachHeight
;
458 if (m_windowStyle
& wxRA_VERTICAL
)
461 nbHor
= (m_noItems
+m_majorDim
-1)/m_majorDim
;
466 nbVer
= (m_noItems
+m_majorDim
-1)/m_majorDim
;
469 // this formula works, but I don't know why.
470 // Please, be sure what you do if you modify it!!
471 if (m_radioWidth
[0]<0)
472 totHeight
= (nbVer
* maxHeight
) + cy1
/2 ;
474 totHeight
= nbVer
* (maxHeight
+cy1
/2) ;
475 totWidth
= nbHor
* (maxWidth
+cx1
) ;
478 // Requires a bigger group box in plain Windows
479 MoveWindow((HWND
) m_hWnd
,x_offset
,y_offset
,totWidth
+cx1
,totHeight
+(3*cy1
)/2,TRUE
) ;
481 MoveWindow((HWND
) m_hWnd
,x_offset
,y_offset
,totWidth
+cx1
,totHeight
+cy1
,TRUE
) ;
488 y_offset
+= (int)(cy1
/2); // Fudge factor since buttons overlapped label
489 // JACS 2/12/93. CTL3D draws group label quite high.
491 int startX
= x_offset
;
492 int startY
= y_offset
;
494 for ( i
= 0 ; i
< m_noItems
; i
++)
496 // Bidimensional radio adjustment
497 if (i
&&((i%m_majorDim
)==0)) // Why is this omitted for i = 0?
499 if (m_windowStyle
& wxRA_VERTICAL
)
502 x_offset
+= maxWidth
+ cx1
;
507 y_offset
+= maxHeight
;
508 if (m_radioWidth
[0]>0)
514 if (m_radioWidth
[i
]<0)
516 // It's a labeled item
517 GetWindowText((HWND
) m_radioButtons
[i
], buf
, 300);
518 GetTextExtent(buf
, ¤t_width
, &cyf
,NULL
,NULL
,GetFont());
520 // How do we find out radio button bitmap size!!
521 // By adjusting them carefully, manually :-)
522 eachWidth
= (int)(current_width
+ RADIO_SIZE
);
523 eachHeight
= (int)((3*cyf
)/2);
527 eachWidth
= m_radioWidth
[i
] ;
528 eachHeight
= m_radioHeight
[i
] ;
531 MoveWindow((HWND
) m_radioButtons
[i
],x_offset
,y_offset
,eachWidth
,eachHeight
,TRUE
);
532 if (m_windowStyle
& wxRA_VERTICAL
)
534 y_offset
+= maxHeight
;
535 if (m_radioWidth
[0]>0)
539 x_offset
+= maxWidth
+ cx1
;
543 void wxRadioBox::GetSize(int *width
, int *height
) const
546 rect
.left
= -1; rect
.right
= -1; rect
.top
= -1; rect
.bottom
= -1;
549 wxFindMaxSize(m_hWnd
, &rect
);
552 for (i
= 0; i
< m_noItems
; i
++)
553 wxFindMaxSize(m_radioButtons
[i
], &rect
);
555 *width
= rect
.right
- rect
.left
;
556 *height
= rect
.bottom
- rect
.top
;
559 void wxRadioBox::GetPosition(int *x
, int *y
) const
561 wxWindow
*parent
= GetParent();
563 rect
.left
= -1; rect
.right
= -1; rect
.top
= -1; rect
.bottom
= -1;
566 for (i
= 0; i
< m_noItems
; i
++)
567 wxFindMaxSize(m_radioButtons
[i
], &rect
);
570 wxFindMaxSize(m_hWnd
, &rect
);
572 // Since we now have the absolute screen coords,
573 // if there's a parent we must subtract its top left corner
579 ::ScreenToClient((HWND
) parent
->GetHWND(), &point
);
581 // We may be faking the client origin.
582 // So a window that's really at (0, 30) may appear
583 // (to wxWin apps) to be at (0, 0).
586 wxPoint
pt(GetParent()->GetClientAreaOrigin());
595 wxString
wxRadioBox::GetLabel(void) const
599 GetWindowText((HWND
) m_hWnd
, wxBuffer
, 300);
600 return wxString(wxBuffer
);
602 else return wxString("");
605 void wxRadioBox::SetLabel(const wxString
& label
)
608 SetWindowText((HWND
) m_hWnd
, label
);
611 void wxRadioBox::SetFocus(void)
615 ::SetFocus((HWND) m_radioButtons[0]);
617 /* Begin Alberts Patch 26. 5. 1997*/
620 if (m_selectedButton
== -1)
621 ::SetFocus((HWND
) m_radioButtons
[0]);
623 ::SetFocus((HWND
) m_radioButtons
[m_selectedButton
]);
625 /* Ende Alberts Patch*/
629 bool wxRadioBox::Show(bool show
)
637 ShowWindow((HWND
) m_hWnd
, cshow
);
639 for (i
= 0; i
< m_noItems
; i
++)
640 ShowWindow((HWND
) m_radioButtons
[i
], cshow
);
644 // Enable a specific button
645 void wxRadioBox::Enable(int item
, bool enable
)
648 wxWindow::Enable(enable
) ;
649 else if (item
< m_noItems
)
650 ::EnableWindow((HWND
) m_radioButtons
[item
], enable
);
653 // Enable all controls
654 void wxRadioBox::Enable(bool enable
)
656 wxControl::Enable(enable
);
659 for (i
= 0; i
< m_noItems
; i
++)
660 ::EnableWindow((HWND
) m_radioButtons
[i
], enable
);
663 // Show a specific button
664 void wxRadioBox::Show(int item
, bool show
)
667 wxRadioBox::Show(show
) ;
668 else if (item
< m_noItems
)
675 ShowWindow((HWND
) m_radioButtons
[item
], cshow
);
679 WXHBRUSH
wxRadioBox::OnCtlColor(WXHDC pDC
, WXHWND pWnd
, WXUINT nCtlColor
,
680 WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
685 HBRUSH hbrush
= Ctl3dCtlColorEx(message
, wParam
, lParam
);
686 return (WXHBRUSH
) hbrush
;
690 if (GetParent()->GetTransparentBackground())
691 SetBkMode((HDC
) pDC
, TRANSPARENT
);
693 SetBkMode((HDC
) pDC
, OPAQUE
);
695 ::SetBkColor((HDC
) pDC
, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue()));
696 ::SetTextColor((HDC
) pDC
, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue()));
698 wxBrush
*backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour(), wxSOLID
);
700 // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush
701 // has a zero usage count.
702 // backgroundBrush->RealizeResource();
703 return (WXHBRUSH
) backgroundBrush
->GetResourceHandle();
706 // For single selection items only
707 wxString
wxRadioBox::GetStringSelection (void) const
709 int sel
= GetSelection ();
711 return this->GetString (sel
);
716 bool wxRadioBox::SetStringSelection (const wxString
& s
)
718 int sel
= FindString (s
);
729 void wxRadioBox::SetLabelFont(wxFont *font)
731 // Decrement the usage count of the old label font
732 // (we may be able to free it up)
734 labelFont->ReleaseResource();
738 // Increment usage count
742 HWND hWnd = GetHWND();
747 font->RealizeResource();
749 if (font->GetResourceHandle())
750 SendMessage(hWnd, WM_SETFONT,
751 (WPARAM)font->GetResourceHandle(),TRUE);
758 bool wxRadioBox::ContainsHWND(WXHWND hWnd
) const
761 for (i
= 0; i
< Number(); i
++)
762 if (GetRadioButtons()[i
] == hWnd
)
767 void wxRadioBox::Command (wxCommandEvent
& event
)
769 SetSelection (event
.m_commandInt
);
770 ProcessCommand (event
);