source: trunk/src/user32/scroll.cpp@ 6043

Last change on this file since 6043 was 6043, checked in by sandervl, 24 years ago

sizegrip & sizebox scrollbar size fixes

File size: 51.3 KB
Line 
1/* $Id: scroll.cpp,v 1.41 2001-06-18 09:00:50 sandervl Exp $ */
2/*
3 * Scrollbar control
4 *
5 * Copyright 1999 Christoph Bratschi
6 *
7 * Copyright 1993 Martin Ayotte
8 * Copyright 1994, 1996 Alexandre Julliard
9 *
10 * WINE version: 20000130
11 *
12 * Status: complete
13 * Version: 5.00
14 */
15
16#include <stdlib.h>
17#include <os2win.h>
18#include "controls.h"
19#include "scroll.h"
20#include "win32wbase.h"
21#include "oslibwin.h"
22#include "initterm.h"
23
24#define DBG_LOCALLOG DBG_scroll
25#include "dbglocal.h"
26
27#define SCROLL_MIN_RECT 4 /* Minimum size of the rectangle between the arrows */
28#define SCROLL_MIN_THUMB 6 /* Minimum size of the thumb in pixels */
29
30#define SCROLL_ARROW_THUMB_OVERLAP 0 /* Overlap between arrows and thumb */
31
32#define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when holding the button down */
33#define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
34#define SCROLL_BLINK_DELAY 1000
35
36#define SCROLL_TIMER 0 /* Scroll timer id */
37#define BLINK_TIMER 1
38
39 /* Scroll-bar hit testing */
40enum SCROLL_HITTEST
41{
42 SCROLL_NOWHERE, /* Outside the scroll bar */
43 SCROLL_TOP_ARROW, /* Top or left arrow */
44 SCROLL_TOP_RECT, /* Rectangle between the top arrow and the thumb */
45 SCROLL_THUMB, /* Thumb rectangle */
46 SCROLL_BOTTOM_RECT, /* Rectangle between the thumb and the bottom arrow */
47 SCROLL_BOTTOM_ARROW /* Bottom or right arrow */
48};
49
50 /* What to do in SetScrollInfo() */
51#define SA_SSI_HIDE 0x0001
52#define SA_SSI_SHOW 0x0002
53#define SA_SSI_REPAINT_INTERIOR 0x0004
54#define SA_SSI_REPAINT_ARROWS 0x0008
55#define SA_SSI_MOVE_THUMB 0x0010
56#define SA_SSI_REFRESH 0x0020
57
58 /* Thumb-tracking info */
59static HWND SCROLL_TrackingWin = 0;
60static INT SCROLL_TrackingBar = 0;
61static INT SCROLL_TrackingPos = 0;
62static INT SCROLL_TrackingVal = 0;
63 /* Focus info */
64static HWND SCROLL_FocusWin = 0;
65static BOOL SCROLL_HasFocus = FALSE;
66static BOOL SCROLL_Highlighted = FALSE;
67static BOOL SCROLL_Scrolling = FALSE;
68
69 /* Hit test code of the last button-down event */
70static enum SCROLL_HITTEST SCROLL_trackHitTest;
71static enum SCROLL_HITTEST SCROLL_lastHitTest;
72static BOOL SCROLL_trackVertical;
73
74 /* Is the moving thumb being displayed? */
75static BOOL SCROLL_MovingThumb = FALSE;
76
77static SCROLLBAR_INFO *SCROLL_GetInfoPtr( HWND hwnd, INT nBar )
78{
79 Win32BaseWindow *win32wnd;
80
81 switch(nBar)
82 {
83 case SB_HORZ:
84 case SB_VERT:
85 {
86 SCROLLBAR_INFO *pInfo;
87 win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
88
89 if (!win32wnd) return NULL;
90 pInfo = win32wnd->getScrollInfo(nBar);
91 RELEASE_WNDOBJ(win32wnd);
92 return pInfo;
93 }
94
95 case SB_CTL:
96 return (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
97 }
98
99 return NULL;
100}
101
102/* Scrollbar Functions */
103
104/***********************************************************************
105 * SCROLL_GetScrollBarRect
106 *
107 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
108 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
109 * 'arrowSize' returns the width or height of an arrow (depending on
110 * the orientation of the scrollbar), 'thumbSize' returns the size of
111 * the thumb, and 'thumbPos' returns the position of the thumb
112 * relative to the left or to the top.
113 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
114 */
115static BOOL SCROLL_GetScrollBarRect( HWND hwnd, INT nBar, RECT *lprect,
116 INT *arrowSize, INT *thumbSize,
117 INT *thumbPos )
118{
119 INT pixels;
120 BOOL vertical;
121 RECT rectClient;
122
123 switch(nBar)
124 {
125 case SB_HORZ:
126 {
127 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
128 RECT rectClient;
129
130 if (!win32wnd) return FALSE;
131 rectClient = *win32wnd->getClientRectPtr();
132 lprect->left = rectClient.left;
133 lprect->top = rectClient.bottom;
134 lprect->right = rectClient.right;
135 lprect->bottom = lprect->top+GetSystemMetrics(SM_CYHSCROLL);
136 if (win32wnd->getStyle() & WS_BORDER)
137 {
138 lprect->left--;
139 lprect->right++;
140 }
141 else
142 if (win32wnd->getStyle() & WS_VSCROLL)
143 lprect->right++;
144 RELEASE_WNDOBJ(win32wnd);
145 vertical = FALSE;
146 break;
147 }
148
149 case SB_VERT:
150 {
151 Win32BaseWindow *win32wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
152 RECT rectClient;
153
154 if (!win32wnd) return FALSE;
155 rectClient = *win32wnd->getClientRectPtr();
156 lprect->left = rectClient.right;
157 lprect->top = rectClient.top;
158 lprect->right = lprect->left+GetSystemMetrics(SM_CXVSCROLL);
159 lprect->bottom = rectClient.bottom;
160 if(win32wnd->getStyle() & WS_BORDER)
161 {
162 lprect->top--;
163 lprect->bottom++;
164 }
165 else
166 if (win32wnd->getStyle() & WS_HSCROLL)
167 lprect->bottom++;
168 RELEASE_WNDOBJ(win32wnd);
169 vertical = TRUE;
170 break;
171 }
172
173 case SB_CTL:
174 {
175 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
176
177 GetClientRect( hwnd, lprect );
178 vertical = ((dwStyle & SBS_VERT) != 0);
179 break;
180 }
181
182 default:
183 return FALSE;
184 }
185
186 if (vertical) pixels = lprect->bottom - lprect->top;
187 else pixels = lprect->right - lprect->left;
188
189 if (pixels <= 2*GetSystemMetrics(SM_CXVSCROLL) + SCROLL_MIN_RECT)
190 {
191 if (pixels > SCROLL_MIN_RECT)
192 *arrowSize = (pixels - SCROLL_MIN_RECT) / 2;
193 else
194 *arrowSize = 0;
195 *thumbPos = *thumbSize = 0;
196 }
197 else
198 {
199 SCROLLBAR_INFO *info = SCROLL_GetInfoPtr( hwnd, nBar );
200
201 *arrowSize = GetSystemMetrics(SM_CXVSCROLL);
202 pixels -= (2 * (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
203
204 if (info->Page)
205 {
206 *thumbSize = pixels * info->Page / (info->MaxVal-info->MinVal+1);
207 if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
208 }
209 else *thumbSize = GetSystemMetrics(SM_CXVSCROLL);
210
211 if (((pixels -= *thumbSize ) < 0) ||
212 ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
213 {
214 /* Rectangle too small or scrollbar disabled -> no thumb */
215 *thumbPos = *thumbSize = 0;
216 }
217 else
218 {
219 INT max = info->MaxVal - MAX( info->Page-1, 0 );
220 if (info->MinVal >= max)
221 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
222 else
223 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
224 + pixels * (info->CurVal-info->MinVal) / (max - info->MinVal);
225 }
226 }
227 return vertical;
228}
229
230/***********************************************************************
231 * SCROLL_PtInRectEx
232 */
233static BOOL SCROLL_PtInRectEx( LPRECT lpRect, POINT pt, BOOL vertical )
234{
235 RECT rect = *lpRect;
236
237 if (vertical)
238 {
239 INT w = lpRect->right-lpRect->left;
240
241 rect.left -= w;
242 rect.right += w;
243 rect.top -= w;
244 rect.bottom += w;
245 } else
246 {
247 INT h = lpRect->bottom-lpRect->top;
248
249 rect.top -= h;
250 rect.bottom += h;
251 rect.left -= h;
252 rect.right += h;
253 }
254
255 return PtInRect( &rect, pt );
256}
257
258/***********************************************************************
259 * SCROLL_HitTest
260 *
261 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
262 */
263static enum SCROLL_HITTEST SCROLL_HitTest( HWND hwnd, INT nBar,
264 POINT pt, BOOL bDragging )
265{
266 INT arrowSize, thumbSize, thumbPos;
267 RECT rect;
268 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
269
270 if (!infoPtr) return SCROLL_NOWHERE;
271
272 BOOL vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
273 &arrowSize, &thumbSize, &thumbPos );
274
275 if ( (bDragging && !SCROLL_PtInRectEx( &rect, pt, vertical )) ||
276 (!PtInRect( &rect, pt )) ) return SCROLL_NOWHERE;
277
278 if (vertical)
279 {
280 if (pt.y < rect.top + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
281 if (pt.y >= rect.bottom - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
282 if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
283 pt.y -= rect.top;
284 if (pt.y < thumbPos) return SCROLL_TOP_RECT;
285 if (pt.y >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
286 }
287 else /* horizontal */
288 {
289 if (pt.x < rect.left + arrowSize) return (infoPtr->flags & ESB_DISABLE_LTUP) ? SCROLL_NOWHERE:SCROLL_TOP_ARROW;
290 if (pt.x >= rect.right - arrowSize) return (infoPtr->flags & ESB_DISABLE_RTDN) ? SCROLL_NOWHERE:SCROLL_BOTTOM_ARROW;
291 if (!thumbPos) return ((infoPtr->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH) ? SCROLL_NOWHERE:SCROLL_TOP_RECT;
292 pt.x -= rect.left;
293 if (pt.x < thumbPos) return SCROLL_TOP_RECT;
294 if (pt.x >= thumbPos + thumbSize) return SCROLL_BOTTOM_RECT;
295 }
296 return SCROLL_THUMB;
297}
298
299static void SCROLL_DrawTopArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL top_pressed)
300{
301 RECT r;
302
303 r = *rect;
304 if( vertical )
305 r.bottom = r.top + arrowSize;
306 else
307 r.right = r.left + arrowSize;
308
309 DrawFrameControl( hdc, &r, DFC_SCROLL,
310 (vertical ? DFCS_SCROLLUP : DFCS_SCROLLLEFT)
311 | (top_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
312 | (infoPtr->flags&ESB_DISABLE_LTUP ? DFCS_INACTIVE : 0 ) );
313}
314
315static void SCROLL_DrawBottomArrow(HDC hdc,SCROLLBAR_INFO *infoPtr,RECT *rect,INT arrowSize,BOOL vertical,BOOL bottom_pressed)
316{
317 RECT r;
318
319 r = *rect;
320 if( vertical )
321 r.top = r.bottom-arrowSize;
322 else
323 r.left = r.right-arrowSize;
324
325 DrawFrameControl( hdc, &r, DFC_SCROLL,
326 (vertical ? DFCS_SCROLLDOWN : DFCS_SCROLLRIGHT)
327 | (bottom_pressed ? (DFCS_PUSHED | DFCS_FLAT) : 0 )
328 | (infoPtr->flags&ESB_DISABLE_RTDN ? DFCS_INACTIVE : 0) );
329}
330
331/***********************************************************************
332 * SCROLL_DrawArrows
333 *
334 * Draw the scroll bar arrows.
335 */
336static void SCROLL_DrawArrows( HDC hdc, SCROLLBAR_INFO *infoPtr,
337 RECT *rect, INT arrowSize, BOOL vertical,
338 BOOL top_pressed, BOOL bottom_pressed )
339{
340 SCROLL_DrawTopArrow(hdc,infoPtr,rect,arrowSize,vertical,top_pressed);
341 SCROLL_DrawBottomArrow(hdc,infoPtr,rect,arrowSize,vertical,bottom_pressed);
342}
343
344static void SCROLL_DrawInterior( HWND hwnd, HDC hdc, INT nBar,
345 RECT *rect, INT arrowSize,
346 INT thumbSize, INT thumbPos,
347 UINT flags, BOOL vertical,
348 BOOL top_selected, BOOL bottom_selected )
349{
350 RECT r;
351 HPEN hSavePen;
352 HBRUSH hSaveBrush,hBrush;
353
354 /* Select the correct brush and pen */
355
356 /* Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
357 * The window-owned scrollbars need to call DEFWND_ControlColor
358 * to correctly setup default scrollbar colors
359 */
360 if (nBar == SB_CTL) {
361 hBrush = (HBRUSH)SendMessageA( GetParent(hwnd), WM_CTLCOLORSCROLLBAR,
362 (WPARAM)hdc,(LPARAM)hwnd);
363 } else {
364 hBrush = (HBRUSH)SendMessageA( hwnd, WM_CTLCOLORSCROLLBAR,
365 (WPARAM)hdc,(LPARAM)hwnd);
366
367 }
368
369 hSavePen = SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
370 hSaveBrush = SelectObject( hdc, hBrush );
371
372 /* Calculate the scroll rectangle */
373
374 r = *rect;
375 if (vertical)
376 {
377 r.top += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
378 r.bottom -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
379 }
380 else
381 {
382 r.left += arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
383 r.right -= (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
384 }
385
386 /* Draw the scroll rectangles and thumb */
387 if (!thumbPos) /* No thumb to draw */
388 {
389 PatBlt( hdc, r.left, r.top,
390 r.right - r.left, r.bottom - r.top,
391 PATCOPY );
392
393 /* cleanup and return */
394 SelectObject( hdc, hSavePen );
395 SelectObject( hdc, hSaveBrush );
396 return;
397 }
398
399 if (vertical)
400 {
401 PatBlt( hdc, r.left, r.top,
402 r.right - r.left,
403 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
404 top_selected ? 0x0f0000 : PATCOPY );
405 r.top += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
406 PatBlt( hdc, r.left, r.top + thumbSize,
407 r.right - r.left,
408 r.bottom - r.top - thumbSize,
409 bottom_selected ? 0x0f0000 : PATCOPY );
410 r.bottom = r.top + thumbSize;
411 }
412 else /* horizontal */
413 {
414 PatBlt( hdc, r.left, r.top,
415 thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP),
416 r.bottom - r.top,
417 top_selected ? 0x0f0000 : PATCOPY );
418 r.left += thumbPos - (arrowSize - SCROLL_ARROW_THUMB_OVERLAP);
419 PatBlt( hdc, r.left + thumbSize, r.top,
420 r.right - r.left - thumbSize,
421 r.bottom - r.top,
422 bottom_selected ? 0x0f0000 : PATCOPY );
423 r.right = r.left + thumbSize;
424 }
425
426 /* Draw the thumb */
427
428 DrawEdge(hdc,&r,EDGE_RAISED,BF_RECT | BF_ADJUST);
429 FillRect(hdc,&r,(SCROLL_FocusWin == hwnd && SCROLL_Highlighted && !SCROLL_Scrolling) ? GetSysColorBrush(COLOR_3DSHADOW):GetSysColorBrush(COLOR_BTNFACE));
430
431 /* cleanup */
432 SelectObject( hdc, hSavePen );
433 SelectObject( hdc, hSaveBrush );
434}
435
436/***********************************************************************
437 * SCROLL_DrawMovingThumb
438 *
439 * Draw the moving thumb rectangle.
440 */
441static void SCROLL_DrawMovingThumb( HDC hdc, RECT *rect, BOOL vertical,
442 INT arrowSize, INT thumbSize )
443{
444 INT pos = SCROLL_TrackingPos;
445 INT max_size;
446
447 if( vertical )
448 max_size = rect->bottom - rect->top;
449 else
450 max_size = rect->right - rect->left;
451
452 max_size -= (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) + thumbSize;
453
454 if( pos < (arrowSize-SCROLL_ARROW_THUMB_OVERLAP) )
455 pos = (arrowSize-SCROLL_ARROW_THUMB_OVERLAP);
456 else if( pos > max_size )
457 pos = max_size;
458
459 SCROLL_DrawInterior( SCROLL_TrackingWin, hdc, SCROLL_TrackingBar,
460 rect, arrowSize, thumbSize, pos,
461 0, vertical, FALSE, FALSE );
462}
463
464/***********************************************************************
465 * SCROLL_ClipPos
466 */
467static POINT SCROLL_ClipPos( LPRECT lpRect, POINT pt )
468{
469 if( pt.x < lpRect->left )
470 pt.x = lpRect->left;
471 else
472 if( pt.x >= lpRect->right )
473 pt.x = lpRect->right-1;
474
475 if( pt.y < lpRect->top )
476 pt.y = lpRect->top;
477 else
478 if( pt.y >= lpRect->bottom )
479 pt.y = lpRect->bottom-1;
480
481 return pt;
482}
483
484/***********************************************************************
485 * SCROLL_GetThumbVal
486 *
487 * Compute the current scroll position based on the thumb position in pixels
488 * from the top of the scroll-bar.
489 */
490static UINT SCROLL_GetThumbVal( SCROLLBAR_INFO *infoPtr, RECT *rect,
491 BOOL vertical, INT pos )
492{
493 INT thumbSize;
494 INT pixels = vertical ? rect->bottom-rect->top : rect->right-rect->left;
495
496 if ((pixels -= 2*(GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP)) <= 0)
497 return infoPtr->MinVal;
498
499 if (infoPtr->Page)
500 {
501 thumbSize = pixels * infoPtr->Page/(infoPtr->MaxVal-infoPtr->MinVal+1);
502 if (thumbSize < SCROLL_MIN_THUMB) thumbSize = SCROLL_MIN_THUMB;
503 }
504 else thumbSize = GetSystemMetrics(SM_CXVSCROLL);
505
506 if ((pixels -= thumbSize) <= 0) return infoPtr->MinVal;
507
508 pos = MAX( 0, pos - (GetSystemMetrics(SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP) );
509 if (pos > pixels) pos = pixels;
510
511 if (!infoPtr->Page) pos *= infoPtr->MaxVal - infoPtr->MinVal;
512 else pos *= infoPtr->MaxVal - infoPtr->MinVal - infoPtr->Page + 1;
513 return infoPtr->MinVal + ((pos + pixels / 2) / pixels);
514}
515
516void SCROLL_GetSizeBox(HWND hwnd,DWORD dwStyle,PRECT rect)
517{
518 RECT clientRect;
519 INT cx = GetSystemMetrics(SM_CXVSCROLL);
520 INT cy = GetSystemMetrics(SM_CYHSCROLL);
521
522 GetClientRect(hwnd,&clientRect);
523
524 if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
525 {
526 rect->left = 0;
527 rect->right = cx;
528 rect->bottom = cy;
529 rect->top = 0;
530 } else
531 {
532 rect->left = clientRect.right-cx;
533 rect->right = clientRect.right;
534 rect->bottom = clientRect.bottom;
535 rect->top = clientRect.bottom-cy;
536 }
537}
538
539void SCROLL_DrawSizeBox(HDC hdc,RECT rect)
540{
541 POINT p1,p2;
542 HPEN penDark = GetSysColorPen(COLOR_3DSHADOW);
543 HPEN penWhite = GetSysColorPen(COLOR_3DHILIGHT);
544 HPEN oldPen = SelectObject(hdc,penDark);
545 INT x;
546
547 p1.x = rect.right-1;
548 p1.y = rect.bottom;
549 p2.x = rect.right;
550 p2.y = rect.bottom-1;
551 for (x = 0;x < 3;x++)
552 {
553 SelectObject(hdc,penDark);
554 MoveToEx(hdc,p1.x,p1.y,NULL);
555 LineTo(hdc,p2.x,p2.y);
556 p1.x--;
557 p2.y--;
558 MoveToEx(hdc,p1.x,p1.y,NULL);
559 LineTo(hdc,p2.x,p2.y);
560 SelectObject(hdc,penWhite);
561 p1.x--;
562 p2.y--;
563 MoveToEx(hdc,p1.x,p1.y,NULL);
564 LineTo(hdc,p2.x,p2.y);
565 p1.x -= 2;
566 p2.y -= 2;
567 }
568
569 SelectObject(hdc,oldPen);
570}
571
572/***********************************************************************
573 * SCROLL_DrawScrollBar
574 *
575 * Redraw the whole scrollbar.
576 */
577void SCROLL_DrawScrollBar(HWND hwnd,HDC hdc,INT nBar,BOOL arrows,BOOL interior)
578{
579 INT arrowSize, thumbSize, thumbPos;
580 RECT rect;
581 BOOL vertical;
582 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr( hwnd, nBar );
583
584 if (!infoPtr) return;
585 if (nBar == SB_CTL)
586 {
587 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
588
589 if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP))
590 {
591 RECT rect;
592 HBRUSH hBrush;
593
594 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
595 hBrush = GetSysColorBrush(COLOR_3DFACE);
596 GetClientRect(hwnd,&rect);
597 FillRect(hdc,&rect,hBrush);
598
599 if (dwStyle & SBS_SIZEGRIP)
600 {
601 SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
602 SCROLL_DrawSizeBox(hdc,rect);
603 }
604
605 ReleaseDC(hwnd,hdc);
606
607 return;
608 }
609 }
610
611 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
612 &arrowSize, &thumbSize, &thumbPos );
613
614 /* Draw the arrows */
615
616 if (arrows && arrowSize)
617 {
618 if( vertical == SCROLL_trackVertical && GetCapture() == hwnd )
619 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
620 (SCROLL_trackHitTest == SCROLL_TOP_ARROW),
621 (SCROLL_trackHitTest == SCROLL_BOTTOM_ARROW) );
622 else
623 SCROLL_DrawArrows( hdc, infoPtr, &rect, arrowSize, vertical,
624 FALSE, FALSE );
625 }
626
627 if (SCROLL_MovingThumb &&
628 (SCROLL_TrackingWin == hwnd) &&
629 (SCROLL_TrackingBar == nBar))
630 SCROLL_DrawMovingThumb( hdc, &rect, vertical, arrowSize, thumbSize );
631 else if( interior )
632 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
633 thumbPos, infoPtr->flags, vertical, SCROLL_trackHitTest == SCROLL_TOP_RECT && SCROLL_lastHitTest == SCROLL_TOP_RECT,SCROLL_trackHitTest == SCROLL_BOTTOM_RECT && SCROLL_lastHitTest == SCROLL_BOTTOM_RECT);
634}
635
636/***********************************************************************
637 * SCROLL_RefreshScrollBar
638 *
639 * Repaint the scroll bar interior after a SetScrollRange() or
640 * SetScrollPos() call.
641 */
642static void SCROLL_RefreshScrollBar( HWND hwnd, INT nBar,
643 BOOL arrows, BOOL interior )
644{
645 HDC hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
646
647 if (!hdc) return;
648
649 SCROLL_DrawScrollBar( hwnd, hdc, nBar, arrows, interior );
650 ReleaseDC( hwnd, hdc );
651}
652
653/* Message Handler */
654
655LRESULT SCROLL_NCCreate(HWND hwnd,WPARAM wParam,LPARAM lParam)
656{
657 SCROLLBAR_INFO *infoPtr = (SCROLLBAR_INFO*)malloc(sizeof(SCROLLBAR_INFO));
658
659 infoPtr->MinVal = infoPtr->CurVal = infoPtr->Page = 0;
660 infoPtr->MaxVal = 100;
661 infoPtr->flags = ESB_ENABLE_BOTH;
662
663 SetInfoPtr(hwnd,(DWORD)infoPtr);
664
665 return TRUE;
666}
667
668LRESULT SCROLL_Create(HWND hwnd,WPARAM wParam,LPARAM lParam)
669{
670 CREATESTRUCTA *lpCreat = (CREATESTRUCTA *)lParam;
671
672#ifdef __WIN32OS2__
673 if (!((lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) && !(lpCreat->style & (SBS_SIZEBOXTOPLEFTALIGN | SBS_SIZEBOXBOTTOMRIGHTALIGN))))
674#endif
675 {
676 if (lpCreat->style & SBS_VERT)
677 {
678 INT w,h;
679
680 w = GetSystemMetrics(SM_CXVSCROLL);
681#ifdef __WIN32OS2__
682 if(lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) {
683 h = GetSystemMetrics(SM_CYHSCROLL);
684 }
685 else h = lpCreat->cy;
686#else
687 h = lpCreat->cy;
688#endif
689 if (lpCreat->style & SBS_LEFTALIGN)
690 MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
691 else if (lpCreat->style & SBS_RIGHTALIGN)
692 MoveWindow(hwnd,lpCreat->x+lpCreat->cx-w,lpCreat->y,w,h,FALSE);
693 } else /* SBS_HORZ */
694 {
695 INT w,h;
696
697#ifdef __WIN32OS2__
698 if(lpCreat->style & (SBS_SIZEBOX | SBS_SIZEGRIP)) {
699 w = GetSystemMetrics(SM_CXVSCROLL);
700 }
701 else w = lpCreat->cx;
702#else
703 w = lpCreat->cx;
704#endif
705
706 h = GetSystemMetrics(SM_CYHSCROLL);
707
708 if (lpCreat->style & SBS_TOPALIGN)
709 MoveWindow(hwnd,lpCreat->x,lpCreat->y,w,h,FALSE);
710 else if (lpCreat->style & SBS_BOTTOMALIGN)
711 MoveWindow(hwnd,lpCreat->x,lpCreat->y+lpCreat->cy-h,w,h,FALSE);
712 }
713 }
714
715 return 0;
716}
717
718static LRESULT SCROLL_Destroy(HWND hwnd,WPARAM wParam,LPARAM lParam)
719{
720 SCROLLBAR_INFO* infoPtr = (SCROLLBAR_INFO*)GetInfoPtr(hwnd);
721
722 free(infoPtr);
723
724 return 0;
725}
726
727/***********************************************************************
728 * SCROLL_HandleScrollEvent
729 *
730 * Handle a mouse or timer event for the scrollbar.
731 * 'pt' is the location of the mouse event in client (for SB_CTL) or
732 * windows coordinates.
733 */
734LRESULT SCROLL_HandleScrollEvent(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,UINT msg)
735{
736 static POINT prevPt; /* Previous mouse position for timer events */
737 static UINT trackThumbPos; /* Thumb position when tracking started. */
738 static BOOL thumbTrackSent;
739 static INT lastClickPos; /* Position in the scroll-bar of the last button-down event. */
740 static INT lastMousePos; /* Position in the scroll-bar of the last mouse event. */
741 static BOOL timerRunning;
742
743 enum SCROLL_HITTEST hittest;
744 HWND hwndOwner, hwndCtl;
745 BOOL vertical;
746 INT arrowSize, thumbSize, thumbPos;
747 RECT rect;
748 HDC hdc;
749 POINT pt;
750 LRESULT res = 0;
751
752 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
753 if (!infoPtr) return res;
754
755 if (nBar == SB_CTL)
756 {
757 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
758
759 if ((dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)))
760 {
761 if (!(dwStyle & SBS_SIZEGRIP)) return res;
762
763 if (msg == WM_NCHITTEST)
764 {
765 if (dwStyle & SBS_SIZEGRIP)
766 {
767 RECT rect;
768
769 pt.x = (SHORT)LOWORD(lParam);
770 pt.y = (SHORT)HIWORD(lParam);
771 ScreenToClient(hwnd,&pt);
772 SCROLL_GetSizeBox(hwnd,dwStyle,&rect);
773 if (PtInRect(&rect,pt))
774 {
775 if (dwStyle & SBS_SIZEBOXTOPLEFTALIGN)
776 return HTTOPLEFT;
777 else
778 return HTBOTTOMRIGHT;
779 }
780 }
781 return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
782 } else if (msg == WM_LBUTTONDOWN)
783 {
784 return DefWindowProcA(hwnd,WM_LBUTTONDOWN,wParam,lParam);
785 }
786
787 return res;
788 }
789 }
790
791 if (msg == WM_NCHITTEST) return DefWindowProcA(hwnd,WM_NCHITTEST,wParam,lParam);
792
793 vertical = SCROLL_GetScrollBarRect(hwnd,nBar,&rect,&arrowSize,&thumbSize,&thumbPos);
794 hwndOwner = (nBar == SB_CTL) ? GetParent(hwnd):hwnd;
795
796 hwndCtl = (nBar == SB_CTL) ? hwnd:0;
797
798 switch (msg)
799 {
800 case WM_LBUTTONDOWN: /* Initialise mouse tracking */
801 pt.x = (SHORT)LOWORD(lParam);
802 pt.y = (SHORT)HIWORD(lParam);
803 SCROLL_trackVertical = vertical;
804 SCROLL_trackHitTest = hittest = SCROLL_HitTest(hwnd,nBar,pt,FALSE);
805 if (SCROLL_trackHitTest == SCROLL_NOWHERE)
806 {
807 MessageBeep(MB_ICONEXCLAMATION);
808
809 return res;
810 }
811 SCROLL_Scrolling = TRUE;
812 timerRunning = FALSE;
813 if ((SCROLL_FocusWin == hwnd) && SCROLL_Highlighted)
814 {
815 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
816 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
817 ReleaseDC(hwnd,hdc);
818 }
819 lastClickPos = vertical ? pt.y:pt.x;
820 lastMousePos = lastClickPos;
821 trackThumbPos = thumbPos;
822 prevPt = pt;
823 if (nBar == SB_CTL) SetFocus(hwnd);
824 SetCapture(hwnd);
825 break;
826
827 case WM_MOUSEMOVE:
828 if (SCROLL_Scrolling)
829 {
830 pt.x = (SHORT)LOWORD(lParam);
831 pt.y = (SHORT)HIWORD(lParam);
832 hittest = SCROLL_HitTest(hwnd,nBar,pt,TRUE);
833 prevPt = pt;
834 } else return res;
835 break;
836
837 case WM_LBUTTONUP:
838 if (SCROLL_Scrolling)
839 {
840 pt.x = (SHORT)LOWORD(lParam);
841 pt.y = (SHORT)HIWORD(lParam);
842 hittest = SCROLL_NOWHERE;
843 ReleaseCapture();
844 SCROLL_Scrolling = FALSE;
845 } else return res;
846 break;
847
848 case WM_CAPTURECHANGED:
849 if (SCROLL_Scrolling)
850 {
851 hittest = SCROLL_NOWHERE;
852 SCROLL_Scrolling = FALSE;
853 } else return res;
854 break;
855
856 case WM_SETFOCUS:
857 if (nBar == SB_CTL)
858 {
859 SCROLL_FocusWin = hwnd;
860 SCROLL_HasFocus = TRUE;
861 SCROLL_Highlighted = FALSE;
862 SetSystemTimer(hwnd,BLINK_TIMER,SCROLL_BLINK_DELAY,(TIMERPROC)0);
863 }
864 return res;
865
866 case WM_KILLFOCUS:
867 if (SCROLL_FocusWin == hwnd)
868 {
869 SCROLL_FocusWin = 0;
870 SCROLL_HasFocus = FALSE;
871 if (SCROLL_Highlighted)
872 {
873 SCROLL_Highlighted = FALSE;
874 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0:DCX_WINDOW));
875 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
876 ReleaseDC(hwnd,hdc);
877 }
878 KillSystemTimer(hwnd,BLINK_TIMER);
879 }
880 return res;
881
882 case WM_SYSTIMER:
883 if (wParam == SCROLL_TIMER)
884 {
885 pt = prevPt;
886 hittest = SCROLL_HitTest( hwnd, nBar, pt, FALSE );
887 break;
888 } else if (wParam == BLINK_TIMER)
889 {
890 SCROLL_Highlighted = ~SCROLL_Highlighted;
891 if (!SCROLL_Scrolling)
892 {
893 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
894 SCROLL_DrawScrollBar(hwnd,hdc,nBar,FALSE,TRUE);
895 ReleaseDC(hwnd,hdc);
896 }
897 return res;
898 } else return res;
899
900 default:
901 return res; /* Should never happen */
902 }
903
904 hdc = GetDCEx(hwnd,0,DCX_CACHE | ((nBar == SB_CTL) ? 0 : DCX_WINDOW));
905
906 switch(SCROLL_trackHitTest)
907 {
908 case SCROLL_NOWHERE: /* No tracking in progress */
909 break;
910
911 case SCROLL_TOP_ARROW:
912 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
913 KillSystemTimer(hwnd,SCROLL_TIMER);
914 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && msg == WM_SYSTIMER))
915 {
916 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
917 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
918 (TIMERPROC)0 );
919 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
920 }
921
922 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
923 {
924 SCROLL_DrawTopArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
925 SCROLL_lastHitTest = hittest;
926 }
927 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
928 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEUP,hwndCtl);
929
930 break;
931
932 case SCROLL_TOP_RECT:
933 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
934 KillSystemTimer(hwnd,SCROLL_TIMER);
935 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
936 {
937 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
938 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
939 (TIMERPROC)0 );
940 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
941 }
942
943 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
944 {
945 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
946 thumbPos, infoPtr->flags, vertical,
947 (hittest == SCROLL_trackHitTest), FALSE );
948 SCROLL_lastHitTest = hittest;
949 }
950
951 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
952 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEUP,hwndCtl);
953
954 break;
955
956 case SCROLL_THUMB:
957 if (msg == WM_LBUTTONDOWN)
958 {
959 SCROLL_TrackingWin = hwnd;
960 SCROLL_TrackingBar = nBar;
961 SCROLL_TrackingPos = trackThumbPos + lastMousePos - lastClickPos;
962 SCROLL_TrackingVal = infoPtr->CurVal;
963 SCROLL_MovingThumb = TRUE;
964 thumbTrackSent = FALSE;
965 SCROLL_DrawMovingThumb(hdc, &rect, vertical, arrowSize, thumbSize);
966 } else if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
967 {
968 UINT val;
969 INT oldPos = infoPtr->CurVal;
970
971 SCROLL_MovingThumb = FALSE;
972 SCROLL_TrackingWin = 0;
973 SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
974 val = SCROLL_GetThumbVal( infoPtr, &rect, vertical,
975 trackThumbPos + lastMousePos - lastClickPos );
976
977 if ((val != infoPtr->CurVal) || thumbTrackSent)
978 SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
979 MAKEWPARAM( SB_THUMBPOSITION, val ), hwndCtl );
980
981 if (oldPos == infoPtr->CurVal)
982 {
983 vertical = SCROLL_GetScrollBarRect( hwnd, nBar, &rect,
984 &arrowSize, &thumbSize, &thumbPos );
985 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
986 thumbPos, infoPtr->flags, vertical,
987 FALSE, FALSE );
988 }
989
990 ReleaseDC(hwnd,hdc);
991 return res;
992 } else if (msg == WM_MOUSEMOVE)
993 {
994 UINT pos;
995
996 if (!SCROLL_PtInRectEx( &rect, pt, vertical )) pos = lastClickPos;
997 else
998 {
999 pt = SCROLL_ClipPos( &rect, pt );
1000 pos = vertical ? pt.y:pt.x;
1001 }
1002 if (pos != lastMousePos)
1003 {
1004 lastMousePos = pos;
1005 SCROLL_TrackingPos = trackThumbPos + pos - lastClickPos;
1006 SCROLL_TrackingVal = SCROLL_GetThumbVal( infoPtr, &rect,
1007 vertical,
1008 SCROLL_TrackingPos );
1009 SCROLL_DrawMovingThumb( hdc, &rect, vertical,
1010 arrowSize, thumbSize );
1011 SendMessageA( hwndOwner, vertical ? WM_VSCROLL : WM_HSCROLL,
1012 MAKEWPARAM( SB_THUMBTRACK, SCROLL_TrackingVal),
1013 hwndCtl );
1014 thumbTrackSent = TRUE;
1015 }
1016 }
1017 break;
1018
1019 case SCROLL_BOTTOM_RECT:
1020 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
1021 KillSystemTimer(hwnd,SCROLL_TIMER);
1022 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
1023 {
1024 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
1025 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
1026 (TIMERPROC)0 );
1027 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
1028 }
1029
1030 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
1031 {
1032 SCROLL_DrawInterior( hwnd, hdc, nBar, &rect, arrowSize, thumbSize,
1033 thumbPos, infoPtr->flags, vertical,
1034 FALSE, (hittest == SCROLL_trackHitTest) );
1035 SCROLL_lastHitTest = hittest;
1036 }
1037
1038 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
1039 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_PAGEDOWN,hwndCtl);
1040
1041 break;
1042
1043 case SCROLL_BOTTOM_ARROW:
1044 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
1045 KillSystemTimer(hwnd,SCROLL_TIMER);
1046 else if ((msg == WM_LBUTTONDOWN) || (!timerRunning && (msg == WM_SYSTIMER)))
1047 {
1048 SetSystemTimer( hwnd, SCROLL_TIMER, (msg == WM_LBUTTONDOWN) ?
1049 SCROLL_FIRST_DELAY : SCROLL_REPEAT_DELAY,
1050 (TIMERPROC)0 );
1051 if (msg != WM_LBUTTONDOWN) timerRunning = TRUE;
1052 }
1053
1054 if ((msg == WM_LBUTTONDOWN) || (SCROLL_lastHitTest != hittest))
1055 {
1056 SCROLL_DrawBottomArrow(hdc,infoPtr,&rect,arrowSize,vertical,(hittest == SCROLL_trackHitTest));
1057 SCROLL_lastHitTest = hittest;
1058 }
1059 if ((hittest == SCROLL_trackHitTest) && ((msg == WM_LBUTTONDOWN) || (msg == WM_SYSTIMER)))
1060 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_LINEDOWN,hwndCtl);
1061
1062 break;
1063 }
1064
1065 if ((msg == WM_LBUTTONUP) || (msg == WM_CAPTURECHANGED))
1066 {
1067 SCROLL_trackHitTest = SCROLL_NOWHERE; /* Terminate tracking */
1068
1069 SendMessageA(hwndOwner,vertical ? WM_VSCROLL:WM_HSCROLL,SB_ENDSCROLL,hwndCtl);
1070 }
1071
1072 ReleaseDC( hwnd, hdc );
1073
1074 return res;
1075}
1076
1077/***********************************************************************
1078 * SCROLL_HandleKbdEvent
1079 *
1080 * Handle a keyboard event (only for SB_CTL scrollbars).
1081 */
1082LRESULT SCROLL_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
1083{
1084 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1085 UINT msg;
1086
1087 if (dwStyle & (SBS_SIZEBOX | SBS_SIZEGRIP)) return 0;
1088
1089 switch(wParam)
1090 {
1091 case VK_PRIOR: msg = SB_PAGEUP; break;
1092 case VK_NEXT: msg = SB_PAGEDOWN; break;
1093 case VK_HOME: msg = SB_TOP; break;
1094 case VK_END: msg = SB_BOTTOM; break;
1095 case VK_UP: msg = SB_LINEUP; break;
1096 case VK_DOWN: msg = SB_LINEDOWN; break;
1097 default:
1098 return 0;
1099 }
1100 SendMessageA( GetParent(hwnd),
1101 (dwStyle & SBS_VERT) ? WM_VSCROLL : WM_HSCROLL,
1102 msg, hwnd );
1103
1104 return 0;
1105}
1106
1107LRESULT SCROLL_Paint(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar)
1108{
1109 PAINTSTRUCT ps;
1110 HDC hdc = wParam ? (HDC)wParam:BeginPaint( hwnd, &ps );
1111
1112 SCROLL_DrawScrollBar( hwnd, hdc, nBar, TRUE, TRUE );
1113 if (!wParam) EndPaint( hwnd, &ps );
1114
1115 return 0;
1116}
1117
1118LRESULT SCROLL_SetRange(HWND hwnd,WPARAM wParam,LPARAM lParam,INT nBar,BOOL redraw)
1119{
1120 SCROLLBAR_INFO *infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1121 INT oldPos = infoPtr->CurVal;
1122
1123 SetScrollRange(hwnd,nBar,wParam,lParam,redraw);
1124 return (oldPos != infoPtr->CurVal) ? infoPtr->CurVal:0;
1125}
1126
1127/* Window Procedures */
1128
1129/***********************************************************************
1130 * ScrollBarWndProc
1131 */
1132LRESULT WINAPI ScrollBarWndProc( HWND hwnd, UINT message, WPARAM wParam,
1133 LPARAM lParam )
1134{
1135 switch(message)
1136 {
1137 case WM_NCCREATE:
1138 return SCROLL_NCCreate(hwnd,wParam,lParam);
1139
1140 case WM_CREATE:
1141 return SCROLL_Create(hwnd,wParam,lParam);
1142
1143 case WM_DESTROY:
1144 return SCROLL_Destroy(hwnd,wParam,lParam);
1145
1146 case WM_LBUTTONDOWN:
1147 case WM_LBUTTONUP:
1148 case WM_NCHITTEST:
1149 case WM_CAPTURECHANGED:
1150 case WM_MOUSEMOVE:
1151 case WM_SYSTIMER:
1152 case WM_SETFOCUS:
1153 case WM_KILLFOCUS:
1154 return SCROLL_HandleScrollEvent(hwnd,wParam,lParam,SB_CTL,message);
1155
1156 case WM_KEYDOWN:
1157 return SCROLL_KeyDown(hwnd,wParam,lParam);
1158
1159 case WM_ERASEBKGND:
1160 return 1;
1161
1162 case WM_GETDLGCODE:
1163 return DLGC_WANTARROWS; /* Windows returns this value */
1164
1165 case WM_PAINT:
1166 return SCROLL_Paint(hwnd,wParam,lParam,SB_CTL);
1167
1168 case SBM_SETPOS:
1169 return SetScrollPos( hwnd, SB_CTL, wParam, (BOOL)lParam );
1170
1171 case SBM_GETPOS:
1172 return GetScrollPos( hwnd, SB_CTL );
1173
1174 case SBM_SETRANGE:
1175 return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,FALSE);
1176
1177 case SBM_GETRANGE:
1178 GetScrollRange( hwnd, SB_CTL, (LPINT)wParam, (LPINT)lParam );
1179 return 0;
1180
1181 case SBM_ENABLE_ARROWS:
1182 return EnableScrollBar( hwnd, SB_CTL, wParam );
1183
1184 case SBM_SETRANGEREDRAW:
1185 return SCROLL_SetRange(hwnd,wParam,lParam,SB_CTL,TRUE);
1186
1187 case SBM_SETSCROLLINFO:
1188 return SetScrollInfo(hwnd,SB_CTL,(SCROLLINFO*)lParam,wParam);
1189
1190 case SBM_GETSCROLLINFO:
1191 return GetScrollInfo( hwnd, SB_CTL, (SCROLLINFO *)lParam );
1192
1193 case 0x00e5:
1194 case 0x00e7:
1195 case 0x00e8:
1196 case 0x00eb:
1197 case 0x00ec:
1198 case 0x00ed:
1199 case 0x00ee:
1200 case 0x00ef:
1201 //ERR("unknown Win32 msg %04x wp=%08x lp=%08lx\n",
1202 // message, wParam, lParam );
1203 break;
1204
1205 default:
1206 return DefWindowProcA( hwnd, message, wParam, lParam );
1207 }
1208
1209 return 0;
1210}
1211
1212/* Scrollbar API */
1213
1214/*************************************************************************
1215 * SetScrollInfo (USER32.501)
1216 * SetScrollInfo32 can be used to set the position, upper bound,
1217 * lower bound, and page size of a scrollbar control.
1218 *
1219 * RETURNS
1220 * Scrollbar position
1221 *
1222 * NOTE
1223 * For 100 lines of text to be displayed in a window of 25 lines,
1224 * one would for instance use info->nMin=0, info->nMax=75
1225 * (corresponding to the 76 different positions of the window on
1226 * the text), and info->nPage=25.
1227 */
1228INT WINAPI SetScrollInfo(HWND hwnd,INT nBar,const SCROLLINFO *info,BOOL bRedraw)
1229{
1230 /* Update the scrollbar state and set action flags according to
1231 * what has to be done graphics wise. */
1232
1233 SCROLLBAR_INFO *infoPtr;
1234 UINT new_flags;
1235 INT action = 0;
1236 BOOL bChangeParams = FALSE; /* don't show/hide scrollbar if params don't change */
1237
1238 dprintf(("USER32: SetScrollInfo %x %d",hwnd,nBar));
1239
1240 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
1241 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return 0;
1242 if ((info->cbSize != sizeof(*info)) &&
1243 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return 0;
1244
1245 /* Set the page size */
1246 if (info->fMask & SIF_PAGE)
1247 {
1248 if( infoPtr->Page != info->nPage )
1249 {
1250 infoPtr->Page = info->nPage;
1251 action |= SA_SSI_REPAINT_INTERIOR;
1252 bChangeParams = TRUE;
1253 }
1254 }
1255
1256 /* Set the scroll pos */
1257 if (info->fMask & SIF_POS)
1258 {
1259 //dsprintf(scroll, " pos=%d", info->nPos );
1260 if( infoPtr->CurVal != info->nPos )
1261 {
1262 infoPtr->CurVal = info->nPos;
1263 action |= SA_SSI_MOVE_THUMB;
1264 }
1265 }
1266
1267 /* Set the scroll range */
1268 if (info->fMask & SIF_RANGE)
1269 {
1270 /* Invalid range -> range is set to (0,0) */
1271 if ((info->nMin > info->nMax) ||
1272 ((UINT)(info->nMax - info->nMin) >= 0x80000000))
1273 {
1274 infoPtr->MinVal = 0;
1275 infoPtr->MaxVal = 0;
1276 bChangeParams = TRUE;
1277 }
1278 else
1279 {
1280 if( infoPtr->MinVal != info->nMin ||
1281 infoPtr->MaxVal != info->nMax )
1282 {
1283 action |= SA_SSI_REPAINT_INTERIOR;
1284 infoPtr->MinVal = info->nMin;
1285 infoPtr->MaxVal = info->nMax;
1286 bChangeParams = TRUE;
1287 }
1288 }
1289 }
1290
1291 /* Make sure the page size is valid */
1292
1293 if (infoPtr->Page < 0) infoPtr->Page = 0;
1294 else if (infoPtr->Page > infoPtr->MaxVal - infoPtr->MinVal + 1 )
1295 infoPtr->Page = infoPtr->MaxVal - infoPtr->MinVal + 1;
1296
1297 /* Make sure the pos is inside the range */
1298
1299 if (infoPtr->CurVal < infoPtr->MinVal)
1300 infoPtr->CurVal = infoPtr->MinVal;
1301 else if (infoPtr->CurVal > infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1302 infoPtr->CurVal = infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 );
1303
1304 //TRACE(" new values: page=%d pos=%d min=%d max=%d\n",
1305 // infoPtr->Page, infoPtr->CurVal,
1306 // infoPtr->MinVal, infoPtr->MaxVal );
1307
1308 /* don't change the scrollbar state if SetScrollInfo
1309 * is just called with SIF_DISABLENOSCROLL
1310 */
1311 if(!(info->fMask & SIF_ALL)) goto done;
1312
1313 /* Check if the scrollbar should be hidden or disabled */
1314 if (info->fMask & (SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL))
1315 {
1316 new_flags = infoPtr->flags;
1317 if (infoPtr->MinVal >= infoPtr->MaxVal - MAX( infoPtr->Page-1, 0 ))
1318 {
1319 /* Hide or disable scroll-bar */
1320 if (info->fMask & SIF_DISABLENOSCROLL)
1321 {
1322 new_flags = ESB_DISABLE_BOTH;
1323 action |= SA_SSI_REFRESH;
1324 }
1325 else
1326 if (nBar != SB_CTL && bChangeParams)
1327 {
1328 action = SA_SSI_HIDE;
1329 infoPtr->flags = 0;
1330 goto done;
1331 }
1332 }
1333 else /* Show and enable scroll-bar */
1334 {
1335 new_flags = 0;
1336 if (nBar != SB_CTL && bChangeParams) action |= SA_SSI_SHOW;
1337 if (infoPtr->flags) action |= SA_SSI_REFRESH;
1338 }
1339
1340 if (infoPtr->flags != new_flags) /* check arrow flags */
1341 {
1342 infoPtr->flags = new_flags;
1343 action |= SA_SSI_REPAINT_ARROWS;
1344 }
1345 }
1346
1347done:
1348 /* Update scrollbar */
1349
1350 if( action & SA_SSI_HIDE )
1351 ShowScrollBar(hwnd,nBar,FALSE);
1352 else
1353 {
1354 if(action & SA_SSI_SHOW)
1355 ShowScrollBar(hwnd,nBar,TRUE);
1356
1357 if (bRedraw)
1358 {
1359 if (action & SA_SSI_REFRESH)
1360 SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,TRUE);
1361 else
1362 {
1363 if (action & (SA_SSI_REPAINT_INTERIOR | SA_SSI_MOVE_THUMB))
1364 SCROLL_RefreshScrollBar(hwnd,nBar,FALSE,TRUE);
1365 if (action & SA_SSI_REPAINT_ARROWS)
1366 SCROLL_RefreshScrollBar(hwnd,nBar,TRUE,FALSE);
1367 }
1368 }
1369 }
1370
1371 /* Return current position */
1372
1373 return infoPtr->CurVal;
1374}
1375/*************************************************************************
1376 * GetScrollInfo (USER32.284)
1377 * GetScrollInfo32 can be used to retrieve the position, upper bound,
1378 * lower bound, and page size of a scrollbar control.
1379 *
1380 * RETURNS STD
1381 */
1382BOOL WINAPI GetScrollInfo(
1383 HWND hwnd /* [I] Handle of window */ ,
1384 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1385 LPSCROLLINFO info /* [IO] (info.fMask [I] specifies which values are to retrieve) */)
1386{
1387 SCROLLBAR_INFO *infoPtr;
1388
1389 dprintf(("USER32: GetScrollInfo"));
1390
1391 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return FALSE;
1392 if (info->fMask & ~(SIF_ALL | SIF_DISABLENOSCROLL)) return FALSE;
1393 if ((info->cbSize != sizeof(*info)) &&
1394 (info->cbSize != sizeof(*info)-sizeof(info->nTrackPos))) return FALSE;
1395
1396 if (info->fMask & SIF_PAGE) info->nPage = infoPtr->Page;
1397 if (info->fMask & SIF_POS) info->nPos = infoPtr->CurVal;
1398 if ((info->fMask & SIF_TRACKPOS) && (info->cbSize == sizeof(*info)))
1399 info->nTrackPos = (SCROLL_MovingThumb && SCROLL_TrackingWin == hwnd && SCROLL_TrackingBar == nBar) ? SCROLL_TrackingVal:infoPtr->CurVal;
1400
1401 if (info->fMask & SIF_RANGE)
1402 {
1403 info->nMin = infoPtr->MinVal;
1404 info->nMax = infoPtr->MaxVal;
1405 }
1406 return (info->fMask & SIF_ALL) != 0;
1407}
1408/*************************************************************************
1409 * SetScrollPos (USER32.502)
1410 *
1411 * RETURNS
1412 * Success: Scrollbar position
1413 * Failure: 0
1414 *
1415 * REMARKS
1416 * Note the ambiguity when 0 is returned. Use GetLastError
1417 * to make sure there was an error (and to know which one).
1418 */
1419INT WINAPI SetScrollPos(
1420 HWND hwnd /* [I] Handle of window whose scrollbar will be affected */,
1421 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */,
1422 INT nPos /* [I] New value */,
1423 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */ )
1424{
1425 SCROLLINFO info;
1426 SCROLLBAR_INFO *infoPtr;
1427 INT oldPos;
1428
1429 dprintf(("SetScrollPos %x %d %d %d", hwnd, nBar, nPos, bRedraw));
1430 if (!(infoPtr = SCROLL_GetInfoPtr(hwnd,nBar))) return 0;
1431 oldPos = infoPtr->CurVal;
1432 info.cbSize = sizeof(info);
1433 info.nPos = nPos;
1434 info.fMask = SIF_POS;
1435 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1436 return oldPos;
1437}
1438/*************************************************************************
1439 * GetScrollPos (USER32.285)
1440 *
1441 * RETURNS
1442 * Success: Current position
1443 * Failure: 0
1444 *
1445 * REMARKS
1446 * Note the ambiguity when 0 is returned. Use GetLastError
1447 * to make sure there was an error (and to know which one).
1448 */
1449INT WINAPI GetScrollPos(
1450 HWND hwnd, /* [I] Handle of window */
1451 INT nBar /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */)
1452{
1453 SCROLLBAR_INFO *infoPtr;
1454
1455 dprintf(("GetScrollPos %x %d", hwnd, nBar));
1456
1457 infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1458 if (!infoPtr) return 0;
1459
1460 return infoPtr->CurVal;
1461}
1462
1463/*************************************************************************
1464 * SetScrollRange (USER32.503)
1465 *
1466 * RETURNS STD
1467 */
1468BOOL WINAPI SetScrollRange(
1469 HWND hwnd, /* [I] Handle of window whose scrollbar will be affected */
1470 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1471 INT MinVal, /* [I] New minimum value */
1472 INT MaxVal, /* [I] New maximum value */
1473 BOOL bRedraw /* [I] Should scrollbar be redrawn afterwards ? */)
1474{
1475 SCROLLINFO info;
1476
1477 dprintf(("SetScrollRange %x %x %d %d %d", hwnd, nBar, MinVal, MaxVal, bRedraw));
1478 info.cbSize = sizeof(info);
1479 info.nMin = MinVal;
1480 info.nMax = MaxVal;
1481 info.fMask = SIF_RANGE;
1482 SetScrollInfo( hwnd, nBar, &info, bRedraw );
1483 return TRUE;
1484}
1485
1486/*************************************************************************
1487 * GetScrollRange (USER32.286)
1488 *
1489 * RETURNS STD
1490 */
1491BOOL WINAPI GetScrollRange(
1492 HWND hwnd, /* [I] Handle of window */
1493 INT nBar, /* [I] One of SB_HORZ, SB_VERT, or SB_CTL */
1494 LPINT lpMin, /* [O] Where to store minimum value */
1495 LPINT lpMax /* [O] Where to store maximum value */)
1496{
1497 SCROLLBAR_INFO *infoPtr;
1498
1499 infoPtr = SCROLL_GetInfoPtr(hwnd,nBar);
1500 if (!infoPtr)
1501 {
1502 if (lpMin) lpMin = 0;
1503 if (lpMax) lpMax = 0;
1504 return FALSE;
1505 }
1506 if (lpMin) *lpMin = infoPtr->MinVal;
1507 if (lpMax) *lpMax = infoPtr->MaxVal;
1508 return TRUE;
1509}
1510
1511/*************************************************************************
1512 * ShowScrollBar (USER32.532)
1513 *
1514 * RETURNS STD
1515 */
1516BOOL WINAPI ShowScrollBar(
1517 HWND hwnd, /* [I] Handle of window whose scrollbar(s) will be affected */
1518 INT nBar, /* [I] One of SB_HORZ, SB_VERT, SB_BOTH or SB_CTL */
1519 BOOL fShow /* [I] TRUE = show, FALSE = hide */)
1520{
1521 BOOL fShowH = (nBar == SB_HORZ) ? fShow : 0;
1522 BOOL fShowV = (nBar == SB_VERT) ? fShow : 0;
1523 DWORD dwStyle;
1524
1525 dprintf(("ShowScrollBar %04x %d %d\n", hwnd, nBar, fShow));
1526 if (!IsWindow(hwnd)) return FALSE;
1527
1528 dwStyle = GetWindowLongA(hwnd, GWL_STYLE);
1529
1530 //CB: does Win32 send a WM_STYLECHANGED message?
1531 switch(nBar)
1532 {
1533 case SB_CTL:
1534 ShowWindow(hwnd,fShow ? SW_SHOW:SW_HIDE);
1535 return TRUE;
1536
1537 case SB_BOTH:
1538 case SB_HORZ:
1539 if (fShow)
1540 {
1541 fShowH = !(dwStyle & WS_HSCROLL);
1542 SetWindowLongA(hwnd, GWL_STYLE, dwStyle | WS_HSCROLL);
1543 }
1544 else /* hide it */
1545 {
1546 fShowH = (dwStyle & WS_HSCROLL);
1547 SetWindowLongA(hwnd, GWL_STYLE, dwStyle & ~WS_HSCROLL);
1548 }
1549 if( nBar == SB_HORZ )
1550 {
1551 fShowV = FALSE;
1552 break;
1553 }
1554 /* fall through */
1555
1556 case SB_VERT:
1557 if (fShow)
1558 {
1559 fShowV = !(dwStyle & WS_VSCROLL);
1560 SetWindowLongA(hwnd, GWL_STYLE, dwStyle | WS_VSCROLL);
1561 }
1562 else /* hide it */
1563 {
1564 fShowV = (dwStyle & WS_VSCROLL);
1565 SetWindowLongA(hwnd, GWL_STYLE, dwStyle & ~WS_VSCROLL);
1566 }
1567 if ( nBar == SB_VERT )
1568 fShowH = FALSE;
1569 break;
1570
1571 default:
1572 return TRUE; /* Nothing to do! */
1573 }
1574
1575 if( fShowH || fShowV ) /* frame has been changed, let the window redraw itself */
1576 {
1577 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
1578 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
1579 }
1580
1581 return TRUE;
1582}
1583
1584/*************************************************************************
1585 * EnableScrollBar (USER32.171)
1586 */
1587BOOL WINAPI EnableScrollBar( HWND hwnd, INT nBar, UINT flags)
1588{
1589 BOOL bFineWithMe;
1590 SCROLLBAR_INFO *infoPtr;
1591
1592 dprintf(("EnableScrollBar %04x %d %d\n", hwnd, nBar, flags));
1593
1594 flags &= ESB_DISABLE_BOTH;
1595
1596 if (nBar == SB_BOTH)
1597 {
1598 if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, SB_VERT ))) return FALSE;
1599 if (!(bFineWithMe = (infoPtr->flags == flags)) )
1600 {
1601 infoPtr->flags = flags;
1602 SCROLL_RefreshScrollBar( hwnd, SB_VERT, TRUE, TRUE );
1603 }
1604 nBar = SB_HORZ;
1605 }
1606 else
1607 bFineWithMe = TRUE;
1608
1609 if (!(infoPtr = SCROLL_GetInfoPtr( hwnd, nBar ))) return FALSE;
1610 if (bFineWithMe && infoPtr->flags == flags) return FALSE;
1611 infoPtr->flags = flags;
1612
1613 SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1614 return TRUE;
1615}
1616
1617BOOL WINAPI GetScrollBarInfo(HWND hwnd,LONG idObject,PSCROLLBARINFO psbi)
1618{
1619 if (!psbi || (psbi->cbSize != sizeof(SCROLLBARINFO)))
1620 {
1621 SetLastError(ERROR_INVALID_PARAMETER);
1622
1623 return FALSE;
1624 }
1625
1626 INT nBar,arrowSize;
1627
1628 switch (idObject)
1629 {
1630 case OBJID_CLIENT:
1631 nBar = SB_CTL;
1632 break;
1633
1634 case OBJID_HSCROLL:
1635 nBar = SB_HORZ;
1636 break;
1637
1638 case OBJID_VSCROLL:
1639 nBar = SB_VERT;
1640 break;
1641
1642 default:
1643 return FALSE;
1644 }
1645
1646 SCROLL_GetScrollBarRect(hwnd,nBar,&psbi->rcScrollBar,&arrowSize,&psbi->dxyLineButton,&psbi->xyThumbTop);
1647 psbi->xyThumbBottom = psbi->xyThumbTop+psbi->dxyLineButton;
1648 psbi->bogus = 0; //CB: undocumented!
1649 psbi->rgstate[0] = IsWindowVisible(hwnd) ? STATE_SYSTEM_INVISIBLE:0;
1650 psbi->rgstate[1] = psbi->rgstate[2] = psbi->rgstate[3] = psbi->rgstate[4] = psbi->rgstate[5] = psbi->rgstate[0]; //CB: todo
1651
1652 return TRUE;
1653}
1654//******************************************************************************
1655//******************************************************************************
1656BOOL SCROLLBAR_Register()
1657{
1658 WNDCLASSA wndClass;
1659
1660//SvL: Don't check this now
1661// if (GlobalFindAtomA(SCROLLBARCLASSNAME)) return FALSE;
1662
1663 ZeroMemory(&wndClass,sizeof(WNDCLASSA));
1664 wndClass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW | CS_PARENTDC;
1665 wndClass.lpfnWndProc = (WNDPROC)ScrollBarWndProc;
1666 wndClass.cbClsExtra = 0;
1667 wndClass.cbWndExtra = sizeof(SCROLLBAR_INFO);
1668 wndClass.hCursor = LoadCursorA(0,IDC_ARROWA);
1669 wndClass.hbrBackground = (HBRUSH)0;
1670 wndClass.lpszClassName = SCROLLBARCLASSNAME;
1671
1672 return RegisterClassA(&wndClass);
1673}
1674//******************************************************************************
1675//******************************************************************************
1676BOOL SCROLLBAR_Unregister()
1677{
1678 if (GlobalFindAtomA(SCROLLBARCLASSNAME))
1679 return UnregisterClassA(SCROLLBARCLASSNAME,(HINSTANCE)NULL);
1680 else return FALSE;
1681}
1682//******************************************************************************
1683//******************************************************************************
1684
Note: See TracBrowser for help on using the repository browser.