]> git.saurik.com Git - wxWidgets.git/blame - src/msw/radiobox.cpp
added test mode to wxLongLongWx which allowed to find the bug in operator*=()
[wxWidgets.git] / src / msw / radiobox.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: radiobox.cpp
3// Purpose: wxRadioBox
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
c085e333 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
e373f51b
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
da07e033 21 #pragma implementation "radiobox.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
da07e033 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
da07e033
VZ
32 #include "wx/bitmap.h"
33 #include "wx/brush.h"
34 #include "wx/radiobox.h"
381dd4bf 35 #include "wx/log.h"
2bda0e17
KB
36#endif
37
38#include "wx/msw/private.h"
39
f048e32f 40#if wxUSE_TOOLTIPS
c25a510b
JS
41
42#ifndef __GNUWIN32__
f048e32f 43 #include <commctrl.h>
c25a510b 44#endif
f048e32f
VZ
45
46 #include "wx/tooltip.h"
47#endif // wxUSE_TOOLTIPS
48
da07e033 49 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
2bda0e17 50
f048e32f
VZ
51// VZ: the new behaviour is to create the radio buttons as children of the
52// radiobox instead of creating them as children of the radiobox' parent.
53//
54// This seems more logical, more consistent with what other frameworks do
55// and allows tooltips to work with radioboxes, so there should be no
56// reason to revert to the backward compatible behaviour - but I still
57// leave this possibility just in case.
c25a510b
JS
58
59// For some reason, the background colour is set wrongly in WIN16 mode
60// if we use the new method.
61
62#ifdef __WIN16__
63#define RADIOBTN_PARENT_IS_RADIOBOX 0
64#else
f048e32f 65#define RADIOBTN_PARENT_IS_RADIOBOX 1
c25a510b 66#endif
f048e32f 67
e373f51b
VZ
68// ---------------------------------------------------------------------------
69// private functions
70// ---------------------------------------------------------------------------
71
e373f51b 72// wnd proc for radio buttons
2a47d3c1 73#ifdef __WIN32__
e373f51b
VZ
74LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hWnd,
75 UINT message,
76 WPARAM wParam,
77 LPARAM lParam);
78
79// ---------------------------------------------------------------------------
80// global vars
81// ---------------------------------------------------------------------------
82
83// the pointer to standard radio button wnd proc
20e85460 84static WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
e373f51b 85
42e69d6b
VZ
86#endif // __WIN32__
87
e373f51b
VZ
88// ===========================================================================
89// implementation
90// ===========================================================================
91
92// ---------------------------------------------------------------------------
93// wxRadioBox
94// ---------------------------------------------------------------------------
95
96int wxRadioBox::GetNumVer() const
97{
98 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
99 {
100 return m_majorDim;
101 }
102 else
103 {
104 return (m_noItems + m_majorDim - 1)/m_majorDim;
105 }
106}
107
108int wxRadioBox::GetNumHor() const
109{
110 if ( m_windowStyle & wxRA_SPECIFY_ROWS )
111 {
112 return (m_noItems + m_majorDim - 1)/m_majorDim;
113 }
114 else
115 {
116 return m_majorDim;
117 }
118}
119
42e69d6b 120bool wxRadioBox::MSWCommand(WXUINT cmd, WXWORD id)
2bda0e17 121{
42e69d6b 122 if ( cmd == BN_CLICKED )
da07e033 123 {
9a5ccab4 124 int selectedButton = -1;
e373f51b
VZ
125
126 for ( int i = 0; i < m_noItems; i++ )
127 {
cc2b7472 128 if ( id == wxGetWindowId(m_radioButtons[i]) )
e373f51b 129 {
9a5ccab4 130 selectedButton = i;
e373f51b
VZ
131
132 break;
133 }
134 }
135
223d09f6 136 wxASSERT_MSG( selectedButton != -1, wxT("click from alien button?") );
2bda0e17 137
9a5ccab4
VZ
138 if ( selectedButton != m_selectedButton )
139 {
140 m_selectedButton = selectedButton;
141
142 SendNotificationEvent();
143 }
144 //else: don't generate events when the selection doesn't change
e373f51b 145
da07e033
VZ
146 return TRUE;
147 }
e373f51b
VZ
148 else
149 return FALSE;
2bda0e17
KB
150}
151
152#if WXWIN_COMPATIBILITY
153wxRadioBox::wxRadioBox(wxWindow *parent, wxFunction func, const char *title,
da07e033
VZ
154 int x, int y, int width, int height,
155 int n, char **choices,
156 int majorDim, long style, const char *name)
2bda0e17
KB
157{
158 wxString *choices2 = new wxString[n];
159 for ( int i = 0; i < n; i ++) choices2[i] = choices[i];
160 Create(parent, -1, title, wxPoint(x, y), wxSize(width, height), n, choices2, majorDim, style,
da07e033 161 wxDefaultValidator, name);
2bda0e17
KB
162 Callback(func);
163 delete choices2;
164}
165
166#endif
167
168// Radio box item
e373f51b 169wxRadioBox::wxRadioBox()
2bda0e17 170{
da07e033
VZ
171 m_selectedButton = -1;
172 m_noItems = 0;
173 m_noRowsOrCols = 0;
174 m_radioButtons = NULL;
e373f51b
VZ
175 m_majorDim = 0;
176 m_radioWidth = NULL;
177 m_radioHeight = NULL;
2bda0e17
KB
178}
179
f048e32f
VZ
180bool wxRadioBox::Create(wxWindow *parent,
181 wxWindowID id,
182 const wxString& title,
183 const wxPoint& pos,
184 const wxSize& size,
185 int n,
186 const wxString choices[],
187 int majorDim,
188 long style,
189 const wxValidator& val,
190 const wxString& name)
2bda0e17 191{
f048e32f 192 // initialize members
da07e033 193 m_selectedButton = -1;
4afd7529 194 m_noItems = 0;
2bda0e17 195
f048e32f 196 m_majorDim = majorDim == 0 ? n : majorDim;
da07e033 197 m_noRowsOrCols = majorDim;
da07e033 198
f048e32f
VZ
199 // common initialization
200 if ( !CreateControl(parent, id, pos, size, style, val, name) )
201 return FALSE;
2bda0e17 202
f048e32f
VZ
203 // create the static box
204 if ( !MSWCreateControl(wxT("BUTTON"), BS_GROUPBOX, pos, size, title, 0) )
205 return FALSE;
da07e033 206
f048e32f 207 // and now create the buttons
4afd7529 208 m_noItems = n;
f048e32f
VZ
209#if RADIOBTN_PARENT_IS_RADIOBOX
210 HWND hwndParent = GetHwnd();
211#else
212 HWND hwndParent = GetHwndOf(parent);
213#endif
da07e033
VZ
214
215 // Some radio boxes test consecutive id.
e373f51b 216 (void)NewControlId();
da07e033 217 m_radioButtons = new WXHWND[n];
e373f51b
VZ
218 m_radioWidth = new int[n];
219 m_radioHeight = new int[n];
f048e32f
VZ
220
221 WXHFONT hfont = 0;
222 wxFont& font = GetFont();
223 if ( font.Ok() )
da07e033 224 {
f048e32f
VZ
225 hfont = font.GetResourceHandle();
226 }
227
228 for ( int i = 0; i < n; i++ )
229 {
230 m_radioWidth[i] =
231 m_radioHeight[i] = -1;
232 long styleBtn = BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE;
e373f51b 233 if ( i == 0 && style == 0 )
f048e32f
VZ
234 styleBtn |= WS_GROUP;
235
da07e033 236 long newId = NewControlId();
da07e033 237
f048e32f
VZ
238 HWND hwndBtn = ::CreateWindow(_T("BUTTON"),
239 choices[i],
240 styleBtn,
241 0, 0, 0, 0, // will be set in SetSize()
e373f51b 242 hwndParent,
f048e32f
VZ
243 (HMENU)newId,
244 wxGetInstance(),
e373f51b 245 NULL);
2bda0e17 246
f048e32f
VZ
247 if ( !hwndBtn )
248 {
249 wxLogLastError("CreateWindow(radio btn)");
250
251 return FALSE;
252 }
253
e373f51b 254 m_radioButtons[i] = (WXHWND)hwndBtn;
42e69d6b 255
e373f51b 256 SubclassRadioButton((WXHWND)hwndBtn);
2bda0e17 257
f048e32f 258 if ( hfont )
da07e033 259 {
f048e32f 260 ::SendMessage(hwndBtn, WM_SETFONT, (WPARAM)hfont, 0L);
da07e033 261 }
e373f51b 262
f048e32f 263 m_subControls.Add(newId);
da07e033 264 }
e373f51b 265
da07e033 266 // Create a dummy radio control to end the group.
f048e32f
VZ
267 (void)::CreateWindow(_T("BUTTON"),
268 _T(""),
269 WS_GROUP | BS_AUTORADIOBUTTON | WS_CHILD,
e373f51b
VZ
270 0, 0, 0, 0, hwndParent,
271 (HMENU)NewControlId(), wxGetInstance(), NULL);
2bda0e17 272
da07e033 273 SetSelection(0);
2bda0e17 274
f048e32f 275 SetSize(pos.x, pos.y, size.x, size.y);
2bda0e17 276
da07e033 277 return TRUE;
2bda0e17 278}
2bda0e17 279
e373f51b 280wxRadioBox::~wxRadioBox()
2bda0e17 281{
da07e033 282 m_isBeingDeleted = TRUE;
1eb20d4a 283
da07e033
VZ
284 if (m_radioButtons)
285 {
286 int i;
287 for (i = 0; i < m_noItems; i++)
42e69d6b 288 ::DestroyWindow((HWND)m_radioButtons[i]);
da07e033
VZ
289 delete[] m_radioButtons;
290 }
42e69d6b 291
da07e033 292 if (m_radioWidth)
e373f51b 293 delete[] m_radioWidth;
da07e033 294 if (m_radioHeight)
e373f51b 295 delete[] m_radioHeight;
2bda0e17
KB
296
297}
298
d66a042c
VZ
299wxString wxRadioBox::GetLabel(int item) const
300{
223d09f6 301 wxCHECK_MSG( item >= 0 && item < m_noItems, wxT(""), wxT("invalid radiobox index") );
d66a042c
VZ
302
303 return wxGetWindowText(m_radioButtons[item]);
304}
305
debe6624 306void wxRadioBox::SetLabel(int item, const wxString& label)
2bda0e17 307{
223d09f6 308 wxCHECK_RET( item >= 0 && item < m_noItems, wxT("invalid radiobox index") );
d66a042c 309
e373f51b 310 m_radioWidth[item] = m_radioHeight[item] = -1;
42e69d6b 311 SetWindowText((HWND)m_radioButtons[item], label.c_str());
2bda0e17
KB
312}
313
debe6624 314void wxRadioBox::SetLabel(int item, wxBitmap *bitmap)
2bda0e17 315{
da07e033 316 /*
e373f51b
VZ
317 m_radioWidth[item] = bitmap->GetWidth() + FB_MARGIN;
318 m_radioHeight[item] = bitmap->GetHeight() + FB_MARGIN;
da07e033 319 */
223d09f6 320 wxFAIL_MSG(wxT("not implemented"));
2bda0e17
KB
321}
322
323int wxRadioBox::FindString(const wxString& s) const
324{
42e69d6b 325 for (int i = 0; i < m_noItems; i++)
da07e033 326 {
42e69d6b 327 if ( s == wxGetWindowText(m_radioButtons[i]) )
da07e033
VZ
328 return i;
329 }
42e69d6b
VZ
330
331 return wxNOT_FOUND;
2bda0e17
KB
332}
333
debe6624 334void wxRadioBox::SetSelection(int N)
2bda0e17 335{
223d09f6 336 wxCHECK_RET( (N >= 0) && (N < m_noItems), wxT("invalid radiobox index") );
2bda0e17 337
da07e033
VZ
338 // Following necessary for Win32s, because Win32s translate BM_SETCHECK
339 if (m_selectedButton >= 0 && m_selectedButton < m_noItems)
e373f51b
VZ
340 ::SendMessage((HWND) m_radioButtons[m_selectedButton], BM_SETCHECK, 0, 0L);
341
342 ::SendMessage((HWND)m_radioButtons[N], BM_SETCHECK, 1, 0L);
343 ::SetFocus((HWND)m_radioButtons[N]);
2bda0e17 344
da07e033 345 m_selectedButton = N;
2bda0e17
KB
346}
347
348// Get single selection, for single choice list items
e373f51b 349int wxRadioBox::GetSelection() const
2bda0e17 350{
da07e033 351 return m_selectedButton;
2bda0e17
KB
352}
353
354// Find string for position
debe6624 355wxString wxRadioBox::GetString(int N) const
2bda0e17 356{
e373f51b 357 return wxGetWindowText(m_radioButtons[N]);
2bda0e17
KB
358}
359
1f916a19 360// Restored old code.
bfc6fde4 361void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
1f916a19 362{
4438caf4
VZ
363 int currentX, currentY;
364 GetPosition(&currentX, &currentY);
c219cecc
VZ
365 int widthOld, heightOld;
366 GetSize(&widthOld, &heightOld);
367
4438caf4
VZ
368 int xx = x;
369 int yy = y;
370
ce96b7a0 371 if (x == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
4438caf4 372 xx = currentX;
ce96b7a0 373 if (y == -1 && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
4438caf4
VZ
374 yy = currentY;
375
f048e32f
VZ
376#if RADIOBTN_PARENT_IS_RADIOBOX
377 int y_offset = 0;
378 int x_offset = 0;
379#else
4438caf4
VZ
380 int y_offset = yy;
381 int x_offset = xx;
f048e32f
VZ
382#endif
383
4438caf4
VZ
384 int current_width, cyf;
385
386 int cx1,cy1;
387 wxGetCharSize(m_hWnd, &cx1, &cy1, & GetFont());
388
389 // Attempt to have a look coherent with other platforms: We compute the
390 // biggest toggle dim, then we align all items according this value.
391 int maxWidth = -1;
392 int maxHeight = -1;
393
394 int i;
395 for (i = 0 ; i < m_noItems; i++)
1f916a19 396 {
4438caf4
VZ
397 int eachWidth;
398 int eachHeight;
399 if (m_radioWidth[i]<0)
400 {
401 // It's a labelled toggle
f048e32f
VZ
402 GetTextExtent(wxGetWindowText(m_radioButtons[i]),
403 &current_width, &cyf);
4438caf4
VZ
404 eachWidth = (int)(current_width + RADIO_SIZE);
405 eachHeight = (int)((3*cyf)/2);
406 }
407 else
408 {
409 eachWidth = m_radioWidth[i];
410 eachHeight = m_radioHeight[i];
411 }
412
413 if (maxWidth<eachWidth)
414 maxWidth = eachWidth;
415 if (maxHeight<eachHeight)
416 maxHeight = eachHeight;
1f916a19 417 }
1f916a19 418
4438caf4
VZ
419 if (m_hWnd)
420 {
421 int totWidth;
422 int totHeight;
1f916a19 423
4438caf4 424 int nbHor = GetNumHor(),
f048e32f 425 nbVer = GetNumVer();
1f916a19 426
4438caf4
VZ
427 // this formula works, but I don't know why.
428 // Please, be sure what you do if you modify it!!
429 if (m_radioWidth[0]<0)
430 totHeight = (nbVer * maxHeight) + cy1/2;
431 else
432 totHeight = nbVer * (maxHeight+cy1/2);
433 totWidth = nbHor * (maxWidth+cx1);
1f916a19 434
4438caf4
VZ
435 int extraHeight = cy1;
436
c219cecc 437#if defined(CTL3D) && !CTL3D
4438caf4
VZ
438 // Requires a bigger group box in plain Windows
439 extraHeight *= 3;
440 extraHeight /= 2;
1f916a19 441#endif
4438caf4 442
c219cecc
VZ
443 // only change our width/height if asked for
444 if ( width == -1 )
445 {
446 if ( sizeFlags & wxSIZE_AUTO_WIDTH )
447 width = totWidth + cx1;
448 else
449 width = widthOld;
450 }
451
452 if ( height == -1 )
453 {
454 if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
455 height = totHeight + extraHeight;
a17e237f 456 else
c219cecc
VZ
457 height = heightOld;
458 }
459
f048e32f 460 ::MoveWindow(GetHwnd(), xx, yy, width, height, TRUE);
4438caf4
VZ
461
462 x_offset += cx1;
463 y_offset += cy1;
464 }
1f916a19 465
c219cecc 466#if defined(CTL3D) && (!CTL3D)
4438caf4
VZ
467 y_offset += (int)(cy1/2); // Fudge factor since buttons overlapped label
468 // JACS 2/12/93. CTL3D draws group label quite high.
1f916a19 469#endif
4438caf4
VZ
470 int startX = x_offset;
471 int startY = y_offset;
1f916a19 472
4438caf4 473 for ( i = 0 ; i < m_noItems; i++)
1f916a19 474 {
4438caf4
VZ
475 // Bidimensional radio adjustment
476 if (i&&((i%m_majorDim)==0)) // Why is this omitted for i = 0?
477 {
478 if (m_windowStyle & wxRA_VERTICAL)
479 {
480 y_offset = startY;
481 x_offset += maxWidth + cx1;
482 }
483 else
484 {
485 x_offset = startX;
486 y_offset += maxHeight;
487 if (m_radioWidth[0]>0)
488 y_offset += cy1/2;
489 }
490 }
491 int eachWidth;
492 int eachHeight;
493 if (m_radioWidth[i]<0)
494 {
495 // It's a labeled item
f048e32f
VZ
496 GetTextExtent(wxGetWindowText(m_radioButtons[i]),
497 &current_width, &cyf);
4438caf4
VZ
498
499 // How do we find out radio button bitmap size!!
500 // By adjusting them carefully, manually :-)
501 eachWidth = (int)(current_width + RADIO_SIZE);
502 eachHeight = (int)((3*cyf)/2);
503 }
504 else
505 {
506 eachWidth = m_radioWidth[i];
507 eachHeight = m_radioHeight[i];
508 }
1f916a19 509
f048e32f
VZ
510 // VZ: make all buttons of the same, maximal size - like this they
511 // cover the radiobox entirely and the radiobox tooltips are always
512 // shown (otherwise they are not when the mouse pointer is in the
513 // radiobox part not belonging to any radiobutton)
514 ::MoveWindow((HWND)m_radioButtons[i],
515 x_offset, y_offset, maxWidth, maxHeight,
516 TRUE);
4438caf4
VZ
517
518 if (m_windowStyle & wxRA_SPECIFY_ROWS)
519 {
520 y_offset += maxHeight;
521 if (m_radioWidth[0]>0)
522 y_offset += cy1/2;
523 }
524 else
525 x_offset += maxWidth + cx1;
1f916a19 526 }
1f916a19
JS
527}
528
2bda0e17
KB
529void wxRadioBox::GetSize(int *width, int *height) const
530{
da07e033
VZ
531 RECT rect;
532 rect.left = -1; rect.right = -1; rect.top = -1; rect.bottom = -1;
2bda0e17 533
da07e033
VZ
534 if (m_hWnd)
535 wxFindMaxSize(m_hWnd, &rect);
2bda0e17 536
da07e033
VZ
537 int i;
538 for (i = 0; i < m_noItems; i++)
539 wxFindMaxSize(m_radioButtons[i], &rect);
2bda0e17 540
da07e033
VZ
541 *width = rect.right - rect.left;
542 *height = rect.bottom - rect.top;
2bda0e17
KB
543}
544
545void wxRadioBox::GetPosition(int *x, int *y) const
546{
da07e033 547 wxWindow *parent = GetParent();
f048e32f 548 RECT rect = { -1, -1, -1, -1 };
da07e033
VZ
549
550 int i;
551 for (i = 0; i < m_noItems; i++)
552 wxFindMaxSize(m_radioButtons[i], &rect);
553
554 if (m_hWnd)
555 wxFindMaxSize(m_hWnd, &rect);
556
f048e32f
VZ
557 // Since we now have the absolute screen coords, if there's a parent we
558 // must subtract its top left corner
da07e033
VZ
559 POINT point;
560 point.x = rect.left;
561 point.y = rect.top;
562 if (parent)
563 {
564 ::ScreenToClient((HWND) parent->GetHWND(), &point);
565 }
f048e32f
VZ
566
567 // We may be faking the client origin. So a window that's really at (0, 30)
568 // may appear (to wxWin apps) to be at (0, 0).
da07e033
VZ
569 if (GetParent())
570 {
571 wxPoint pt(GetParent()->GetClientAreaOrigin());
572 point.x -= pt.x;
573 point.y -= pt.y;
574 }
575
576 *x = point.x;
577 *y = point.y;
2bda0e17
KB
578}
579
e373f51b 580void wxRadioBox::SetFocus()
2bda0e17 581{
da07e033
VZ
582 if (m_noItems > 0)
583 {
584 if (m_selectedButton == -1)
585 ::SetFocus((HWND) m_radioButtons[0]);
586 else
587 ::SetFocus((HWND) m_radioButtons[m_selectedButton]);
588 }
2bda0e17
KB
589
590}
591
debe6624 592bool wxRadioBox::Show(bool show)
2bda0e17 593{
42e69d6b
VZ
594 if ( !wxControl::Show(show) )
595 return FALSE;
596
597 int nCmdShow = show ? SW_SHOW : SW_HIDE;
598 for ( int i = 0; i < m_noItems; i++ )
599 {
600 ::ShowWindow((HWND)m_radioButtons[i], nCmdShow);
601 }
602
da07e033 603 return TRUE;
2bda0e17
KB
604}
605
606// Enable a specific button
debe6624 607void wxRadioBox::Enable(int item, bool enable)
2bda0e17 608{
42e69d6b 609 wxCHECK_RET( item >= 0 && item < m_noItems,
223d09f6 610 wxT("invalid item in wxRadioBox::Enable()") );
42e69d6b
VZ
611
612 ::EnableWindow((HWND) m_radioButtons[item], enable);
2bda0e17
KB
613}
614
615// Enable all controls
cc2b7472 616bool wxRadioBox::Enable(bool enable)
2bda0e17 617{
cc2b7472
VZ
618 if ( !wxControl::Enable(enable) )
619 return FALSE;
1eb20d4a 620
42e69d6b 621 for (int i = 0; i < m_noItems; i++)
da07e033 622 ::EnableWindow((HWND) m_radioButtons[i], enable);
cc2b7472
VZ
623
624 return TRUE;
2bda0e17
KB
625}
626
627// Show a specific button
debe6624 628void wxRadioBox::Show(int item, bool show)
2bda0e17 629{
42e69d6b 630 wxCHECK_RET( item >= 0 && item < m_noItems,
223d09f6 631 wxT("invalid item in wxRadioBox::Show()") );
42e69d6b
VZ
632
633 ::ShowWindow((HWND)m_radioButtons[item], show ? SW_SHOW : SW_HIDE);
2bda0e17
KB
634}
635
2bda0e17 636// For single selection items only
e373f51b 637wxString wxRadioBox::GetStringSelection() const
2bda0e17 638{
e373f51b
VZ
639 wxString result;
640 int sel = GetSelection();
da07e033 641 if (sel > -1)
e373f51b
VZ
642 result = GetString(sel);
643
644 return result;
2bda0e17
KB
645}
646
e373f51b 647bool wxRadioBox::SetStringSelection(const wxString& s)
2bda0e17 648{
da07e033
VZ
649 int sel = FindString (s);
650 if (sel > -1)
2bda0e17 651 {
da07e033
VZ
652 SetSelection (sel);
653 return TRUE;
2bda0e17 654 }
da07e033
VZ
655 else
656 return FALSE;
2bda0e17
KB
657}
658
2bda0e17
KB
659bool wxRadioBox::ContainsHWND(WXHWND hWnd) const
660{
da07e033 661 int i;
2bda0e17 662 for (i = 0; i < Number(); i++)
42e69d6b 663 {
da07e033
VZ
664 if (GetRadioButtons()[i] == hWnd)
665 return TRUE;
42e69d6b
VZ
666 }
667
da07e033 668 return FALSE;
2bda0e17
KB
669}
670
4afd7529 671void wxRadioBox::Command(wxCommandEvent & event)
2bda0e17 672{
da07e033
VZ
673 SetSelection (event.m_commandInt);
674 ProcessCommand (event);
2bda0e17
KB
675}
676
e373f51b
VZ
677void wxRadioBox::SubclassRadioButton(WXHWND hWndBtn)
678{
42e69d6b 679#ifdef __WIN32__
e373f51b
VZ
680 HWND hwndBtn = (HWND)hWndBtn;
681
682 if ( !s_wndprocRadioBtn )
20e85460 683 s_wndprocRadioBtn = (WXFARPROC)::GetWindowLong(hwndBtn, GWL_WNDPROC);
e373f51b 684
2a47d3c1 685 // No GWL_USERDATA in Win16, so omit this subclassing.
e373f51b
VZ
686 ::SetWindowLong(hwndBtn, GWL_WNDPROC, (long)wxRadioBtnWndProc);
687 ::SetWindowLong(hwndBtn, GWL_USERDATA, (long)this);
42e69d6b 688#endif // __WIN32__
e373f51b
VZ
689}
690
9a5ccab4
VZ
691void wxRadioBox::SendNotificationEvent()
692{
693 wxCommandEvent event(wxEVT_COMMAND_RADIOBOX_SELECTED, m_windowId);
694 event.SetInt( m_selectedButton );
36dda0de 695 event.SetString( GetString(m_selectedButton) );
9a5ccab4
VZ
696 event.SetEventObject( this );
697 ProcessCommand(event);
698}
699
4afd7529
VZ
700bool wxRadioBox::SetFont(const wxFont& font)
701{
702 if ( !wxControl::SetFont(font) )
703 {
704 // nothing to do
705 return FALSE;
706 }
707
708 // also set the font of our radio buttons
709 WXHFONT hfont = wxFont(font).GetResourceHandle();
710 for ( int n = 0; n < m_noItems; n++ )
711 {
712 ::SendMessage((HWND)m_radioButtons[n], WM_SETFONT, (WPARAM)hfont, 0L);
713 }
714
715 return TRUE;
716}
717
c92d798f
JS
718long wxRadioBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
719{
720 // This is required for the radiobox to be sensitive to mouse input,
721 // e.g. for Dialog Editor.
722 if (nMsg == WM_NCHITTEST)
723 {
724 int xPos = LOWORD(lParam); // horizontal position of cursor
725 int yPos = HIWORD(lParam); // vertical position of cursor
726
727 ScreenToClient(&xPos, &yPos);
728
729 // Make sure you can drag by the top of the groupbox, but let
730 // other (enclosed) controls get mouse events also
731 if (yPos < 10)
732 return (long)HTCLIENT;
733 }
734
735 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
736}
737
e373f51b
VZ
738// ---------------------------------------------------------------------------
739// window proc for radio buttons
740// ---------------------------------------------------------------------------
741
2a47d3c1
JS
742#ifdef __WIN32__
743
e373f51b
VZ
744LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
745 UINT msg,
746 WPARAM wParam,
747 LPARAM lParam)
748{
f048e32f
VZ
749 bool processed = FALSE;
750 if ( msg == WM_KEYDOWN
751#if wxUSE_TOOLTIPS
752 || msg == WM_NOTIFY
753#endif // wxUSE_TOOLTIPS
754 )
e373f51b
VZ
755 {
756 wxRadioBox *radiobox = (wxRadioBox *)::GetWindowLong(hwnd, GWL_USERDATA);
757
223d09f6 758 wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
e373f51b 759
c25a510b 760#if wxUSE_TOOLTIPS && !defined(__GNUWIN32__)
f048e32f 761 if ( msg == WM_NOTIFY )
e373f51b 762 {
f048e32f
VZ
763 NMHDR* hdr = (NMHDR *)lParam;
764 if ( (int)hdr->code == TTN_NEEDTEXT )
765 {
766 wxToolTip *tt = radiobox->GetToolTip();
767 if ( tt )
e373f51b 768 {
f048e32f
VZ
769 TOOLTIPTEXT *ttt = (TOOLTIPTEXT *)lParam;
770 ttt->lpszText = (wxChar *)tt->GetTip().c_str();
e373f51b 771
f048e32f 772 processed = TRUE;
e373f51b 773 }
f048e32f 774 }
e373f51b 775 }
f048e32f
VZ
776 else // msg == WM_KEYDOWN
777#endif // wxUSE_TOOLTIPS
e373f51b 778 {
f048e32f
VZ
779 processed = TRUE;
780
781 int sel = radiobox->GetSelection();
782
783 switch ( wParam )
9a5ccab4 784 {
f048e32f
VZ
785 case VK_UP:
786 sel--;
787 break;
788
789 case VK_LEFT:
790 sel -= radiobox->GetNumVer();
791 break;
792
793 case VK_DOWN:
794 sel++;
795 break;
796
797 case VK_RIGHT:
798 sel += radiobox->GetNumVer();
799 break;
800
801 case VK_TAB:
802 {
803 wxNavigationKeyEvent event;
804 event.SetDirection(!(::GetKeyState(VK_SHIFT) & 0x100));
805 event.SetWindowChange(FALSE);
806 event.SetEventObject(radiobox);
807
808 if ( radiobox->GetEventHandler()->ProcessEvent(event) )
809 return 0;
810 }
811 // fall through
812
813 default:
814 processed = FALSE;
815 }
816
817 if ( processed )
818 {
819 if ( sel >= 0 && sel < radiobox->Number() )
820 {
821 radiobox->SetSelection(sel);
9a5ccab4 822
f048e32f
VZ
823 // emulate the button click
824 radiobox->SendNotificationEvent();
825 }
9a5ccab4 826 }
e373f51b
VZ
827 }
828 }
829
f048e32f 830 if ( processed )
e373f51b 831 return 0;
f048e32f
VZ
832
833 return ::CallWindowProc(CASTWNDPROC s_wndprocRadioBtn, hwnd, msg, wParam, lParam);
e373f51b 834}
42e69d6b
VZ
835
836#endif // __WIN32__
e373f51b 837