]> git.saurik.com Git - wxWidgets.git/blob - src/msw/slider95.cpp
defs.h doubled include fixed.
[wxWidgets.git] / src / msw / slider95.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/slider.cpp
3 // Purpose: wxSlider, using the Win95 (and later) trackbar control
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart 1998
9 // Vadim Zeitlin 2004
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
12
13 // ============================================================================
14 // declarations
15 // ============================================================================
16
17 // ----------------------------------------------------------------------------
18 // headers
19 // ----------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 #ifdef __BORLANDC__
25 #pragma hdrstop
26 #endif
27
28 #if wxUSE_SLIDER
29
30 #ifndef WX_PRECOMP
31 #include "wx/brush.h"
32 #endif
33
34 #include "wx/slider.h"
35 #include "wx/msw/subwin.h"
36
37 #if !(defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__))
38 #include <commctrl.h>
39 #endif
40
41 // ----------------------------------------------------------------------------
42 // constants
43 // ----------------------------------------------------------------------------
44
45 // indices of labels in wxSlider::m_labels
46 enum
47 {
48 SliderLabel_Min,
49 SliderLabel_Max,
50 SliderLabel_Value,
51 SliderLabel_Last
52 };
53
54 // the gap between the slider and the labels, in pixels
55 static const int HGAP = 5;
56
57 // ----------------------------------------------------------------------------
58 // XTI
59 // ----------------------------------------------------------------------------
60
61 #if wxUSE_EXTENDED_RTTI
62 WX_DEFINE_FLAGS( wxSliderStyle )
63
64 wxBEGIN_FLAGS( wxSliderStyle )
65 // new style border flags, we put them first to
66 // use them for streaming out
67 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
68 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
69 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
70 wxFLAGS_MEMBER(wxBORDER_RAISED)
71 wxFLAGS_MEMBER(wxBORDER_STATIC)
72 wxFLAGS_MEMBER(wxBORDER_NONE)
73
74 // old style border flags
75 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
76 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
77 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
78 wxFLAGS_MEMBER(wxRAISED_BORDER)
79 wxFLAGS_MEMBER(wxSTATIC_BORDER)
80 wxFLAGS_MEMBER(wxBORDER)
81
82 // standard window styles
83 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
84 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
85 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
86 wxFLAGS_MEMBER(wxWANTS_CHARS)
87 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
88 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
89 wxFLAGS_MEMBER(wxVSCROLL)
90 wxFLAGS_MEMBER(wxHSCROLL)
91
92 wxFLAGS_MEMBER(wxSL_HORIZONTAL)
93 wxFLAGS_MEMBER(wxSL_VERTICAL)
94 wxFLAGS_MEMBER(wxSL_AUTOTICKS)
95 wxFLAGS_MEMBER(wxSL_LABELS)
96 wxFLAGS_MEMBER(wxSL_LEFT)
97 wxFLAGS_MEMBER(wxSL_TOP)
98 wxFLAGS_MEMBER(wxSL_RIGHT)
99 wxFLAGS_MEMBER(wxSL_BOTTOM)
100 wxFLAGS_MEMBER(wxSL_BOTH)
101 wxFLAGS_MEMBER(wxSL_SELRANGE)
102 wxFLAGS_MEMBER(wxSL_INVERSE)
103
104 wxEND_FLAGS( wxSliderStyle )
105
106 IMPLEMENT_DYNAMIC_CLASS_XTI(wxSlider, wxControl,"wx/scrolbar.h")
107
108 wxBEGIN_PROPERTIES_TABLE(wxSlider)
109 wxEVENT_RANGE_PROPERTY( Scroll , wxEVT_SCROLL_TOP , wxEVT_SCROLL_CHANGED , wxScrollEvent )
110 wxEVENT_PROPERTY( Updated , wxEVT_COMMAND_SLIDER_UPDATED , wxCommandEvent )
111
112 wxPROPERTY( Value , int , SetValue, GetValue , 0, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
113 wxPROPERTY( Minimum , int , SetMin, GetMin, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
114 wxPROPERTY( Maximum , int , SetMax, GetMax, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
115 wxPROPERTY( PageSize , int , SetPageSize, GetLineSize, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
116 wxPROPERTY( LineSize , int , SetLineSize, GetLineSize, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
117 wxPROPERTY( ThumbLength , int , SetThumbLength, GetThumbLength, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
118 wxPROPERTY_FLAGS( WindowStyle , wxSliderStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
119 wxEND_PROPERTIES_TABLE()
120
121 wxBEGIN_HANDLERS_TABLE(wxSlider)
122 wxEND_HANDLERS_TABLE()
123
124 wxCONSTRUCTOR_8( wxSlider , wxWindow* , Parent , wxWindowID , Id , int , Value , int , Minimum , int , Maximum , wxPoint , Position , wxSize , Size , long , WindowStyle )
125 #else
126 IMPLEMENT_DYNAMIC_CLASS(wxSlider, wxControl)
127 #endif
128
129 // ============================================================================
130 // wxSlider implementation
131 // ============================================================================
132
133 // ----------------------------------------------------------------------------
134 // construction
135 // ----------------------------------------------------------------------------
136
137 void wxSlider::Init()
138 {
139 m_labels = NULL;
140
141 m_pageSize = 1;
142 m_lineSize = 1;
143 m_rangeMax = 0;
144 m_rangeMin = 0;
145 m_tickFreq = 0;
146
147 m_isDragging = false;
148 }
149
150 bool
151 wxSlider::Create(wxWindow *parent,
152 wxWindowID id,
153 int value,
154 int minValue,
155 int maxValue,
156 const wxPoint& pos,
157 const wxSize& size,
158 long style,
159 const wxValidator& validator,
160 const wxString& name)
161 {
162 // our styles are redundant: wxSL_LEFT/RIGHT imply wxSL_VERTICAL and
163 // wxSL_TOP/BOTTOM imply wxSL_HORIZONTAL, but for backwards compatibility
164 // reasons we can't really change it, instead try to infer the orientation
165 // from the flags given to us here
166 switch ( style & (wxSL_LEFT | wxSL_RIGHT | wxSL_TOP | wxSL_BOTTOM) )
167 {
168 case wxSL_LEFT:
169 case wxSL_RIGHT:
170 style |= wxSL_VERTICAL;
171 break;
172
173 case wxSL_TOP:
174 case wxSL_BOTTOM:
175 style |= wxSL_HORIZONTAL;
176 break;
177
178 case 0:
179 // no specific direction, do we have at least the orientation?
180 if ( !(style & (wxSL_HORIZONTAL | wxSL_VERTICAL)) )
181 {
182 // no, choose default
183 style |= wxSL_BOTTOM | wxSL_HORIZONTAL;
184 }
185 };
186
187 wxASSERT_MSG( !(style & wxSL_VERTICAL) || !(style & wxSL_HORIZONTAL),
188 _T("incompatible slider direction and orientation") );
189
190
191 // initialize everything
192 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
193 return false;
194
195 // ensure that we have correct values for GetLabelsSize()
196 m_rangeMin = minValue;
197 m_rangeMax = maxValue;
198
199 // create the labels first, so that our DoGetBestSize() could take them
200 // into account
201 //
202 // note that we could simply create 3 wxStaticTexts here but it could
203 // result in some observable side effects at wx level (e.g. the parent of
204 // wxSlider would have 3 more children than expected) and so we prefer not
205 // to do it like this
206 if ( m_windowStyle & wxSL_LABELS )
207 {
208 m_labels = new wxSubwindows(SliderLabel_Last);
209
210 HWND hwndParent = GetHwndOf(parent);
211 for ( size_t n = 0; n < SliderLabel_Last; n++ )
212 {
213 (*m_labels)[n] = ::CreateWindow
214 (
215 wxT("STATIC"),
216 NULL,
217 WS_CHILD | WS_VISIBLE | SS_CENTER,
218 0, 0, 0, 0,
219 hwndParent,
220 (HMENU)NewControlId(),
221 wxGetInstance(),
222 NULL
223 );
224 }
225
226 m_labels->SetFont(GetFont());
227 }
228
229 // now create the main control too
230 if ( !MSWCreateControl(TRACKBAR_CLASS, wxEmptyString, pos, size) )
231 return false;
232
233 // and initialize everything
234 SetRange(minValue, maxValue);
235 SetValue(value);
236 SetPageSize((maxValue - minValue)/10);
237
238 // we need to position the labels correctly if we have them and if
239 // SetSize() hadn't been called before (when best size was determined by
240 // MSWCreateControl()) as in this case they haven't been put in place yet
241 if ( m_labels && size.x != wxDefaultCoord && size.y != wxDefaultCoord )
242 {
243 SetSize(size);
244 }
245
246 return true;
247 }
248
249 WXDWORD wxSlider::MSWGetStyle(long style, WXDWORD *exstyle) const
250 {
251 WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle);
252
253 // TBS_HORZ, TBS_RIGHT and TBS_BOTTOM are 0 but do include them for clarity
254 msStyle |= style & wxSL_VERTICAL ? TBS_VERT : TBS_HORZ;
255
256 if ( style & wxSL_BOTH )
257 {
258 // this fully specifies the style combined with TBS_VERT/HORZ above
259 msStyle |= TBS_BOTH;
260 }
261 else // choose one direction
262 {
263 if ( style & wxSL_LEFT )
264 msStyle |= TBS_LEFT;
265 else if ( style & wxSL_RIGHT )
266 msStyle |= TBS_RIGHT;
267 else if ( style & wxSL_TOP )
268 msStyle |= TBS_TOP;
269 else if ( style & wxSL_BOTTOM )
270 msStyle |= TBS_BOTTOM;
271 }
272
273 if ( style & wxSL_AUTOTICKS )
274 msStyle |= TBS_AUTOTICKS;
275 else
276 msStyle |= TBS_NOTICKS;
277
278 if ( style & wxSL_SELRANGE )
279 msStyle |= TBS_ENABLESELRANGE;
280
281 return msStyle;
282 }
283
284 wxSlider::~wxSlider()
285 {
286 delete m_labels;
287 }
288
289 // ----------------------------------------------------------------------------
290 // event handling
291 // ----------------------------------------------------------------------------
292
293 bool wxSlider::MSWOnScroll(int WXUNUSED(orientation),
294 WXWORD wParam,
295 WXWORD WXUNUSED(pos),
296 WXHWND control)
297 {
298 wxEventType scrollEvent;
299 switch ( wParam )
300 {
301 case SB_TOP:
302 scrollEvent = wxEVT_SCROLL_TOP;
303 break;
304
305 case SB_BOTTOM:
306 scrollEvent = wxEVT_SCROLL_BOTTOM;
307 break;
308
309 case SB_LINEUP:
310 scrollEvent = wxEVT_SCROLL_LINEUP;
311 break;
312
313 case SB_LINEDOWN:
314 scrollEvent = wxEVT_SCROLL_LINEDOWN;
315 break;
316
317 case SB_PAGEUP:
318 scrollEvent = wxEVT_SCROLL_PAGEUP;
319 break;
320
321 case SB_PAGEDOWN:
322 scrollEvent = wxEVT_SCROLL_PAGEDOWN;
323 break;
324
325 case SB_THUMBTRACK:
326 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
327 m_isDragging = true;
328 break;
329
330 case SB_THUMBPOSITION:
331 if ( m_isDragging )
332 {
333 scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
334 m_isDragging = false;
335 }
336 else
337 {
338 // this seems to only happen when the mouse wheel is used: in
339 // this case, as it might be unexpected to get THUMBRELEASE
340 // without preceding THUMBTRACKs, we don't generate it at all
341 // but generate CHANGED event because the control itself does
342 // not send us SB_ENDSCROLL for whatever reason when mouse
343 // wheel is used
344 scrollEvent = wxEVT_SCROLL_CHANGED;
345 }
346 break;
347
348 case SB_ENDSCROLL:
349 scrollEvent = wxEVT_SCROLL_CHANGED;
350 break;
351
352 default:
353 // unknown scroll event?
354 return false;
355 }
356
357 int newPos = ValueInvertOrNot((int) ::SendMessage((HWND) control, TBM_GETPOS, 0, 0));
358 if ( (newPos < GetMin()) || (newPos > GetMax()) )
359 {
360 // out of range - but we did process it
361 return true;
362 }
363
364 SetValue(newPos);
365
366 wxScrollEvent event(scrollEvent, m_windowId);
367 event.SetPosition(newPos);
368 event.SetEventObject( this );
369 GetEventHandler()->ProcessEvent(event);
370
371 wxCommandEvent cevent( wxEVT_COMMAND_SLIDER_UPDATED, GetId() );
372 cevent.SetInt( newPos );
373 cevent.SetEventObject( this );
374
375 return GetEventHandler()->ProcessEvent( cevent );
376 }
377
378 void wxSlider::Command (wxCommandEvent & event)
379 {
380 SetValue (event.GetInt());
381 ProcessCommand (event);
382 }
383
384 // ----------------------------------------------------------------------------
385 // geometry stuff
386 // ----------------------------------------------------------------------------
387
388 wxRect wxSlider::GetBoundingBox() const
389 {
390 // take care not to call our own functions which would call us recursively
391 int x, y, w, h;
392 wxSliderBase::DoGetPosition(&x, &y);
393 wxSliderBase::DoGetSize(&w, &h);
394
395 wxRect rect(x, y, w, h);
396 if ( m_labels )
397 {
398 wxRect lrect = m_labels->GetBoundingBox();
399 GetParent()->ScreenToClient(&lrect.x, &lrect.y);
400 rect.Union(lrect);
401 }
402
403 return rect;
404 }
405
406 void wxSlider::DoGetSize(int *width, int *height) const
407 {
408 wxRect rect = GetBoundingBox();
409
410 if ( width )
411 *width = rect.width;
412 if ( height )
413 *height = rect.height;
414 }
415
416 void wxSlider::DoGetPosition(int *x, int *y) const
417 {
418 wxRect rect = GetBoundingBox();
419
420 if ( x )
421 *x = rect.x;
422 if ( y )
423 *y = rect.y;
424 }
425
426 int wxSlider::GetLabelsSize(int *width) const
427 {
428 int cy;
429
430 if ( width )
431 {
432 // find the max label width
433 int wLabelMin, wLabelMax;
434 GetTextExtent(Format(m_rangeMin), &wLabelMin, &cy);
435 GetTextExtent(Format(m_rangeMax), &wLabelMax, &cy);
436
437 *width = wxMax(wLabelMin, wLabelMax);
438 }
439 else
440 {
441 cy = GetCharHeight();
442 }
443
444 return EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
445 }
446
447 void wxSlider::DoMoveWindow(int x, int y, int width, int height)
448 {
449 // all complications below are because we need to position the labels,
450 // without them everything is easy
451 if ( !m_labels )
452 {
453 wxSliderBase::DoMoveWindow(x, y, width, height);
454 return;
455 }
456
457 // be careful to position the slider itself after moving the labels as
458 // otherwise our GetBoundingBox(), which is called from WM_SIZE handler,
459 // would return a wrong result and wrong size would be cached internally
460 if ( HasFlag(wxSL_VERTICAL) )
461 {
462 int wLabel;
463 int hLabel = GetLabelsSize(&wLabel);
464
465 int xLabel = HasFlag(wxSL_LEFT) ? x + width - wLabel : x;
466
467 // position all labels: min at the top, value in the middle and max at
468 // the bottom
469 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
470 xLabel, y, wLabel, hLabel);
471
472 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
473 xLabel, y + (height - hLabel)/2, wLabel, hLabel);
474
475 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
476 xLabel, y + height - hLabel, wLabel, hLabel);
477
478 // position the slider itself along the left/right edge
479 wxSliderBase::DoMoveWindow(HasFlag(wxSL_LEFT) ? x : x + wLabel + HGAP,
480 y + hLabel/2,
481 width - wLabel - HGAP,
482 height - hLabel);
483 }
484 else // horizontal
485 {
486 int wLabel;
487 int hLabel = GetLabelsSize(&wLabel);
488
489 int yLabel = HasFlag(wxSL_TOP) ? y + height - hLabel : y;
490
491 // position all labels: min on the left, value in the middle and max to
492 // the right
493 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Min],
494 x, yLabel, wLabel, hLabel);
495
496 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Value],
497 x + (width - wLabel)/2, yLabel, wLabel, hLabel);
498
499 DoMoveSibling((HWND)(*m_labels)[SliderLabel_Max],
500 x + width - wLabel, yLabel, wLabel, hLabel);
501
502 // position the slider itself along the top/bottom edge
503 wxSliderBase::DoMoveWindow(x,
504 HasFlag(wxSL_TOP) ? y : y + hLabel,
505 width,
506 height - hLabel);
507 }
508 }
509
510 wxSize wxSlider::DoGetBestSize() const
511 {
512 // these values are arbitrary
513 static const int length = 100;
514 static const int thumb = 24;
515 static const int ticks = 8;
516
517 int *width;
518 wxSize size;
519 if ( HasFlag(wxSL_VERTICAL) )
520 {
521 size.x = thumb;
522 size.y = length;
523 width = &size.x;
524
525 if ( m_labels )
526 {
527 int wLabel;
528 int hLabel = GetLabelsSize(&wLabel);
529
530 // account for the labels
531 size.x += HGAP + wLabel;
532
533 // labels are indented relative to the slider itself
534 size.y += hLabel;
535 }
536 }
537 else // horizontal
538 {
539 size.x = length;
540 size.y = thumb;
541 width = &size.y;
542
543 if ( m_labels )
544 {
545 // labels add extra height
546 size.y += GetLabelsSize();
547 }
548 }
549
550 // need extra space to show ticks
551 if ( HasFlag(wxSL_TICKS) )
552 {
553 *width += ticks;
554
555 // and maybe twice as much if we show them on both sides
556 if ( HasFlag(wxSL_BOTH) )
557 *width += ticks;
558 }
559
560 return size;
561 }
562
563 // ----------------------------------------------------------------------------
564 // slider-specific methods
565 // ----------------------------------------------------------------------------
566
567 int wxSlider::GetValue() const
568 {
569 return ValueInvertOrNot(::SendMessage(GetHwnd(), TBM_GETPOS, 0, 0));
570 }
571
572 void wxSlider::SetValue(int value)
573 {
574 ::SendMessage(GetHwnd(), TBM_SETPOS, (WPARAM)TRUE, (LPARAM)ValueInvertOrNot(value));
575
576 if ( m_labels )
577 {
578 ::SetWindowText((*m_labels)[SliderLabel_Value], Format(value));
579 }
580 }
581
582 void wxSlider::SetRange(int minValue, int maxValue)
583 {
584 m_rangeMin = minValue;
585 m_rangeMax = maxValue;
586
587 ::SendMessage(GetHwnd(), TBM_SETRANGEMIN, TRUE, m_rangeMin);
588 ::SendMessage(GetHwnd(), TBM_SETRANGEMAX, TRUE, m_rangeMax);
589
590 if ( m_labels )
591 {
592 ::SetWindowText((*m_labels)[SliderLabel_Min], Format(ValueInvertOrNot(m_rangeMin)));
593 ::SetWindowText((*m_labels)[SliderLabel_Max], Format(ValueInvertOrNot(m_rangeMax)));
594 }
595 }
596
597 void wxSlider::SetTickFreq(int n, int pos)
598 {
599 m_tickFreq = n;
600 ::SendMessage( GetHwnd(), TBM_SETTICFREQ, (WPARAM) n, (LPARAM) pos );
601 }
602
603 void wxSlider::SetPageSize(int pageSize)
604 {
605 ::SendMessage( GetHwnd(), TBM_SETPAGESIZE, (WPARAM) 0, (LPARAM) pageSize );
606 m_pageSize = pageSize;
607 }
608
609 int wxSlider::GetPageSize() const
610 {
611 return m_pageSize;
612 }
613
614 void wxSlider::ClearSel()
615 {
616 ::SendMessage(GetHwnd(), TBM_CLEARSEL, (WPARAM) TRUE, (LPARAM) 0);
617 }
618
619 void wxSlider::ClearTicks()
620 {
621 ::SendMessage(GetHwnd(), TBM_CLEARTICS, (WPARAM) TRUE, (LPARAM) 0);
622 }
623
624 void wxSlider::SetLineSize(int lineSize)
625 {
626 m_lineSize = lineSize;
627 ::SendMessage(GetHwnd(), TBM_SETLINESIZE, (WPARAM) 0, (LPARAM) lineSize);
628 }
629
630 int wxSlider::GetLineSize() const
631 {
632 return (int)::SendMessage(GetHwnd(), TBM_GETLINESIZE, 0, 0);
633 }
634
635 int wxSlider::GetSelEnd() const
636 {
637 return (int)::SendMessage(GetHwnd(), TBM_GETSELEND, 0, 0);
638 }
639
640 int wxSlider::GetSelStart() const
641 {
642 return (int)::SendMessage(GetHwnd(), TBM_GETSELSTART, 0, 0);
643 }
644
645 void wxSlider::SetSelection(int minPos, int maxPos)
646 {
647 ::SendMessage(GetHwnd(), TBM_SETSEL,
648 (WPARAM) TRUE /* redraw */,
649 (LPARAM) MAKELONG( minPos, maxPos) );
650 }
651
652 void wxSlider::SetThumbLength(int len)
653 {
654 ::SendMessage(GetHwnd(), TBM_SETTHUMBLENGTH, (WPARAM) len, (LPARAM) 0);
655 }
656
657 int wxSlider::GetThumbLength() const
658 {
659 return (int)::SendMessage( GetHwnd(), TBM_GETTHUMBLENGTH, 0, 0);
660 }
661
662 void wxSlider::SetTick(int tickPos)
663 {
664 ::SendMessage( GetHwnd(), TBM_SETTIC, (WPARAM) 0, (LPARAM) tickPos );
665 }
666
667 // ----------------------------------------------------------------------------
668 // composite control methods
669 // ----------------------------------------------------------------------------
670
671 WXHWND wxSlider::GetStaticMin() const
672 {
673 return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Min] : NULL;
674 }
675
676 WXHWND wxSlider::GetStaticMax() const
677 {
678 return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Max] : NULL;
679 }
680
681 WXHWND wxSlider::GetEditValue() const
682 {
683 return m_labels ? (WXHWND)(*m_labels)[SliderLabel_Value] : NULL;
684 }
685
686 WX_FORWARD_STD_METHODS_TO_SUBWINDOWS(wxSlider, wxSliderBase, m_labels)
687
688 #endif // wxUSE_SLIDER