1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/slider95.cpp
3 // Purpose: wxSlider95, using the Win95 trackbar control
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart 1998
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ============================================================================
15 // ============================================================================
17 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
18 #pragma implementation "slider95.h"
21 // ----------------------------------------------------------------------------
23 // ----------------------------------------------------------------------------
25 // For compilers that support precompilation, includes "wx.h".
26 #include "wx/wxprec.h"
38 #include "wx/slider.h"
39 #include "wx/msw/subwin.h"
41 #if !(defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__))
45 // ----------------------------------------------------------------------------
47 // ----------------------------------------------------------------------------
49 // indices of labels in wxSlider95::m_labels
58 // the gap between the slider and the labels, in pixels
59 static const int HGAP
= 5;
61 // ----------------------------------------------------------------------------
63 // ----------------------------------------------------------------------------
65 #if wxUSE_EXTENDED_RTTI
66 WX_DEFINE_FLAGS( wxSliderStyle
)
68 wxBEGIN_FLAGS( wxSliderStyle
)
69 // new style border flags, we put them first to
70 // use them for streaming out
71 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
72 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
73 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
74 wxFLAGS_MEMBER(wxBORDER_RAISED
)
75 wxFLAGS_MEMBER(wxBORDER_STATIC
)
76 wxFLAGS_MEMBER(wxBORDER_NONE
)
78 // old style border flags
79 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
80 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
81 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
82 wxFLAGS_MEMBER(wxRAISED_BORDER
)
83 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
84 wxFLAGS_MEMBER(wxBORDER
)
86 // standard window styles
87 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
88 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
89 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
90 wxFLAGS_MEMBER(wxWANTS_CHARS
)
91 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
92 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
93 wxFLAGS_MEMBER(wxVSCROLL
)
94 wxFLAGS_MEMBER(wxHSCROLL
)
96 wxFLAGS_MEMBER(wxSL_HORIZONTAL
)
97 wxFLAGS_MEMBER(wxSL_VERTICAL
)
98 wxFLAGS_MEMBER(wxSL_AUTOTICKS
)
99 wxFLAGS_MEMBER(wxSL_LABELS
)
100 wxFLAGS_MEMBER(wxSL_LEFT
)
101 wxFLAGS_MEMBER(wxSL_TOP
)
102 wxFLAGS_MEMBER(wxSL_RIGHT
)
103 wxFLAGS_MEMBER(wxSL_BOTTOM
)
104 wxFLAGS_MEMBER(wxSL_BOTH
)
105 wxFLAGS_MEMBER(wxSL_SELRANGE
)
107 wxEND_FLAGS( wxSliderStyle
)
109 IMPLEMENT_DYNAMIC_CLASS_XTI(wxSlider95
, wxControl
,"wx/scrolbar.h")
111 wxBEGIN_PROPERTIES_TABLE(wxSlider95
)
112 wxEVENT_RANGE_PROPERTY( Scroll
, wxEVT_SCROLL_TOP
, wxEVT_SCROLL_ENDSCROLL
, wxScrollEvent
)
113 wxEVENT_PROPERTY( Updated
, wxEVT_COMMAND_SLIDER_UPDATED
, wxCommandEvent
)
115 wxPROPERTY( Value
, int , SetValue
, GetValue
, 0, 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
116 wxPROPERTY( Minimum
, int , SetMin
, GetMin
, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
117 wxPROPERTY( Maximum
, int , SetMax
, GetMax
, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
118 wxPROPERTY( PageSize
, int , SetPageSize
, GetLineSize
, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
119 wxPROPERTY( LineSize
, int , SetLineSize
, GetLineSize
, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
120 wxPROPERTY( ThumbLength
, int , SetThumbLength
, GetThumbLength
, 1 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
121 wxPROPERTY_FLAGS( WindowStyle
, wxSliderStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
122 wxEND_PROPERTIES_TABLE()
124 wxBEGIN_HANDLERS_TABLE(wxSlider95
)
125 wxEND_HANDLERS_TABLE()
127 wxCONSTRUCTOR_8( wxSlider95
, wxWindow
* , Parent
, wxWindowID
, Id
, int , Value
, int , Minimum
, int , Maximum
, wxPoint
, Position
, wxSize
, Size
, long , WindowStyle
)
129 IMPLEMENT_DYNAMIC_CLASS(wxSlider95
, wxControl
)
132 // ============================================================================
133 // wxSlider95 implementation
134 // ============================================================================
136 // ----------------------------------------------------------------------------
138 // ----------------------------------------------------------------------------
140 void wxSlider95::Init()
152 wxSlider95::Create(wxWindow
*parent
,
160 const wxValidator
& validator
,
161 const wxString
& name
)
163 // initialize everything
164 if ( !CreateControl(parent
, id
, pos
, size
, style
, validator
, name
) )
167 // ensure that we have correct values for GetLabelsSize()
168 m_rangeMin
= minValue
;
169 m_rangeMax
= maxValue
;
171 // create the labels first, so that our DoGetBestSize() could take them
174 // note that we could simply create 3 wxStaticTexts here but it could
175 // result in some observable side effects at wx level (e.g. the parent of
176 // wxSlider would have 3 more children than expected) and so we prefer not
177 // to do it like this
178 if ( m_windowStyle
& wxSL_LABELS
)
180 m_labels
= new wxSubwindows(SliderLabel_Last
);
182 HWND hwndParent
= GetHwndOf(parent
);
183 for ( size_t n
= 0; n
< SliderLabel_Last
; n
++ )
185 (*m_labels
)[n
] = ::CreateWindow
189 WS_CHILD
| WS_VISIBLE
| SS_CENTER
,
192 (HMENU
)NewControlId(),
198 m_labels
->SetFont(GetFont());
201 // now create the main control too
202 if ( !MSWCreateControl(TRACKBAR_CLASS
, wxEmptyString
, pos
, size
) )
205 // and initialize everything
206 SetRange(minValue
, maxValue
);
208 SetPageSize((maxValue
- minValue
)/10);
213 WXDWORD
wxSlider95::MSWGetStyle(long style
, WXDWORD
*exstyle
) const
215 WXDWORD msStyle
= wxControl::MSWGetStyle(style
, exstyle
);
217 // TBS_HORZ is 0 anyhow, but do mention it explicitly for clarity
218 msStyle
|= style
& wxSL_VERTICAL
? TBS_VERT
: TBS_HORZ
;
220 if ( style
& wxSL_AUTOTICKS
)
221 msStyle
|= TBS_AUTOTICKS
;
223 // again, TBS_RIGHT is 0 but do include it for clarity
224 if ( style
& wxSL_LEFT
)
226 else if ( style
& wxSL_RIGHT
)
227 msStyle
|= TBS_RIGHT
;
228 else if ( style
& wxSL_TOP
)
230 else if ( style
& wxSL_BOTTOM
)
231 msStyle
|= TBS_BOTTOM
;
232 else if ( style
& wxSL_BOTH
)
234 else if ( !(style
& wxSL_AUTOTICKS
) )
235 msStyle
|= TBS_NOTICKS
;
237 if ( style
& wxSL_SELRANGE
)
238 msStyle
|= TBS_ENABLESELRANGE
;
243 wxSlider95::~wxSlider95()
248 // ----------------------------------------------------------------------------
250 // ----------------------------------------------------------------------------
252 bool wxSlider95::MSWOnScroll(int WXUNUSED(orientation
),
254 WXWORD
WXUNUSED(pos
),
257 wxEventType scrollEvent
;
261 scrollEvent
= wxEVT_SCROLL_TOP
;
265 scrollEvent
= wxEVT_SCROLL_BOTTOM
;
269 scrollEvent
= wxEVT_SCROLL_LINEUP
;
273 scrollEvent
= wxEVT_SCROLL_LINEDOWN
;
277 scrollEvent
= wxEVT_SCROLL_PAGEUP
;
281 scrollEvent
= wxEVT_SCROLL_PAGEDOWN
;
285 scrollEvent
= wxEVT_SCROLL_THUMBTRACK
;
288 case SB_THUMBPOSITION
:
289 scrollEvent
= wxEVT_SCROLL_THUMBRELEASE
;
293 scrollEvent
= wxEVT_SCROLL_ENDSCROLL
;
297 // unknown scroll event?
301 int newPos
= (int) ::SendMessage((HWND
) control
, TBM_GETPOS
, 0, 0);
302 if ( (newPos
< GetMin()) || (newPos
> GetMax()) )
304 // out of range - but we did process it
310 wxScrollEvent
event(scrollEvent
, m_windowId
);
311 event
.SetPosition(newPos
);
312 event
.SetEventObject( this );
313 GetEventHandler()->ProcessEvent(event
);
315 wxCommandEvent
cevent( wxEVT_COMMAND_SLIDER_UPDATED
, GetId() );
316 cevent
.SetInt( newPos
);
317 cevent
.SetEventObject( this );
319 return GetEventHandler()->ProcessEvent( cevent
);
322 void wxSlider95::Command (wxCommandEvent
& event
)
324 SetValue (event
.GetInt());
325 ProcessCommand (event
);
328 // ----------------------------------------------------------------------------
330 // ----------------------------------------------------------------------------
332 wxRect
wxSlider95::GetBoundingBox() const
334 // take care not to call our own functions which would call us recursively
336 wxSliderBase::DoGetPosition(&x
, &y
);
337 wxSliderBase::DoGetSize(&w
, &h
);
339 wxRect
rect(x
, y
, w
, h
);
341 rect
.Union(m_labels
->GetBoundingBox());
346 void wxSlider95::DoGetSize(int *width
, int *height
) const
348 wxRect rect
= GetBoundingBox();
353 *height
= rect
.height
;
356 void wxSlider95::DoGetPosition(int *x
, int *y
) const
358 wxRect rect
= GetBoundingBox();
366 int wxSlider95::GetLabelsSize(int *width
) const
372 // find the max label width
373 int wLabelMin
, wLabelMax
;
374 GetTextExtent(Format(m_rangeMin
), &wLabelMin
, &cy
);
375 GetTextExtent(Format(m_rangeMax
), &wLabelMax
, &cy
);
377 *width
= wxMax(wLabelMin
, wLabelMax
);
381 cy
= GetCharHeight();
384 return EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy
);
387 void wxSlider95::DoMoveWindow(int x
, int y
, int width
, int height
)
389 // all complications below are because we need to position the labels,
390 // without them everything is easy
393 wxSliderBase::DoMoveWindow(x
, y
, width
, height
);
397 if ( HasFlag(wxSL_VERTICAL
) )
400 int hLabel
= GetLabelsSize(&wLabel
);
402 int xLabel
= HasFlag(wxSL_LEFT
) ? x
+ width
- wLabel
: x
;
404 // position the slider itself along the left/right edge
405 ::MoveWindow(GetHwnd(),
406 HasFlag(wxSL_LEFT
) ? x
: x
+ wLabel
+ HGAP
,
408 width
- wLabel
- HGAP
,
412 // position all labels: min at the top, value in the middle and max at
414 ::MoveWindow((*m_labels
)[SliderLabel_Min
],
415 xLabel
, y
, wLabel
, hLabel
, TRUE
);
417 ::MoveWindow((*m_labels
)[SliderLabel_Value
],
418 xLabel
, y
+ (height
- hLabel
)/2, wLabel
, hLabel
, TRUE
);
420 ::MoveWindow((*m_labels
)[SliderLabel_Max
],
421 xLabel
, y
+ height
- hLabel
, wLabel
, hLabel
, TRUE
);
426 int hLabel
= GetLabelsSize(&wLabel
);
428 int yLabel
= HasFlag(wxSL_TOP
) ? y
+ height
- hLabel
: y
;
430 // position the slider itself along the top/bottom edge
431 ::MoveWindow(GetHwnd(),
433 HasFlag(wxSL_TOP
) ? y
: y
+ hLabel
,
438 // position all labels: min on the left, value in the middle and max to
440 ::MoveWindow((*m_labels
)[SliderLabel_Min
],
441 x
, yLabel
, wLabel
, hLabel
, TRUE
);
443 ::MoveWindow((*m_labels
)[SliderLabel_Value
],
444 x
+ (width
- wLabel
)/2, yLabel
, wLabel
, hLabel
, TRUE
);
446 ::MoveWindow((*m_labels
)[SliderLabel_Max
],
447 x
+ width
- wLabel
, yLabel
, wLabel
, hLabel
, TRUE
);
451 wxSize
wxSlider95::DoGetBestSize() const
453 // these values are arbitrary
454 static const int length
= 100;
455 static const int thickness
= 26;
458 if ( HasFlag(wxSL_VERTICAL
) )
466 int hLabel
= GetLabelsSize(&wLabel
);
468 // account for the labels
469 size
.x
+= HGAP
+ wLabel
;
471 // labels are indented relative to the slider itself
482 // labels add extra height
483 size
.y
+= GetLabelsSize();
490 // ----------------------------------------------------------------------------
491 // slider-specific methods
492 // ----------------------------------------------------------------------------
494 int wxSlider95::GetValue() const
496 return ::SendMessage(GetHwnd(), TBM_GETPOS
, 0, 0);
499 void wxSlider95::SetValue(int value
)
501 ::SendMessage(GetHwnd(), TBM_SETPOS
, (WPARAM
)TRUE
, (LPARAM
)value
);
505 ::SetWindowText((*m_labels
)[SliderLabel_Value
], Format(value
));
509 void wxSlider95::SetRange(int minValue
, int maxValue
)
511 m_rangeMin
= minValue
;
512 m_rangeMax
= maxValue
;
514 ::SendMessage(GetHwnd(), TBM_SETRANGE
, TRUE
, MAKELONG(minValue
, maxValue
));
518 ::SetWindowText((*m_labels
)[SliderLabel_Min
], Format(m_rangeMin
));
519 ::SetWindowText((*m_labels
)[SliderLabel_Max
], Format(m_rangeMax
));
523 void wxSlider95::SetTickFreq(int n
, int pos
)
526 ::SendMessage( GetHwnd(), TBM_SETTICFREQ
, (WPARAM
) n
, (LPARAM
) pos
);
529 void wxSlider95::SetPageSize(int pageSize
)
531 ::SendMessage( GetHwnd(), TBM_SETPAGESIZE
, (WPARAM
) 0, (LPARAM
) pageSize
);
532 m_pageSize
= pageSize
;
535 int wxSlider95::GetPageSize() const
540 void wxSlider95::ClearSel()
542 ::SendMessage(GetHwnd(), TBM_CLEARSEL
, (WPARAM
) TRUE
, (LPARAM
) 0);
545 void wxSlider95::ClearTicks()
547 ::SendMessage(GetHwnd(), TBM_CLEARTICS
, (WPARAM
) TRUE
, (LPARAM
) 0);
550 void wxSlider95::SetLineSize(int lineSize
)
552 m_lineSize
= lineSize
;
553 ::SendMessage(GetHwnd(), TBM_SETLINESIZE
, (WPARAM
) 0, (LPARAM
) lineSize
);
556 int wxSlider95::GetLineSize() const
558 return (int)::SendMessage(GetHwnd(), TBM_GETLINESIZE
, 0, 0);
561 int wxSlider95::GetSelEnd() const
563 return (int)::SendMessage(GetHwnd(), TBM_SETSELEND
, 0, 0);
566 int wxSlider95::GetSelStart() const
568 return (int)::SendMessage(GetHwnd(), TBM_GETSELSTART
, 0, 0);
571 void wxSlider95::SetSelection(int minPos
, int maxPos
)
573 ::SendMessage(GetHwnd(), TBM_SETSEL
,
574 (WPARAM
) TRUE
/* redraw */,
575 (LPARAM
) MAKELONG( minPos
, maxPos
) );
578 void wxSlider95::SetThumbLength(int len
)
580 ::SendMessage(GetHwnd(), TBM_SETTHUMBLENGTH
, (WPARAM
) len
, (LPARAM
) 0);
583 int wxSlider95::GetThumbLength() const
585 return (int)::SendMessage( GetHwnd(), TBM_GETTHUMBLENGTH
, 0, 0);
588 void wxSlider95::SetTick(int tickPos
)
590 ::SendMessage( GetHwnd(), TBM_SETTIC
, (WPARAM
) 0, (LPARAM
) tickPos
);
593 // ----------------------------------------------------------------------------
594 // composite control methods
595 // ----------------------------------------------------------------------------
597 WXHWND
wxSlider95::GetStaticMin() const
599 return m_labels
? (WXHWND
)(*m_labels
)[SliderLabel_Min
] : NULL
;
602 WXHWND
wxSlider95::GetStaticMax() const
604 return m_labels
? (WXHWND
)(*m_labels
)[SliderLabel_Max
] : NULL
;
607 WXHWND
wxSlider95::GetEditValue() const
609 return m_labels
? (WXHWND
)(*m_labels
)[SliderLabel_Value
] : NULL
;
612 bool wxSlider95::ContainsHWND(WXHWND hWnd
) const
614 return m_labels
&& m_labels
->HasWindow((HWND
)hWnd
);
617 bool wxSlider95::Show(bool show
)
619 if ( !wxSliderBase::Show(show
) )
623 m_labels
->Show(show
);
628 #endif // wxUSE_SLIDER