]> git.saurik.com Git - wxWidgets.git/blob - src/msw/scrolbar.cpp
supporting events also for root control (needed for event handling of mouse and paint...
[wxWidgets.git] / src / msw / scrolbar.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/scrolbar.cpp
3 // Purpose: wxScrollBar
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "scrolbar.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_SCROLLBAR
24
25 #ifndef WX_PRECOMP
26 #include "wx/utils.h"
27 #endif
28
29 #include "wx/scrolbar.h"
30 #include "wx/msw/private.h"
31
32 #if wxUSE_EXTENDED_RTTI
33 WX_DEFINE_FLAGS( wxScrollBarStyle )
34
35 wxBEGIN_FLAGS( wxScrollBarStyle )
36 // new style border flags, we put them first to
37 // use them for streaming out
38 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
39 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
40 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
41 wxFLAGS_MEMBER(wxBORDER_RAISED)
42 wxFLAGS_MEMBER(wxBORDER_STATIC)
43 wxFLAGS_MEMBER(wxBORDER_NONE)
44
45 // old style border flags
46 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
47 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
48 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
49 wxFLAGS_MEMBER(wxRAISED_BORDER)
50 wxFLAGS_MEMBER(wxSTATIC_BORDER)
51 wxFLAGS_MEMBER(wxBORDER)
52
53 // standard window styles
54 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
55 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
56 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
57 wxFLAGS_MEMBER(wxWANTS_CHARS)
58 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
59 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
60 wxFLAGS_MEMBER(wxVSCROLL)
61 wxFLAGS_MEMBER(wxHSCROLL)
62
63 wxFLAGS_MEMBER(wxSB_HORIZONTAL)
64 wxFLAGS_MEMBER(wxSB_VERTICAL)
65
66 wxEND_FLAGS( wxScrollBarStyle )
67
68 IMPLEMENT_DYNAMIC_CLASS_XTI(wxScrollBar, wxControl,"wx/scrolbar.h")
69
70 wxBEGIN_PROPERTIES_TABLE(wxScrollBar)
71 wxEVENT_RANGE_PROPERTY( Scroll , wxEVT_SCROLL_TOP , wxEVT_SCROLL_ENDSCROLL , wxScrollEvent )
72
73 wxPROPERTY( ThumbPosition , int , SetThumbPosition, GetThumbPosition, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
74 wxPROPERTY( Range , int , SetRange, GetRange, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
75 wxPROPERTY( ThumbSize , int , SetThumbSize, GetThumbSize, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
76 wxPROPERTY( PageSize , int , SetPageSize, GetPageSize, 0 , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
77 wxPROPERTY_FLAGS( WindowStyle , wxScrollBarStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
78 wxEND_PROPERTIES_TABLE()
79
80 wxBEGIN_HANDLERS_TABLE(wxScrollBar)
81 wxEND_HANDLERS_TABLE()
82
83 wxCONSTRUCTOR_5( wxScrollBar , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
84 #else
85 IMPLEMENT_DYNAMIC_CLASS(wxScrollBar, wxControl)
86 #endif
87
88 // Scrollbar
89 bool wxScrollBar::Create(wxWindow *parent, wxWindowID id,
90 const wxPoint& pos,
91 const wxSize& size, long style,
92 const wxValidator& wxVALIDATOR_PARAM(validator),
93 const wxString& name)
94 {
95 if (!parent)
96 return FALSE;
97 parent->AddChild(this);
98 SetName(name);
99 #if wxUSE_VALIDATORS
100 SetValidator(validator);
101 #endif // wxUSE_VALIDATORS
102
103 if ((style & wxBORDER_MASK) == wxBORDER_DEFAULT)
104 style |= wxNO_BORDER;
105
106 SetBackgroundColour(parent->GetBackgroundColour()) ;
107 SetForegroundColour(parent->GetForegroundColour()) ;
108 m_windowStyle = style;
109
110 if ( id == -1 )
111 m_windowId = (int)NewControlId();
112 else
113 m_windowId = id;
114
115 int x = pos.x;
116 int y = pos.y;
117 int width = size.x;
118 int height = size.y;
119
120 if (width == -1)
121 {
122 if (style & wxHORIZONTAL)
123 width = 140;
124 else
125 width = 14;
126 }
127 if (height == -1)
128 {
129 if (style & wxVERTICAL)
130 height = 140;
131 else
132 height = 14;
133 }
134
135 WXDWORD exStyle = 0;
136 WXDWORD wstyle = MSWGetStyle(style, & exStyle) ;
137
138 // Now create scrollbar
139 DWORD _direction = (style & wxHORIZONTAL) ?
140 SBS_HORZ: SBS_VERT;
141 HWND scroll_bar = CreateWindowEx(exStyle, wxT("SCROLLBAR"), wxT("scrollbar"),
142 _direction | wstyle,
143 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)m_windowId,
144 wxGetInstance(), NULL);
145
146 m_pageSize = 1;
147 m_viewSize = 1;
148 m_objectSize = 1;
149
150 ::SetScrollRange(scroll_bar, SB_CTL, 0, 1, FALSE);
151 ::SetScrollPos(scroll_bar, SB_CTL, 0, FALSE);
152 ShowWindow(scroll_bar, SW_SHOW);
153
154 SetFont(parent->GetFont());
155
156 m_hWnd = (WXHWND)scroll_bar;
157
158 // Subclass again for purposes of dialog editing mode
159 SubclassWin((WXHWND) scroll_bar);
160
161 SetSize(x, y, width, height);
162
163 return TRUE;
164 }
165
166 wxScrollBar::~wxScrollBar(void)
167 {
168 }
169
170 bool wxScrollBar::MSWOnScroll(int WXUNUSED(orientation), WXWORD wParam,
171 WXWORD pos, WXHWND WXUNUSED(control))
172 {
173 // current and max positions
174 int position,
175 maxPos, trackPos = pos;
176
177 // when we're dragging the scrollbar we can't use pos parameter because it
178 // is limited to 16 bits
179 // JACS: now always using GetScrollInfo, since there's no reason
180 // not to
181 // if ( wParam == SB_THUMBPOSITION || wParam == SB_THUMBTRACK )
182 {
183 SCROLLINFO scrollInfo;
184 wxZeroMemory(scrollInfo);
185 scrollInfo.cbSize = sizeof(SCROLLINFO);
186
187 // also get the range if we call GetScrollInfo() anyhow -- this is less
188 // expensive than call it once here and then call GetScrollRange()
189 // below
190 scrollInfo.fMask = SIF_RANGE | SIF_POS | SIF_TRACKPOS;
191
192 if ( !::GetScrollInfo(GetHwnd(), SB_CTL, &scrollInfo) )
193 {
194 wxLogLastError(_T("GetScrollInfo"));
195 }
196
197 trackPos = scrollInfo.nTrackPos;
198 position = scrollInfo.nPos;
199 maxPos = scrollInfo.nMax;
200 }
201 #if 0
202 else
203 {
204 position = ::GetScrollPos((HWND) control, SB_CTL);
205 int minPos;
206 ::GetScrollRange((HWND) control, SB_CTL, &minPos, &maxPos);
207 }
208 #endif
209
210 #if defined(__WIN95__)
211 // A page size greater than one has the effect of reducing the effective
212 // range, therefore the range has already been boosted artificially - so
213 // reduce it again.
214 if ( m_pageSize > 1 )
215 maxPos -= (m_pageSize - 1);
216 #endif // __WIN95__
217
218 wxEventType scrollEvent = wxEVT_NULL;
219
220 int nScrollInc;
221 switch ( wParam )
222 {
223 case SB_BOTTOM:
224 nScrollInc = maxPos - position;
225 scrollEvent = wxEVT_SCROLL_TOP;
226 break;
227
228 case SB_TOP:
229 nScrollInc = -position;
230 scrollEvent = wxEVT_SCROLL_BOTTOM;
231 break;
232
233 case SB_LINEUP:
234 nScrollInc = -1;
235 scrollEvent = wxEVT_SCROLL_LINEUP;
236 break;
237
238 case SB_LINEDOWN:
239 nScrollInc = 1;
240 scrollEvent = wxEVT_SCROLL_LINEDOWN;
241 break;
242
243 case SB_PAGEUP:
244 nScrollInc = -GetPageSize();
245 scrollEvent = wxEVT_SCROLL_PAGEUP;
246 break;
247
248 case SB_PAGEDOWN:
249 nScrollInc = GetPageSize();
250 scrollEvent = wxEVT_SCROLL_PAGEDOWN;
251 break;
252
253 case SB_THUMBPOSITION:
254 nScrollInc = trackPos - position;
255 scrollEvent = wxEVT_SCROLL_THUMBRELEASE;
256 break;
257
258 case SB_THUMBTRACK:
259 nScrollInc = trackPos - position;
260 scrollEvent = wxEVT_SCROLL_THUMBTRACK;
261 break;
262
263 case SB_ENDSCROLL:
264 nScrollInc = 0;
265 scrollEvent = wxEVT_SCROLL_ENDSCROLL;
266 break;
267
268 default:
269 nScrollInc = 0;
270 }
271
272 if ( nScrollInc )
273 {
274 position += nScrollInc;
275
276 if ( position < 0 )
277 position = 0;
278 if ( position > maxPos )
279 position = maxPos;
280
281 SetThumbPosition(position);
282 }
283 else if ( scrollEvent != wxEVT_SCROLL_THUMBRELEASE &&
284 scrollEvent != wxEVT_SCROLL_ENDSCROLL )
285 {
286 // don't process the event if there is no displacement,
287 // unless this is a thumb release or end scroll event.
288 return FALSE;
289 }
290
291 wxScrollEvent event(scrollEvent, m_windowId);
292 event.SetOrientation(IsVertical() ? wxVERTICAL : wxHORIZONTAL);
293 event.SetPosition(position);
294 event.SetEventObject( this );
295
296 return GetEventHandler()->ProcessEvent(event);
297 }
298
299 void wxScrollBar::SetThumbPosition(int viewStart)
300 {
301 #if defined(__WIN95__)
302 SCROLLINFO info;
303 info.cbSize = sizeof(SCROLLINFO);
304 info.nPage = 0;
305 info.nMin = 0;
306 info.nPos = viewStart;
307 info.fMask = SIF_POS ;
308
309 ::SetScrollInfo((HWND) GetHWND(), SB_CTL, &info, TRUE);
310 #else
311 ::SetScrollPos((HWND) GetHWND(), SB_CTL, viewStart, TRUE);
312 #endif
313 }
314
315 int wxScrollBar::GetThumbPosition(void) const
316 {
317 SCROLLINFO scrollInfo;
318 wxZeroMemory(scrollInfo);
319 scrollInfo.cbSize = sizeof(SCROLLINFO);
320 scrollInfo.fMask = SIF_POS;
321
322 if ( !::GetScrollInfo(GetHwnd(), SB_CTL, &scrollInfo) )
323 {
324 wxLogLastError(_T("GetScrollInfo"));
325 }
326 return scrollInfo.nPos;
327 // return ::GetScrollPos((HWND)m_hWnd, SB_CTL);
328 }
329
330 void wxScrollBar::SetScrollbar(int position, int thumbSize, int range, int pageSize,
331 bool refresh)
332 {
333 m_viewSize = pageSize;
334 m_pageSize = thumbSize;
335 m_objectSize = range;
336
337 // The range (number of scroll steps) is the
338 // object length minus the page size.
339 int range1 = wxMax((m_objectSize - m_pageSize), 0) ;
340
341 #if defined(__WIN95__)
342 // Try to adjust the range to cope with page size > 1
343 // (see comment for SetPageLength)
344 if ( m_pageSize > 1 )
345 {
346 range1 += (m_pageSize - 1);
347 }
348
349 SCROLLINFO info;
350 info.cbSize = sizeof(SCROLLINFO);
351 info.nPage = m_pageSize;
352 info.nMin = 0;
353 info.nMax = range1;
354 info.nPos = position;
355
356 info.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;
357
358 ::SetScrollInfo((HWND) GetHWND(), SB_CTL, &info, refresh);
359 #else
360 ::SetScrollPos((HWND)m_hWnd, SB_CTL, position, TRUE);
361 ::SetScrollRange((HWND)m_hWnd, SB_CTL, 0, range1, TRUE);
362 #endif
363 }
364
365
366 WXHBRUSH wxScrollBar::OnCtlColor(WXHDC WXUNUSED(pDC), WXHWND WXUNUSED(pWnd), WXUINT WXUNUSED(nCtlColor),
367 WXUINT WXUNUSED(message), WXWPARAM WXUNUSED(wParam), WXLPARAM WXUNUSED(lParam))
368 {
369 return 0;
370 }
371
372 void wxScrollBar::Command(wxCommandEvent& event)
373 {
374 SetThumbPosition(event.m_commandInt);
375 ProcessCommand(event);
376 }
377
378 #endif // wxUSE_SCROLLBAR