1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/scrolbar.cpp
3 // Purpose: wxScrollBar
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "scrolbar.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
29 #include "wx/scrolbar.h"
30 #include "wx/msw/private.h"
32 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar
, wxControl
)
42 BEGIN_EVENT_TABLE(wxScrollBar
, wxControl
)
43 #if WXWIN_COMPATIBILITY
44 EVT_SCROLL(wxScrollBar::OnScroll
)
50 bool wxScrollBar::Create(wxWindow
*parent
, wxWindowID id
,
52 const wxSize
& size
, long style
,
53 const wxValidator
& validator
,
58 parent
->AddChild(this);
61 SetValidator(validator
);
62 #endif // wxUSE_VALIDATORS
64 if ((style
& wxBORDER_MASK
) == wxBORDER_DEFAULT
)
67 SetBackgroundColour(parent
->GetBackgroundColour()) ;
68 SetForegroundColour(parent
->GetForegroundColour()) ;
69 m_windowStyle
= style
;
72 m_windowId
= (int)NewControlId();
83 if (style
& wxHORIZONTAL
)
90 if (style
& wxVERTICAL
)
97 WXDWORD wstyle
= MSWGetStyle(style
, & exStyle
) ;
99 // Now create scrollbar
100 DWORD _direction
= (style
& wxHORIZONTAL
) ?
102 HWND scroll_bar
= CreateWindowEx(exStyle
, wxT("SCROLLBAR"), wxT("scrollbar"),
104 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)m_windowId
,
105 wxGetInstance(), NULL
);
111 ::SetScrollRange(scroll_bar
, SB_CTL
, 0, 1, FALSE
);
112 ::SetScrollPos(scroll_bar
, SB_CTL
, 0, FALSE
);
113 ShowWindow(scroll_bar
, SW_SHOW
);
115 SetFont(parent
->GetFont());
117 m_hWnd
= (WXHWND
)scroll_bar
;
119 // Subclass again for purposes of dialog editing mode
120 SubclassWin((WXHWND
) scroll_bar
);
122 SetSize(x
, y
, width
, height
);
127 wxScrollBar::~wxScrollBar(void)
131 bool wxScrollBar::MSWOnScroll(int WXUNUSED(orientation
), WXWORD wParam
,
132 WXWORD pos
, WXHWND
WXUNUSED(control
))
134 // current and max positions
136 maxPos
, trackPos
= pos
;
138 // when we're dragging the scrollbar we can't use pos parameter because it
139 // is limited to 16 bits
140 // JACS: now always using GetScrollInfo, since there's no reason
142 // if ( wParam == SB_THUMBPOSITION || wParam == SB_THUMBTRACK )
144 SCROLLINFO scrollInfo
;
145 wxZeroMemory(scrollInfo
);
146 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
148 // also get the range if we call GetScrollInfo() anyhow -- this is less
149 // expensive than call it once here and then call GetScrollRange()
151 scrollInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_TRACKPOS
;
153 if ( !::GetScrollInfo(GetHwnd(), SB_CTL
, &scrollInfo
) )
155 wxLogLastError(_T("GetScrollInfo"));
158 trackPos
= scrollInfo
.nTrackPos
;
159 position
= scrollInfo
.nPos
;
160 maxPos
= scrollInfo
.nMax
;
165 position
= ::GetScrollPos((HWND
) control
, SB_CTL
);
167 ::GetScrollRange((HWND
) control
, SB_CTL
, &minPos
, &maxPos
);
171 #if defined(__WIN95__)
172 // A page size greater than one has the effect of reducing the effective
173 // range, therefore the range has already been boosted artificially - so
175 if ( m_pageSize
> 1 )
176 maxPos
-= (m_pageSize
- 1);
179 wxEventType scrollEvent
= wxEVT_NULL
;
185 nScrollInc
= maxPos
- position
;
186 scrollEvent
= wxEVT_SCROLL_TOP
;
190 nScrollInc
= -position
;
191 scrollEvent
= wxEVT_SCROLL_BOTTOM
;
196 scrollEvent
= wxEVT_SCROLL_LINEUP
;
201 scrollEvent
= wxEVT_SCROLL_LINEDOWN
;
205 nScrollInc
= -GetPageSize();
206 scrollEvent
= wxEVT_SCROLL_PAGEUP
;
210 nScrollInc
= GetPageSize();
211 scrollEvent
= wxEVT_SCROLL_PAGEDOWN
;
214 case SB_THUMBPOSITION
:
215 nScrollInc
= trackPos
- position
;
216 scrollEvent
= wxEVT_SCROLL_THUMBRELEASE
;
220 nScrollInc
= trackPos
- position
;
221 scrollEvent
= wxEVT_SCROLL_THUMBTRACK
;
226 scrollEvent
= wxEVT_SCROLL_ENDSCROLL
;
235 position
+= nScrollInc
;
239 if ( position
> maxPos
)
242 SetThumbPosition(position
);
244 else if ( scrollEvent
!= wxEVT_SCROLL_THUMBRELEASE
&&
245 scrollEvent
!= wxEVT_SCROLL_ENDSCROLL
)
247 // don't process the event if there is no displacement,
248 // unless this is a thumb release or end scroll event.
252 wxScrollEvent
event(scrollEvent
, m_windowId
);
253 event
.SetOrientation(IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
254 event
.SetPosition(position
);
255 event
.SetEventObject( this );
257 return GetEventHandler()->ProcessEvent(event
);
260 void wxScrollBar::SetThumbPosition(int viewStart
)
262 #if defined(__WIN95__)
264 info
.cbSize
= sizeof(SCROLLINFO
);
267 info
.nPos
= viewStart
;
268 info
.fMask
= SIF_POS
;
270 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
272 ::SetScrollPos((HWND
) GetHWND(), SB_CTL
, viewStart
, TRUE
);
276 int wxScrollBar::GetThumbPosition(void) const
278 SCROLLINFO scrollInfo
;
279 wxZeroMemory(scrollInfo
);
280 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
281 scrollInfo
.fMask
= SIF_POS
;
283 if ( !::GetScrollInfo(GetHwnd(), SB_CTL
, &scrollInfo
) )
285 wxLogLastError(_T("GetScrollInfo"));
287 return scrollInfo
.nPos
;
288 // return ::GetScrollPos((HWND)m_hWnd, SB_CTL);
291 void wxScrollBar::SetScrollbar(int position
, int thumbSize
, int range
, int pageSize
,
294 m_viewSize
= pageSize
;
295 m_pageSize
= thumbSize
;
296 m_objectSize
= range
;
298 // The range (number of scroll steps) is the
299 // object length minus the page size.
300 int range1
= wxMax((m_objectSize
- m_pageSize
), 0) ;
302 #if defined(__WIN95__)
303 // Try to adjust the range to cope with page size > 1
304 // (see comment for SetPageLength)
305 if ( m_pageSize
> 1 )
307 range1
+= (m_pageSize
- 1);
311 info
.cbSize
= sizeof(SCROLLINFO
);
312 info
.nPage
= m_pageSize
;
315 info
.nPos
= position
;
317 info
.fMask
= SIF_PAGE
| SIF_RANGE
| SIF_POS
;
319 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, refresh
);
321 ::SetScrollPos((HWND
)m_hWnd
, SB_CTL
, position
, TRUE
);
322 ::SetScrollRange((HWND
)m_hWnd
, SB_CTL
, 0, range1
, TRUE
);
327 /* From the WIN32 documentation:
328 In version 4.0 or later, the maximum value that a scroll bar can report
329 (that is, the maximum scrolling position) depends on the page size.
330 If the scroll bar has a page size greater than one, the maximum scrolling position
331 is less than the maximum range value. You can use the following formula to calculate
332 the maximum scrolling position:
334 MaxScrollPos = MaxRangeValue - (PageSize - 1)
337 #if WXWIN_COMPATIBILITY
338 void wxScrollBar::SetPageSize(int pageLength
)
340 m_pageSize
= pageLength
;
342 #if defined(__WIN95__)
344 info
.cbSize
= sizeof(SCROLLINFO
);
345 info
.nPage
= pageLength
;
346 info
.fMask
= SIF_PAGE
;
348 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
352 void wxScrollBar::SetObjectLength(int objectLength
)
354 m_objectSize
= objectLength
;
356 // The range (number of scroll steps) is the
357 // object length minus the view size.
358 int range
= wxMax((objectLength
- m_viewSize
), 0) ;
360 #if defined(__WIN95__)
361 // Try to adjust the range to cope with page size > 1
362 // (see comment for SetPageLength)
363 if ( m_pageSize
> 1 )
365 range
+= (m_pageSize
- 1);
369 info
.cbSize
= sizeof(SCROLLINFO
);
374 info
.fMask
= SIF_RANGE
;
376 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
378 ::SetScrollRange((HWND
)m_hWnd
, SB_CTL
, 0, range
, TRUE
);
382 void wxScrollBar::SetViewLength(int viewLength
)
384 m_viewSize
= viewLength
;
387 void wxScrollBar::GetValues(int *viewStart
, int *viewLength
, int *objectLength
,
388 int *pageLength
) const
390 *viewStart
= ::GetScrollPos((HWND
)m_hWnd
, SB_CTL
);
391 *viewLength
= m_viewSize
;
392 *objectLength
= m_objectSize
;
393 *pageLength
= m_pageSize
;
397 WXHBRUSH
wxScrollBar::OnCtlColor(WXHDC
WXUNUSED(pDC
), WXHWND
WXUNUSED(pWnd
), WXUINT
WXUNUSED(nCtlColor
),
398 WXUINT
WXUNUSED(message
), WXWPARAM
WXUNUSED(wParam
), WXLPARAM
WXUNUSED(lParam
))
403 void wxScrollBar::Command(wxCommandEvent
& event
)
405 SetThumbPosition(event
.m_commandInt
);
406 ProcessCommand(event
);
409 #if WXWIN_COMPATIBILITY
410 // Backward compatibility
411 void wxScrollBar::OnScroll(wxScrollEvent
& event
)
413 wxEventType oldEvent
= event
.GetEventType();
414 event
.SetEventType( wxEVT_COMMAND_SCROLLBAR_UPDATED
);
415 if ( !GetEventHandler()->ProcessEvent(event
) )
417 event
.SetEventType( oldEvent
);
418 if (!GetParent()->GetEventHandler()->ProcessEvent(event
))
424 #endif // wxUSE_SCROLLBAR