1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "slider.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
25 #include "wx/slider.h"
28 #include "wx/msw/private.h"
30 // Can opt to not use track bar under Win95 if you prefer it - set to 0
31 #define USE_TRACK_BAR 1
33 #if defined(__WIN95__) && !defined(__GNUWIN32__)
37 #if !USE_SHARED_LIBRARY
38 IMPLEMENT_DYNAMIC_CLASS(wxSlider
, wxControl
)
40 #if WXWIN_COMPATIBILITY
41 BEGIN_EVENT_TABLE(wxSlider
, wxControl
)
42 EVT_SCROLL(wxSlider::OnScroll
)
49 wxSlider::wxSlider(void)
61 bool wxSlider::Create(wxWindow
*parent
, const wxWindowID id
,
62 const int value
, const int minValue
, const int maxValue
,
64 const wxSize
& size
, const long style
,
65 const wxValidator
& validator
,
69 SetValidator(validator
);
71 if (parent
) parent
->AddChild(this);
72 SetBackgroundColour(parent
->GetDefaultBackgroundColour()) ;
73 SetForegroundColour(parent
->GetDefaultForegroundColour()) ;
80 m_windowStyle
= style
;
84 m_windowId
= (int)NewControlId();
93 #if defined(__WIN95__) && USE_TRACK_BAR
96 if ( m_windowStyle
& wxSL_LABELS
)
98 msStyle
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| SS_CENTER
;
101 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
) ;
103 m_staticValue
= (WXHWND
) CreateWindowEx(exStyle
, "STATIC", NULL
,
105 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
106 wxGetInstance(), NULL
);
108 // Now create min static control
109 sprintf(wxBuffer
, "%d", minValue
);
110 m_staticMin
= (WXHWND
) CreateWindowEx(0, "STATIC", wxBuffer
,
112 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
113 wxGetInstance(), NULL
);
117 if (m_windowStyle
& wxSL_VERTICAL
)
118 msStyle
= TBS_VERT
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
;
120 msStyle
= TBS_HORZ
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
;
122 if ( m_windowStyle
& wxSL_AUTOTICKS
)
123 msStyle
|= TBS_AUTOTICKS
;
125 if ( m_windowStyle
& wxSL_LEFT
)
127 else if ( m_windowStyle
& wxSL_RIGHT
)
128 msStyle
|= TBS_RIGHT
;
129 else if ( m_windowStyle
& wxSL_TOP
)
131 else if ( m_windowStyle
& wxSL_BOTTOM
)
132 msStyle
|= TBS_BOTTOM
;
133 else if ( m_windowStyle
& wxSL_BOTH
)
135 else if ( ! (m_windowStyle
& wxSL_AUTOTICKS
) )
136 msStyle
|= TBS_NOTICKS
;
138 if ( m_windowStyle
& wxSL_SELRANGE
)
139 msStyle
|= TBS_ENABLESELRANGE
;
141 HWND scroll_bar
= CreateWindowEx(MakeExtendedStyle(m_windowStyle
), TRACKBAR_CLASS
, wxBuffer
,
143 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)m_windowId
,
144 wxGetInstance(), NULL
);
146 m_rangeMax
= maxValue
;
147 m_rangeMin
= minValue
;
149 m_pageSize
= (int)((maxValue
-minValue
)/10);
151 ::SendMessage(scroll_bar
, TBM_SETRANGE
, TRUE
, MAKELONG(minValue
, maxValue
));
152 ::SendMessage(scroll_bar
, TBM_SETPOS
, TRUE
, (LPARAM
)value
);
153 ::SendMessage(scroll_bar
, TBM_SETPAGESIZE
, 0, (LPARAM
)m_pageSize
);
155 m_hWnd
= (WXHWND
)scroll_bar
;
157 SubclassWin(GetHWND());
159 if ( m_windowStyle
& wxSL_LABELS
)
161 // Finally, create max value static item
162 sprintf(wxBuffer
, "%d", maxValue
);
163 m_staticMax
= (WXHWND
) CreateWindowEx(0, "STATIC", wxBuffer
,
165 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
166 wxGetInstance(), NULL
);
168 SetFont(parent
->GetFont());
172 // GetFont()->RealizeResource();
173 if (GetFont()->GetResourceHandle())
176 SendMessage((HWND
)m_staticMin
,WM_SETFONT
,
177 (WPARAM
)GetFont()->GetResourceHandle(),0L);
179 SendMessage((HWND
)m_staticMax
,WM_SETFONT
,
180 (WPARAM
)GetFont()->GetResourceHandle(),0L);
182 SendMessage((HWND
)m_staticValue
,WM_SETFONT
,
183 (WPARAM
)GetFont()->GetResourceHandle(),0L);
188 // non-Win95 implementation
190 long msStyle
= WS_CHILD
| WS_VISIBLE
| WS_BORDER
| SS_CENTER
;
193 WXDWORD exStyle
= Determine3DEffects(WS_EX_CLIENTEDGE
, &want3D
) ;
195 m_staticValue
= (WXHWND
) CreateWindowEx(exStyle
, "STATIC", NULL
,
197 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
198 wxGetInstance(), NULL
);
200 // Now create min static control
201 sprintf(wxBuffer
, "%d", minValue
);
202 m_staticMin
= (WXHWND
) CreateWindowEx(0, "STATIC", wxBuffer
,
204 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
205 wxGetInstance(), NULL
);
208 m_windowId
= (int)NewControlId();
211 if (m_windowStyle
& wxSL_VERTICAL
)
212 msStyle
= SBS_VERT
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
;
214 msStyle
= SBS_HORZ
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
;
216 HWND scroll_bar
= CreateWindowEx(MakeExtendedStyle(m_windowStyle
), "SCROLLBAR", wxBuffer
,
218 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)m_windowId
,
219 wxGetInstance(), NULL
);
221 m_pageSize
= (int)((maxValue
-minValue
)/10);
222 m_rangeMax
= maxValue
;
223 m_rangeMin
= minValue
;
225 ::SetScrollRange(scroll_bar
, SB_CTL
, minValue
, maxValue
, FALSE
);
226 ::SetScrollPos(scroll_bar
, SB_CTL
, value
, FALSE
);
227 ShowWindow(scroll_bar
, SW_SHOW
);
229 m_hWnd
= (WXHWND
)scroll_bar
;
231 // Subclass again for purposes of dialog editing mode
232 SubclassWin(GetHWND());
234 // Finally, create max value static item
235 sprintf(wxBuffer
, "%d", maxValue
);
236 m_staticMax
= (WXHWND
) CreateWindowEx(0, "STATIC", wxBuffer
,
238 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)NewControlId(),
239 wxGetInstance(), NULL
);
241 SetFont(* parent
->GetFont());
245 // GetFont()->RealizeResource();
246 if (GetFont()->GetResourceHandle())
249 SendMessage((HWND
)m_staticMin
,WM_SETFONT
,
250 (WPARAM
)GetFont()->GetResourceHandle(),0L);
252 SendMessage((HWND
)m_staticMax
,WM_SETFONT
,
253 (WPARAM
)GetFont()->GetResourceHandle(),0L);
255 SendMessage((HWND
)m_staticValue
,WM_SETFONT
,
256 (WPARAM
)GetFont()->GetResourceHandle(),0L);
261 SetSize(x
, y
, width
, height
);
267 void wxSlider::MSWOnVScroll(const WXWORD wParam
, const WXWORD pos
, const WXHWND control
)
269 #if defined(__WIN95__) && USE_TRACK_BAR
270 int position
= 0; // Dummy - not used in this mode
272 int position
= ::GetScrollPos((HWND
)control
, SB_CTL
);
280 nScrollInc
= m_rangeMax
- position
;
281 scrollEvent
= wxEVT_SCROLL_TOP
;
285 nScrollInc
= - position
;
286 scrollEvent
= wxEVT_SCROLL_BOTTOM
;
290 nScrollInc
= - GetLineSize();
291 scrollEvent
= wxEVT_SCROLL_LINEUP
;
295 nScrollInc
= GetLineSize();
296 scrollEvent
= wxEVT_SCROLL_LINEDOWN
;
300 nScrollInc
= -GetPageSize();
301 scrollEvent
= wxEVT_SCROLL_PAGEUP
;
305 nScrollInc
= GetPageSize();
306 scrollEvent
= wxEVT_SCROLL_PAGEDOWN
;
310 case SB_THUMBPOSITION
:
312 nScrollInc
= (signed short)pos
- position
;
314 nScrollInc
= pos
- position
;
316 scrollEvent
= wxEVT_SCROLL_THUMBTRACK
;
324 #if !(WIN95 && USE_TRACK_BAR)
329 #if defined(__WIN95__) && USE_TRACK_BAR
330 int newPos
= (int)::SendMessage((HWND
) control
, TBM_GETPOS
, 0, 0);
332 int newPos
= position
+ nScrollInc
;
334 if (!(newPos
< GetMin() || newPos
> GetMax()))
338 wxScrollEvent
event(scrollEvent
, m_windowId
);
339 event
.SetPosition(newPos
);
340 event
.SetEventObject( this );
341 GetEventHandler()->ProcessEvent(event
);
346 void wxSlider::MSWOnHScroll(const WXWORD wParam
, const WXWORD pos
, const WXHWND control
)
348 MSWOnVScroll(wParam
, pos
, control
);
351 wxSlider::~wxSlider(void)
354 DestroyWindow((HWND
) m_staticMin
);
356 DestroyWindow((HWND
) m_staticMax
);
358 DestroyWindow((HWND
) m_staticValue
);
361 int wxSlider::GetValue(void) const
363 #if defined(__WIN95__) && USE_TRACK_BAR
364 return ::SendMessage((HWND
) GetHWND(), TBM_GETPOS
, 0, 0);
366 return ::GetScrollPos((HWND
) GetHWND(), SB_CTL
);
370 void wxSlider::SetValue(const int value
)
372 #if defined(__WIN95__) && USE_TRACK_BAR
373 ::SendMessage((HWND
) GetHWND(), TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)value
);
375 ::SetScrollPos((HWND
) GetHWND(), SB_CTL
, value
, TRUE
);
379 sprintf(wxBuffer
, "%d", value
);
380 SetWindowText((HWND
) m_staticValue
, wxBuffer
);
384 void wxSlider::GetSize(int *width
, int *height
) const
387 rect
.left
= -1; rect
.right
= -1; rect
.top
= -1; rect
.bottom
= -1;
389 wxFindMaxSize(GetHWND(), &rect
);
392 wxFindMaxSize(m_staticMin
, &rect
);
394 wxFindMaxSize(m_staticMax
, &rect
);
396 wxFindMaxSize(m_staticValue
, &rect
);
398 *width
= rect
.right
- rect
.left
;
399 *height
= rect
.bottom
- rect
.top
;
402 void wxSlider::GetPosition(int *x
, int *y
) const
404 wxWindow
*parent
= GetParent();
406 rect
.left
= -1; rect
.right
= -1; rect
.top
= -1; rect
.bottom
= -1;
408 wxFindMaxSize(GetHWND(), &rect
);
411 wxFindMaxSize(m_staticMin
, &rect
);
413 wxFindMaxSize(m_staticMax
, &rect
);
415 wxFindMaxSize(m_staticValue
, &rect
);
417 // Since we now have the absolute screen coords,
418 // if there's a parent we must subtract its top left corner
423 ::ScreenToClient((HWND
) parent
->GetHWND(), &point
);
429 void wxSlider::SetSize(const int x
, const int y
, const int width
, const int height
, const int sizeFlags
)
436 int currentX
, currentY
;
437 GetPosition(¤tX
, ¤tY
);
438 if (x
== -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
440 if (y
== -1 || (sizeFlags
& wxSIZE_ALLOW_MINUS_ONE
))
448 int cx
; // slider,min,max sizes
452 wxGetCharSize(GetHWND(), &cx
, &cy
,GetFont());
454 if ((m_windowStyle
& wxSL_VERTICAL
) != wxSL_VERTICAL
)
456 if ( m_windowStyle
& wxSL_LABELS
)
460 GetWindowText((HWND
) m_staticMin
, buf
, 300);
461 GetTextExtent(buf
, &min_len
, &cyf
,NULL
,NULL
, GetFont());
465 GetWindowText((HWND
) m_staticMax
, buf
, 300);
466 GetTextExtent(buf
, &max_len
, &cyf
,NULL
,NULL
, GetFont());
469 int new_width
= (int)(wxMax(min_len
, max_len
));
470 int valueHeight
= (int)cyf
;
472 // For some reason, under Win95, the text edit control has
473 // a lot of space before the first character
476 #if defined(__WIN95__)
477 // The height needs to be a bit bigger under Win95 if using native
479 valueHeight
= (int) (valueHeight
* 1.5) ;
481 MoveWindow((HWND
) m_staticValue
, x_offset
, y_offset
, new_width
, valueHeight
, TRUE
);
482 x_offset
+= new_width
+ cx
;
485 MoveWindow((HWND
) m_staticMin
, x_offset
, y_offset
, (int)min_len
, cy
, TRUE
);
486 x_offset
+= (int)(min_len
+ cx
);
488 int slider_length
= (int)(w1
- x_offset
- max_len
- cx
);
490 #if defined(__WIN95__) && USE_TRACK_BAR
491 int slider_height
= h1
;
492 if (slider_height
< 0 )
495 int slider_height
= cy
;
498 // Slider must have a minimum/default length/height
499 if (slider_length
< 100)
502 MoveWindow((HWND
) GetHWND(), x_offset
, y_offset
, slider_length
, slider_height
, TRUE
);
503 x_offset
+= slider_length
+ cx
;
505 MoveWindow((HWND
) m_staticMax
, x_offset
, y_offset
, (int)max_len
, cy
, TRUE
);
514 MoveWindow((HWND
) GetHWND(), x1
, y1
, w1
, h1
, TRUE
);
519 if ( m_windowStyle
& wxSL_LABELS
)
522 GetWindowText((HWND
) m_staticMin
, buf
, 300);
523 GetTextExtent(buf
, &min_len
, &cyf
,NULL
,NULL
,GetFont());
526 GetWindowText((HWND
) m_staticMax
, buf
, 300);
527 GetTextExtent(buf
, &max_len
, &cyf
,NULL
,NULL
, GetFont());
531 int new_width
= (int)(wxMax(min_len
, max_len
));
532 int valueHeight
= (int)cyf
;
533 /*** Suggested change by George Tasker - remove this block...
535 // For some reason, under Win95, the text edit control has
536 // a lot of space before the first character
539 ... and replace with following line: */
542 #if defined(__WIN95__)
543 // The height needs to be a bit bigger under Win95 if using native
545 valueHeight
= (int) (valueHeight
* 1.5) ;
548 MoveWindow((HWND
) m_staticValue
, x_offset
, y_offset
, new_width
, valueHeight
, TRUE
);
549 y_offset
+= valueHeight
;
552 MoveWindow((HWND
) m_staticMin
, x_offset
, y_offset
, (int)min_len
, cy
, TRUE
);
555 int slider_length
= (int)(h1
- y_offset
- cy
- cy
);
556 #if defined(__WIN95__) && USE_TRACK_BAR
557 int slider_width
= w1
;
558 if (slider_width
< 0 )
561 // Use character height as an estimate of slider width (yes, width)
562 int slider_width
= cy
;
565 // Slider must have a minimum/default length
566 if (slider_length
< 100)
569 MoveWindow((HWND
) GetHWND(), x_offset
, y_offset
, slider_width
, slider_length
, TRUE
);
570 y_offset
+= slider_length
;
572 MoveWindow((HWND
) m_staticMax
, x_offset
, y_offset
, (int)max_len
, cy
, TRUE
);
581 MoveWindow((HWND
) GetHWND(), x1
, y1
, w1
, h1
, TRUE
);
586 #if WXWIN_COMPATIBILITY
587 GetEventHandler()->OldOnSize(width, height);
589 wxSizeEvent event(wxSize(width, height), m_windowId);
590 event.eventObject = this;
591 GetEventHandler()->ProcessEvent(event);
597 void wxSlider::SetRange(const int minValue
, const int maxValue
)
599 m_rangeMin
= minValue
;
600 m_rangeMax
= maxValue
;
602 #if defined(__WIN95__) && USE_TRACK_BAR
603 ::SendMessage((HWND
) GetHWND(), TBM_SETRANGE
, TRUE
, MAKELONG(minValue
, maxValue
));
605 ::SetScrollRange((HWND
) GetHWND(), SB_CTL
, m_rangeMin
, m_rangeMax
, TRUE
);
610 sprintf(buf
, "%d", m_rangeMin
);
611 SetWindowText((HWND
) m_staticMin
, buf
);
616 sprintf(buf
, "%d", m_rangeMax
);
617 SetWindowText((HWND
) m_staticMax
, buf
);
621 WXHBRUSH
wxSlider::OnCtlColor(const WXHDC pDC
, const WXHWND pWnd
, const WXUINT nCtlColor
,
622 WXUINT message
, WXWPARAM wParam
, WXLPARAM lParam
)
624 if ( nCtlColor
== CTLCOLOR_SCROLLBAR
)
627 // Otherwise, it's a static
628 if (GetParent()->GetTransparentBackground())
629 SetBkMode((HDC
) pDC
, TRANSPARENT
);
631 SetBkMode((HDC
) pDC
, OPAQUE
);
633 ::SetBkColor((HDC
) pDC
, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue()));
634 ::SetTextColor((HDC
) pDC
, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue()));
636 wxBrush
*backgroundBrush
= wxTheBrushList
->FindOrCreateBrush(GetBackgroundColour(), wxSOLID
);
638 // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush
639 // has a zero usage count.
640 // backgroundBrush->RealizeResource();
641 return (WXHBRUSH
) backgroundBrush
->GetResourceHandle();
644 // For trackbars only
645 void wxSlider::SetTickFreq(const int n
, const int pos
)
647 #if defined(__WIN95__) && USE_TRACK_BAR
649 ::SendMessage( (HWND
) GetHWND(), TBM_SETTICFREQ
, (WPARAM
) n
, (LPARAM
) pos
);
653 void wxSlider::SetPageSize(const int pageSize
)
655 #if defined(__WIN95__) && USE_TRACK_BAR
656 ::SendMessage( (HWND
) GetHWND(), TBM_SETPAGESIZE
, (WPARAM
) 0, (LPARAM
) pageSize
);
658 m_pageSize
= pageSize
;
661 int wxSlider::GetPageSize(void) const
666 void wxSlider::ClearSel(void)
668 #if defined(__WIN95__) && USE_TRACK_BAR
669 ::SendMessage( (HWND
) GetHWND(), TBM_CLEARSEL
, (WPARAM
) TRUE
, (LPARAM
) 0 );
673 void wxSlider::ClearTicks(void)
675 #if defined(__WIN95__) && USE_TRACK_BAR
676 ::SendMessage( (HWND
) GetHWND(), TBM_CLEARTICS
, (WPARAM
) TRUE
, (LPARAM
) 0 );
680 void wxSlider::SetLineSize(const int lineSize
)
682 m_lineSize
= lineSize
;
683 #if defined(__WIN95__) && USE_TRACK_BAR
684 ::SendMessage( (HWND
) GetHWND(), TBM_SETLINESIZE
, (WPARAM
) 0, (LPARAM
) lineSize
);
688 int wxSlider::GetLineSize(void) const
690 #if defined(__WIN95__) && USE_TRACK_BAR
691 return (int) ::SendMessage( (HWND
) GetHWND(), TBM_GETLINESIZE
, (WPARAM
) 0, (LPARAM
) 0 );
697 int wxSlider::GetSelEnd(void) const
699 #if defined(__WIN95__) && USE_TRACK_BAR
700 return (int) ::SendMessage( (HWND
) GetHWND(), TBM_SETSELEND
, (WPARAM
) 0, (LPARAM
) 0 );
706 int wxSlider::GetSelStart(void) const
708 #if defined(__WIN95__) && USE_TRACK_BAR
709 return (int) ::SendMessage( (HWND
) GetHWND(), TBM_GETSELSTART
, (WPARAM
) 0, (LPARAM
) 0 );
715 void wxSlider::SetSelection(const int minPos
, const int maxPos
)
717 #if defined(__WIN95__) && USE_TRACK_BAR
718 ::SendMessage( (HWND
) GetHWND(), TBM_SETSEL
, (WPARAM
) TRUE
, (LPARAM
) MAKELONG( minPos
, maxPos
) );
722 void wxSlider::SetThumbLength(const int len
)
724 #if defined(__WIN95__) && USE_TRACK_BAR
725 ::SendMessage( (HWND
) GetHWND(), TBM_SETTHUMBLENGTH
, (WPARAM
) len
, (LPARAM
) 0 );
729 int wxSlider::GetThumbLength(void) const
731 #if defined(__WIN95__) && USE_TRACK_BAR
732 return (int) ::SendMessage( (HWND
) GetHWND(), TBM_GETTHUMBLENGTH
, (WPARAM
) 0, (LPARAM
) 0 );
738 void wxSlider::SetTick(const int tickPos
)
740 #if defined(__WIN95__) && USE_TRACK_BAR
741 ::SendMessage( (HWND
) GetHWND(), TBM_SETTIC
, (WPARAM
) 0, (LPARAM
) tickPos
);
745 bool wxSlider::ContainsHWND(WXHWND hWnd
) const
747 return ( hWnd
== GetStaticMin() || hWnd
== GetStaticMax() || hWnd
== GetEditValue() );
750 #if WXWIN_COMPATIBILITY
751 // Backward compatibility
752 void wxSlider::OnScroll(wxScrollEvent
& event
)
754 int oldEvent
= event
.GetEventType();
755 event
.SetEventType( wxEVT_COMMAND_SLIDER_UPDATED
);
756 if ( !GetEventHandler()->ProcessEvent(event
) )
758 event
.SetEventType( oldEvent
);
759 if (!GetParent()->GetEventHandler()->ProcessEvent(event
))
765 void wxSlider::Command (wxCommandEvent
& event
)
767 SetValue (event
.GetInt());
768 ProcessCommand (event
);
771 bool wxSlider::Show(const bool show
)
773 wxWindow::Show(show
);
782 ShowWindow((HWND
) m_staticValue
, (BOOL
)cshow
);
784 ShowWindow((HWND
) m_staticMin
, (BOOL
)cshow
);
786 ShowWindow((HWND
) m_staticMax
, (BOOL
)cshow
);