1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/scrolbar.cpp
3 // Purpose: wxScrollBar
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
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
)
34 BEGIN_EVENT_TABLE(wxScrollBar
, wxControl
)
35 #if WXWIN_COMPATIBILITY
36 EVT_SCROLL(wxScrollBar::OnScroll
)
42 bool wxScrollBar::Create(wxWindow
*parent
, wxWindowID id
,
44 const wxSize
& size
, long style
,
45 const wxValidator
& validator
,
50 parent
->AddChild(this);
53 SetValidator(validator
);
54 #endif // wxUSE_VALIDATORS
56 SetBackgroundColour(parent
->GetBackgroundColour()) ;
57 SetForegroundColour(parent
->GetForegroundColour()) ;
58 m_windowStyle
= style
;
61 m_windowId
= (int)NewControlId();
72 if (style
& wxHORIZONTAL
)
79 if (style
& wxVERTICAL
)
85 DWORD wstyle
= WS_VISIBLE
| WS_CHILD
;
87 if ( m_windowStyle
& wxCLIP_SIBLINGS
)
88 wstyle
|= WS_CLIPSIBLINGS
;
90 // Now create scrollbar
91 DWORD _direction
= (style
& wxHORIZONTAL
) ?
93 HWND scroll_bar
= CreateWindowEx(MakeExtendedStyle(style
), wxT("SCROLLBAR"), wxT("scrollbar"),
95 0, 0, 0, 0, (HWND
) parent
->GetHWND(), (HMENU
)m_windowId
,
96 wxGetInstance(), NULL
);
102 ::SetScrollRange(scroll_bar
, SB_CTL
, 0, 1, FALSE
);
103 ::SetScrollPos(scroll_bar
, SB_CTL
, 0, FALSE
);
104 ShowWindow(scroll_bar
, SW_SHOW
);
106 SetFont(parent
->GetFont());
108 m_hWnd
= (WXHWND
)scroll_bar
;
110 // Subclass again for purposes of dialog editing mode
111 SubclassWin((WXHWND
) scroll_bar
);
113 SetSize(x
, y
, width
, height
);
118 wxScrollBar::~wxScrollBar(void)
122 bool wxScrollBar::MSWOnScroll(int WXUNUSED(orientation
), WXWORD wParam
,
123 WXWORD pos
, WXHWND control
)
125 // current and max positions
127 maxPos
, trackPos
= pos
;
130 // when we're dragging the scrollbar we can't use pos parameter because it
131 // is limited to 16 bits
132 if ( wParam
== SB_THUMBPOSITION
|| wParam
== SB_THUMBTRACK
)
134 SCROLLINFO scrollInfo
;
135 wxZeroMemory(scrollInfo
);
136 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
138 // also get the range if we call GetScrollInfo() anyhow -- this is less
139 // expensive than call it once here and then call GetScrollRange()
141 scrollInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_TRACKPOS
;
143 if ( !::GetScrollInfo(GetHwnd(), SB_CTL
, &scrollInfo
) )
145 wxLogLastError(_T("GetScrollInfo"));
148 trackPos
= scrollInfo
.nTrackPos
;
149 position
= scrollInfo
.nPos
;
150 maxPos
= scrollInfo
.nMax
;
155 position
= ::GetScrollPos((HWND
) control
, SB_CTL
);
157 ::GetScrollRange((HWND
) control
, SB_CTL
, &minPos
, &maxPos
);
160 #if defined(__WIN95__)
161 // A page size greater than one has the effect of reducing the effective
162 // range, therefore the range has already been boosted artificially - so
164 if ( m_pageSize
> 1 )
165 maxPos
-= (m_pageSize
- 1);
168 wxEventType scrollEvent
= wxEVT_NULL
;
174 nScrollInc
= maxPos
- position
;
175 scrollEvent
= wxEVT_SCROLL_TOP
;
179 nScrollInc
= -position
;
180 scrollEvent
= wxEVT_SCROLL_BOTTOM
;
185 scrollEvent
= wxEVT_SCROLL_LINEUP
;
190 scrollEvent
= wxEVT_SCROLL_LINEDOWN
;
194 nScrollInc
= -GetPageSize();
195 scrollEvent
= wxEVT_SCROLL_PAGEUP
;
199 nScrollInc
= GetPageSize();
200 scrollEvent
= wxEVT_SCROLL_PAGEDOWN
;
203 case SB_THUMBPOSITION
:
204 nScrollInc
= trackPos
- position
;
205 scrollEvent
= wxEVT_SCROLL_THUMBRELEASE
;
209 nScrollInc
= trackPos
- position
;
210 scrollEvent
= wxEVT_SCROLL_THUMBTRACK
;
215 scrollEvent
= wxEVT_SCROLL_ENDSCROLL
;
224 position
+= nScrollInc
;
228 if ( position
> maxPos
)
231 SetThumbPosition(position
);
233 else if ( scrollEvent
!= wxEVT_SCROLL_THUMBRELEASE
&&
234 scrollEvent
!= wxEVT_SCROLL_ENDSCROLL
)
236 // don't process the event if there is no displacement,
237 // unless this is a thumb release or end scroll event.
241 wxScrollEvent
event(scrollEvent
, m_windowId
);
242 event
.SetOrientation(IsVertical() ? wxVERTICAL
: wxHORIZONTAL
);
243 event
.SetPosition(position
);
244 event
.SetEventObject( this );
246 return GetEventHandler()->ProcessEvent(event
);
249 void wxScrollBar::SetThumbPosition(int viewStart
)
251 #if defined(__WIN95__)
253 info
.cbSize
= sizeof(SCROLLINFO
);
256 info
.nPos
= viewStart
;
257 info
.fMask
= SIF_POS
;
259 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
261 ::SetScrollPos((HWND
) GetHWND(), SB_CTL
, viewStart
, TRUE
);
265 int wxScrollBar::GetThumbPosition(void) const
267 return ::GetScrollPos((HWND
)m_hWnd
, SB_CTL
);
270 void wxScrollBar::SetScrollbar(int position
, int thumbSize
, int range
, int pageSize
,
273 m_viewSize
= pageSize
;
274 m_pageSize
= thumbSize
;
275 m_objectSize
= range
;
277 // The range (number of scroll steps) is the
278 // object length minus the page size.
279 int range1
= wxMax((m_objectSize
- m_pageSize
), 0) ;
281 #if defined(__WIN95__)
282 // Try to adjust the range to cope with page size > 1
283 // (see comment for SetPageLength)
284 if ( m_pageSize
> 1 )
286 range1
+= (m_pageSize
- 1);
290 info
.cbSize
= sizeof(SCROLLINFO
);
291 info
.nPage
= m_pageSize
;
294 info
.nPos
= position
;
296 info
.fMask
= SIF_PAGE
| SIF_RANGE
| SIF_POS
;
298 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, refresh
);
300 ::SetScrollPos((HWND
)m_hWnd
, SB_CTL
, position
, TRUE
);
301 ::SetScrollRange((HWND
)m_hWnd
, SB_CTL
, 0, range1
, TRUE
);
306 /* From the WIN32 documentation:
307 In version 4.0 or later, the maximum value that a scroll bar can report
308 (that is, the maximum scrolling position) depends on the page size.
309 If the scroll bar has a page size greater than one, the maximum scrolling position
310 is less than the maximum range value. You can use the following formula to calculate
311 the maximum scrolling position:
313 MaxScrollPos = MaxRangeValue - (PageSize - 1)
316 #if WXWIN_COMPATIBILITY
317 void wxScrollBar::SetPageSize(int pageLength
)
319 m_pageSize
= pageLength
;
321 #if defined(__WIN95__)
323 info
.cbSize
= sizeof(SCROLLINFO
);
324 info
.nPage
= pageLength
;
325 info
.fMask
= SIF_PAGE
;
327 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
331 void wxScrollBar::SetObjectLength(int objectLength
)
333 m_objectSize
= objectLength
;
335 // The range (number of scroll steps) is the
336 // object length minus the view size.
337 int range
= wxMax((objectLength
- m_viewSize
), 0) ;
339 #if defined(__WIN95__)
340 // Try to adjust the range to cope with page size > 1
341 // (see comment for SetPageLength)
342 if ( m_pageSize
> 1 )
344 range
+= (m_pageSize
- 1);
348 info
.cbSize
= sizeof(SCROLLINFO
);
353 info
.fMask
= SIF_RANGE
;
355 ::SetScrollInfo((HWND
) GetHWND(), SB_CTL
, &info
, TRUE
);
357 ::SetScrollRange((HWND
)m_hWnd
, SB_CTL
, 0, range
, TRUE
);
361 void wxScrollBar::SetViewLength(int viewLength
)
363 m_viewSize
= viewLength
;
366 void wxScrollBar::GetValues(int *viewStart
, int *viewLength
, int *objectLength
,
367 int *pageLength
) const
369 *viewStart
= ::GetScrollPos((HWND
)m_hWnd
, SB_CTL
);
370 *viewLength
= m_viewSize
;
371 *objectLength
= m_objectSize
;
372 *pageLength
= m_pageSize
;
376 WXHBRUSH
wxScrollBar::OnCtlColor(WXHDC
WXUNUSED(pDC
), WXHWND
WXUNUSED(pWnd
), WXUINT
WXUNUSED(nCtlColor
),
377 WXUINT
WXUNUSED(message
), WXWPARAM
WXUNUSED(wParam
), WXLPARAM
WXUNUSED(lParam
))
382 void wxScrollBar::Command(wxCommandEvent
& event
)
384 SetThumbPosition(event
.m_commandInt
);
385 ProcessCommand(event
);
388 #if WXWIN_COMPATIBILITY
389 // Backward compatibility
390 void wxScrollBar::OnScroll(wxScrollEvent
& event
)
392 wxEventType oldEvent
= event
.GetEventType();
393 event
.SetEventType( wxEVT_COMMAND_SCROLLBAR_UPDATED
);
394 if ( !GetEventHandler()->ProcessEvent(event
) )
396 event
.SetEventType( oldEvent
);
397 if (!GetParent()->GetEventHandler()->ProcessEvent(event
))
403 #endif // wxUSE_SCROLLBAR