2 * Interface code to SCROLLBAR widget
4 * Copyright Martin Ayotte, 1993
5 * Copyright Alexandre Julliard, 1994
7 * Small fixes and implemented SB_THUMBPOSITION
8 * by Peter Broadhurst, 940611
13 #include <sys/types.h>
17 #include "sysmetrics.h"
23 /* #define DEBUG_SCROLL */
27 static HBITMAP hUpArrow
= 0;
28 static HBITMAP hDnArrow
= 0;
29 static HBITMAP hLfArrow
= 0;
30 static HBITMAP hRgArrow
= 0;
31 static HBITMAP hUpArrowD
= 0;
32 static HBITMAP hDnArrowD
= 0;
33 static HBITMAP hLfArrowD
= 0;
34 static HBITMAP hRgArrowD
= 0;
35 static HBITMAP hUpArrowI
= 0;
36 static HBITMAP hDnArrowI
= 0;
37 static HBITMAP hLfArrowI
= 0;
38 static HBITMAP hRgArrowI
= 0;
40 #define TOP_ARROW(flags,pressed) \
41 (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
42 #define BOTTOM_ARROW(flags,pressed) \
43 (((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
44 #define LEFT_ARROW(flags,pressed) \
45 (((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
46 #define RIGHT_ARROW(flags,pressed) \
47 (((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
50 /* Minimum size of the rectangle between the arrows */
51 #define SCROLL_MIN_RECT 4
53 /* Delay (in ms) before first repetition when holding the button down */
54 #define SCROLL_FIRST_DELAY 200
56 /* Delay (in ms) between scroll repetitions */
57 #define SCROLL_REPEAT_DELAY 100
60 #define SCROLL_TIMER 0
62 /* Scroll-bar hit testing */
65 SCROLL_NOWHERE
, /* Outside the scroll bar */
66 SCROLL_TOP_ARROW
, /* Top or left arrow */
67 SCROLL_TOP_RECT
, /* Rectangle between the top arrow and the thumb */
68 SCROLL_THUMB
, /* Thumb rectangle */
69 SCROLL_BOTTOM_RECT
, /* Rectangle between the thumb and the bottom arrow */
70 SCROLL_BOTTOM_ARROW
/* Bottom or right arrow */
74 /***********************************************************************
77 static void SCROLL_LoadBitmaps(void)
79 hUpArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROW
));
80 hDnArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROW
));
81 hLfArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROW
));
82 hRgArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROW
));
83 hUpArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWD
));
84 hDnArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWD
));
85 hLfArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWD
));
86 hRgArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWD
));
87 hUpArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWI
));
88 hDnArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWI
));
89 hLfArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWI
));
90 hRgArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWI
));
94 /***********************************************************************
95 * SCROLL_GetScrollInfo
97 static SCROLLINFO
*SCROLL_GetScrollInfo( HWND hwnd
, int nBar
)
100 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
102 if (!wndPtr
) return NULL
;
105 case SB_HORZ
: handle
= wndPtr
->hHScroll
; break;
106 case SB_VERT
: handle
= wndPtr
->hVScroll
; break;
107 case SB_CTL
: return (SCROLLINFO
*)wndPtr
->wExtra
;
108 default: return NULL
;
111 if (!handle
) /* Create the info structure if needed */
113 if ((handle
= USER_HEAP_ALLOC( sizeof(SCROLLINFO
) )))
115 SCROLLINFO
*infoPtr
= (SCROLLINFO
*) USER_HEAP_LIN_ADDR( handle
);
116 infoPtr
->MinVal
= infoPtr
->CurVal
= 0;
117 infoPtr
->MaxVal
= 100;
118 infoPtr
->flags
= ESB_ENABLE_BOTH
;
119 if (nBar
== SB_HORZ
) wndPtr
->hHScroll
= handle
;
120 else wndPtr
->hVScroll
= handle
;
122 if (!hUpArrow
) SCROLL_LoadBitmaps();
124 return (SCROLLINFO
*) USER_HEAP_LIN_ADDR( handle
);
128 /***********************************************************************
129 * SCROLL_GetScrollBarRect
131 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
132 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
133 * 'arrowSize' returns the width or height of an arrow (depending on the
134 * orientation of the scrollbar), and 'thumbPos' returns the position of
135 * the thumb relative to the left or to the top.
136 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
138 static BOOL
SCROLL_GetScrollBarRect( HWND hwnd
, int nBar
, RECT
*lprect
,
139 WORD
*arrowSize
, WORD
*thumbPos
)
143 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
148 lprect
->left
= wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
- 1;
149 lprect
->top
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
;
150 lprect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
+1;
151 lprect
->bottom
= lprect
->top
+ SYSMETRICS_CYHSCROLL
+ 1;
156 lprect
->left
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
;
157 lprect
->top
= wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
- 1;
158 lprect
->right
= lprect
->left
+ SYSMETRICS_CXVSCROLL
+ 1;
159 lprect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
+1;
164 GetClientRect( hwnd
, lprect
);
165 vertical
= ((wndPtr
->dwStyle
& SBS_VERT
) != 0);
172 if (vertical
) pixels
= lprect
->bottom
- lprect
->top
;
173 else pixels
= lprect
->right
- lprect
->left
;
175 if (pixels
> 2*SYSMETRICS_CXVSCROLL
+ SCROLL_MIN_RECT
)
177 *arrowSize
= SYSMETRICS_CXVSCROLL
;
179 else if (pixels
> SCROLL_MIN_RECT
)
181 *arrowSize
= (pixels
- SCROLL_MIN_RECT
) / 2;
185 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) > 0)
187 SCROLLINFO
*info
= SCROLL_GetScrollInfo( hwnd
, nBar
);
188 if ((info
->flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
190 else if (info
->MinVal
== info
->MaxVal
)
191 *thumbPos
= *arrowSize
;
193 *thumbPos
= *arrowSize
+ pixels
* (info
->CurVal
- info
->MinVal
) /
194 (info
->MaxVal
- info
->MinVal
);
201 /***********************************************************************
204 * Compute the current scroll position based on the thumb position in pixels
205 * from the top of the scroll-bar.
207 static UINT
SCROLL_GetThumbVal( SCROLLINFO
*infoPtr
, RECT
*rect
,
208 BOOL vertical
, WORD pos
)
210 int pixels
= vertical
? rect
->bottom
-rect
->top
: rect
->right
-rect
->left
;
211 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) <= 0) return infoPtr
->MinVal
;
212 pos
= MAX( 0, pos
- SYSMETRICS_CXVSCROLL
);
213 if (pos
> pixels
) pos
= pixels
;
214 dprintf_scroll(stddeb
,"GetThumbVal: pos=%d ret=%d\n", pos
,
216 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
218 return (infoPtr
->MinVal
219 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
224 /***********************************************************************
227 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
229 static enum SCROLL_HITTEST
SCROLL_HitTest( HWND hwnd
, int nBar
, POINT pt
)
231 WORD arrowSize
, thumbPos
;
234 BOOL vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
235 &arrowSize
, &thumbPos
);
236 if (!PtInRect( &rect
, pt
)) return SCROLL_NOWHERE
;
240 if (pt
.y
<= rect
.top
+ arrowSize
+ 1) return SCROLL_TOP_ARROW
;
241 if (pt
.y
>= rect
.bottom
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
242 if (!thumbPos
) return SCROLL_TOP_RECT
;
244 if (pt
.y
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
245 if (pt
.y
> thumbPos
+SYSMETRICS_CYHSCROLL
) return SCROLL_BOTTOM_RECT
;
248 else /* horizontal */
250 if (pt
.x
<= rect
.left
+ arrowSize
) return SCROLL_TOP_ARROW
;
251 if (pt
.x
>= rect
.right
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
252 if (!thumbPos
) return SCROLL_TOP_RECT
;
254 if (pt
.x
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
255 if (pt
.x
> thumbPos
+SYSMETRICS_CXVSCROLL
) return SCROLL_BOTTOM_RECT
;
261 /***********************************************************************
264 * Draw the scroll bar arrows.
266 static void SCROLL_DrawArrows( HDC hdc
, SCROLLINFO
*infoPtr
, RECT
*rect
,
267 WORD arrowSize
, BOOL vertical
,
268 BOOL top_pressed
, BOOL bottom_pressed
)
270 HDC hdcMem
= CreateCompatibleDC( hdc
);
271 HBITMAP hbmpPrev
= SelectObject( hdcMem
, vertical
?
272 TOP_ARROW(infoPtr
->flags
, top_pressed
)
273 : LEFT_ARROW(infoPtr
->flags
, top_pressed
));
274 SetStretchBltMode( hdc
, STRETCH_DELETESCANS
);
275 StretchBlt( hdc
, rect
->left
, rect
->top
,
276 vertical
? rect
->right
-rect
->left
: arrowSize
+1,
277 vertical
? arrowSize
+1 : rect
->bottom
-rect
->top
,
279 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
282 SelectObject( hdcMem
, vertical
?
283 BOTTOM_ARROW( infoPtr
->flags
, bottom_pressed
)
284 : RIGHT_ARROW( infoPtr
->flags
, bottom_pressed
) );
286 StretchBlt( hdc
, rect
->left
, rect
->bottom
- arrowSize
- 1,
287 rect
->right
- rect
->left
, arrowSize
+ 1,
289 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
292 StretchBlt( hdc
, rect
->right
- arrowSize
- 1, rect
->top
,
293 arrowSize
+ 1, rect
->bottom
- rect
->top
,
295 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
297 SelectObject( hdcMem
, hbmpPrev
);
302 /***********************************************************************
303 * SCROLL_DrawMovingThumb
305 * Draw the moving thumb rectangle.
307 static void SCROLL_DrawMovingThumb( HDC hdc
, RECT
*rect
, BOOL vertical
,
308 WORD arrowSize
, WORD thumbPos
)
314 if (r
.top
< rect
->top
+ arrowSize
) r
.top
= rect
->top
+ arrowSize
;
315 if (r
.top
+ SYSMETRICS_CYHSCROLL
>= rect
->bottom
- arrowSize
)
316 r
.top
= rect
->bottom
- arrowSize
- SYSMETRICS_CYHSCROLL
- 1;
317 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
322 if (r
.left
< rect
->left
+ arrowSize
) r
.left
= rect
->left
+ arrowSize
;
323 if (r
.left
+ SYSMETRICS_CXVSCROLL
>= rect
->right
- arrowSize
)
324 r
.left
= rect
->right
- arrowSize
- SYSMETRICS_CXVSCROLL
- 1;
325 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
327 InflateRect( &r
, -1, -1 );
328 DrawFocusRect( hdc
, &r
);
332 /***********************************************************************
333 * SCROLL_DrawInterior
335 * Draw the scroll bar interior (everything except the arrows).
337 static void SCROLL_DrawInterior( HWND hwnd
, HDC hdc
, int nBar
, RECT
*rect
,
338 WORD arrowSize
, WORD thumbPos
, WORD flags
,
339 BOOL vertical
, BOOL top_selected
,
340 BOOL bottom_selected
)
344 /* Select the correct brush and pen */
346 SelectObject( hdc
, sysColorObjects
.hpenWindowFrame
);
347 if ((flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
349 /* This ought to be the color of the parent window */
350 SelectObject( hdc
, sysColorObjects
.hbrushWindow
);
354 if (nBar
== SB_CTL
) /* Only scrollbar controls send WM_CTLCOLOR */
357 HBRUSH hbrush
= (HBRUSH
)SendMessage( GetParent(hwnd
),
358 WM_CTLCOLORSCROLLBAR
,
359 (WPARAM
)hdc
, (LPARAM
)hwnd
);
361 HBRUSH hbrush
= SendMessage( GetParent(hwnd
), WM_CTLCOLOR
, hdc
,
362 MAKELONG(hwnd
, CTLCOLOR_SCROLLBAR
) );
364 SelectObject( hdc
, hbrush
);
366 else SelectObject( hdc
, sysColorObjects
.hbrushScrollbar
);
369 /* Calculate the scroll rectangle */
375 r
.bottom
-= arrowSize
;
380 r
.right
-= arrowSize
;
383 /* Draw the scroll bar frame */
385 MoveTo( hdc
, r
.left
, r
.top
);
386 LineTo( hdc
, r
.right
-1, r
.top
);
387 LineTo( hdc
, r
.right
-1, r
.bottom
-1 );
388 LineTo( hdc
, r
.left
, r
.bottom
-1 );
389 LineTo( hdc
, r
.left
, r
.top
);
391 /* Draw the scroll rectangles and thumb */
393 if (!thumbPos
) /* No thumb to draw */
395 PatBlt( hdc
, r
.left
+1, r
.top
+1, r
.right
- r
.left
- 2,
396 r
.bottom
- r
.top
- 2, PATCOPY
);
402 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
403 r
.right
- r
.left
- 2,
404 thumbPos
- arrowSize
,
405 top_selected
? 0x0f0000 : PATCOPY
);
406 r
.top
+= thumbPos
- arrowSize
;
407 PatBlt( hdc
, r
.left
+ 1, r
.top
+ SYSMETRICS_CYHSCROLL
+ 1,
408 r
.right
- r
.left
- 2,
409 r
.bottom
- r
.top
- SYSMETRICS_CYHSCROLL
- 2,
410 bottom_selected
? 0x0f0000 : PATCOPY
);
411 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
413 else /* horizontal */
415 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
416 thumbPos
- arrowSize
,
417 r
.bottom
- r
.top
- 2,
418 top_selected
? 0x0f0000 : PATCOPY
);
419 r
.left
+= thumbPos
- arrowSize
;
420 PatBlt( hdc
, r
.left
+ SYSMETRICS_CYHSCROLL
+ 1, r
.top
+ 1,
421 r
.right
- r
.left
- SYSMETRICS_CYHSCROLL
- 2,
422 r
.bottom
- r
.top
- 2,
423 bottom_selected
? 0x0f0000 : PATCOPY
);
424 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
429 SelectObject( hdc
, sysColorObjects
.hbrushBtnFace
);
430 Rectangle( hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
431 InflateRect( &r
, -1, -1 );
432 GRAPH_DrawReliefRect( hdc
, &r
, 1, 2, FALSE
);
436 /***********************************************************************
437 * SCROLL_DrawScrollBar
439 * Redraw the whole scrollbar.
441 void SCROLL_DrawScrollBar( HWND hwnd
, HDC hdc
, int nBar
)
443 WORD arrowSize
, thumbPos
;
446 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
447 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
449 if (!wndPtr
|| !infoPtr
||
450 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
451 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
453 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
454 &arrowSize
, &thumbPos
);
455 /* Draw the arrows */
457 if (arrowSize
) SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
,
458 vertical
, FALSE
, FALSE
);
460 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
461 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
465 /***********************************************************************
466 * SCROLL_RefreshScrollBar
468 * Repaint the scroll bar interior after a SetScrollRange() or
469 * SetScrollPos() call.
471 static void SCROLL_RefreshScrollBar( HWND hwnd
, int nBar
)
473 WORD arrowSize
, thumbPos
;
477 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
478 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
480 if (!wndPtr
|| !infoPtr
||
481 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
482 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
484 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
485 &arrowSize
, &thumbPos
);
486 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
488 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
489 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
490 ReleaseDC( hwnd
, hdc
);
494 /***********************************************************************
495 * SCROLL_HandleKbdEvent
497 * Handle a keyboard event (only for SB_CTL scrollbars).
499 static void SCROLL_HandleKbdEvent( HWND hwnd
, WORD wParam
)
501 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
506 case VK_PRIOR
: msg
= SB_PAGEUP
; break;
507 case VK_NEXT
: msg
= SB_PAGEDOWN
; break;
508 case VK_HOME
: msg
= SB_TOP
; break;
509 case VK_END
: msg
= SB_BOTTOM
; break;
510 case VK_UP
: msg
= SB_LINEUP
; break;
511 case VK_DOWN
: msg
= SB_LINEDOWN
; break;
516 SendMessage( GetParent(hwnd
),
517 (wndPtr
->dwStyle
& SBS_VERT
) ? WM_VSCROLL
: WM_HSCROLL
,
518 (WPARAM
)msg
, (LPARAM
)hwnd
);
520 SendMessage( GetParent(hwnd
),
521 (wndPtr
->dwStyle
& SBS_VERT
) ? WM_VSCROLL
: WM_HSCROLL
,
522 msg
, MAKELONG( 0, hwnd
));
527 /***********************************************************************
528 * SCROLL_HandleScrollEvent
530 * Handle a mouse or timer event for the scrollbar.
531 * 'pt' is the location of the mouse event in client (for SB_CTL) or
532 * windows coordinates.
534 void SCROLL_HandleScrollEvent( HWND hwnd
, int nBar
, WORD msg
, POINT pt
)
536 /* Previous mouse position for timer events */
538 /* Hit test code of the last button-down event */
539 static enum SCROLL_HITTEST trackHitTest
;
540 /* Thumb position when tracking started. */
541 static UINT trackThumbPos
;
542 /* Position in the scroll-bar of the last button-down event. */
543 static int lastClickPos
;
544 /* Position in the scroll-bar of the last mouse event. */
545 static int lastMousePos
;
547 enum SCROLL_HITTEST hittest
;
548 HWND hwndOwner
, hwndCtl
;
550 WORD arrowSize
, thumbPos
;
554 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
555 if (!infoPtr
) return;
556 if ((trackHitTest
== SCROLL_NOWHERE
) && (msg
!= WM_LBUTTONDOWN
)) return;
558 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
559 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
560 &arrowSize
, &thumbPos
);
561 hwndOwner
= (nBar
== SB_CTL
) ? GetParent(hwnd
) : hwnd
;
562 hwndCtl
= (nBar
== SB_CTL
) ? hwnd
: 0;
566 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
567 trackHitTest
= hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
568 lastClickPos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
569 lastMousePos
= lastClickPos
;
570 trackThumbPos
= thumbPos
;
573 if (nBar
== SB_CTL
) SetFocus( hwnd
);
577 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
582 hittest
= SCROLL_NOWHERE
;
588 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
592 return; /* Should never happen */
595 dprintf_scroll( stddeb
, "ScrollBar Event: hwnd="NPFMT
" bar=%d msg=%x pt=%ld,%ld hit=%d\n",
596 hwnd
, nBar
, msg
, (LONG
)pt
.x
, (LONG
)pt
.y
, hittest
);
600 case SCROLL_NOWHERE
: /* No tracking in progress */
603 case SCROLL_TOP_ARROW
:
604 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
605 (hittest
== trackHitTest
), FALSE
);
606 if (hittest
== trackHitTest
)
608 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
610 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
611 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
614 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
615 (WPARAM
)SB_LINEUP
, (LPARAM
)hwndCtl
);
617 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
618 SB_LINEUP
, MAKELONG( 0, hwndCtl
));
622 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
625 case SCROLL_TOP_RECT
:
626 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
627 infoPtr
->flags
, vertical
,
628 (hittest
== trackHitTest
), FALSE
);
629 if (hittest
== trackHitTest
)
631 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
633 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
634 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
637 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
638 (WPARAM
)SB_PAGEUP
, (LPARAM
)hwndCtl
);
640 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
641 SB_PAGEUP
, MAKELONG( 0, hwndCtl
));
645 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
649 if (msg
== WM_LBUTTONDOWN
)
650 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
651 trackThumbPos
+ lastMousePos
- lastClickPos
);
652 else if (msg
== WM_LBUTTONUP
)
653 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
654 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
655 else /* WM_MOUSEMOVE */
659 if (!PtInRect( &rect
, pt
)) pos
= lastClickPos
;
660 else pos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
661 if (pos
!= lastMousePos
)
663 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
664 trackThumbPos
+ lastMousePos
- lastClickPos
);
665 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
666 trackThumbPos
+ pos
- lastClickPos
);
668 val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
669 trackThumbPos
+ lastMousePos
- lastClickPos
);
671 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
672 MAKEWPARAM(SB_THUMBTRACK
,val
), (LPARAM
)hwndCtl
);
674 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
675 SB_THUMBTRACK
, MAKELONG( val
, hwndCtl
));
681 case SCROLL_BOTTOM_RECT
:
682 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
683 infoPtr
->flags
, vertical
,
684 FALSE
, (hittest
== trackHitTest
) );
685 if (hittest
== trackHitTest
)
687 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
689 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
690 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
693 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
694 (WPARAM
)SB_PAGEDOWN
, (LPARAM
)hwndCtl
);
696 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
697 SB_PAGEDOWN
, MAKELONG( 0, hwndCtl
));
701 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
704 case SCROLL_BOTTOM_ARROW
:
705 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
706 FALSE
, (hittest
== trackHitTest
) );
707 if (hittest
== trackHitTest
)
709 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
711 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
712 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
715 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
716 (WPARAM
)SB_LINEDOWN
, (LPARAM
)hwndCtl
);
718 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
719 SB_LINEDOWN
, MAKELONG( 0, hwndCtl
));
723 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
727 if (msg
== WM_LBUTTONUP
)
729 if (trackHitTest
== SCROLL_THUMB
)
731 UINT val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
732 trackThumbPos
+ lastMousePos
- lastClickPos
);
734 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
735 MAKEWPARAM(SB_THUMBPOSITION
,val
), (LPARAM
)hwndCtl
);
737 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
738 SB_THUMBPOSITION
, MAKELONG( val
, hwndCtl
) );
743 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
744 (WPARAM
)SB_ENDSCROLL
, (LPARAM
)hwndCtl
);
746 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
747 SB_ENDSCROLL
, MAKELONG( 0, hwndCtl
) );
749 trackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
752 ReleaseDC( hwnd
, hdc
);
756 /***********************************************************************
759 LONG
ScrollBarWndProc( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
762 Pt
.x
= LOWORD(lParam
); Pt
.y
= HIWORD(lParam
);
763 /* ^ Can't use MAKEPOINT macro in WINELIB32 */
769 CREATESTRUCT
*lpCreat
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
770 if (lpCreat
->style
& SBS_SIZEBOX
)
772 fprintf( stdnimp
, "Unimplemented style SBS_SIZEBOX.\n" );
773 return 0; /* FIXME */
776 if (lpCreat
->style
& SBS_VERT
)
778 if (lpCreat
->style
& SBS_LEFTALIGN
)
779 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
780 SYSMETRICS_CXVSCROLL
+1, lpCreat
->cy
, FALSE
);
781 else if (lpCreat
->style
& SBS_RIGHTALIGN
)
783 lpCreat
->x
+lpCreat
->cx
-SYSMETRICS_CXVSCROLL
-1,
785 SYSMETRICS_CXVSCROLL
+ 1, lpCreat
->cy
, FALSE
);
789 if (lpCreat
->style
& SBS_TOPALIGN
)
790 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
791 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
792 else if (lpCreat
->style
& SBS_BOTTOMALIGN
)
795 lpCreat
->y
+lpCreat
->cy
-SYSMETRICS_CYHSCROLL
-1,
796 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
799 if (!hUpArrow
) SCROLL_LoadBitmaps();
800 dprintf_scroll( stddeb
, "ScrollBar creation, hwnd="NPFMT
"\n", hwnd
);
807 SCROLL_HandleScrollEvent( hwnd
, SB_CTL
, message
, Pt
);
811 SCROLL_HandleKbdEvent( hwnd
, wParam
);
820 HDC hdc
= BeginPaint( hwnd
, &ps
);
821 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_CTL
);
822 EndPaint( hwnd
, &ps
);
827 return DefWindowProc( hwnd
, message
, wParam
, lParam
);
833 /*************************************************************************
834 * SetScrollPos (USER.62)
836 int SetScrollPos( HWND hwnd
, int nBar
, int nPos
, BOOL bRedraw
)
841 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
843 dprintf_scroll( stddeb
,"SetScrollPos min=%d max=%d pos=%d\n",
844 infoPtr
->MinVal
, infoPtr
->MaxVal
, nPos
);
846 if (nPos
< infoPtr
->MinVal
) nPos
= infoPtr
->MinVal
;
847 else if (nPos
> infoPtr
->MaxVal
) nPos
= infoPtr
->MaxVal
;
848 oldPos
= infoPtr
->CurVal
;
849 infoPtr
->CurVal
= nPos
;
850 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
855 /*************************************************************************
856 * GetScrollPos (USER.63)
858 int GetScrollPos( HWND hwnd
, int nBar
)
862 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
863 return infoPtr
->CurVal
;
867 /*************************************************************************
868 * SetScrollRange (USER.64)
870 void SetScrollRange(HWND hwnd
, int nBar
, int MinVal
, int MaxVal
, BOOL bRedraw
)
874 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
876 dprintf_scroll( stddeb
,"SetScrollRange hwnd="NPFMT
" bar=%d min=%d max=%d\n",
877 hwnd
, nBar
, MinVal
, MaxVal
);
879 /* Invalid range -> range is set to (0,0) */
880 if ((MinVal
> MaxVal
) || ((long)MaxVal
- MinVal
> 32767L))
882 if (infoPtr
->CurVal
< MinVal
) infoPtr
->CurVal
= MinVal
;
883 else if (infoPtr
->CurVal
> MaxVal
) infoPtr
->CurVal
= MaxVal
;
884 infoPtr
->MinVal
= MinVal
;
885 infoPtr
->MaxVal
= MaxVal
;
887 /* Non-client scroll-bar is hidden if min==max */
888 if (nBar
!= SB_CTL
) ShowScrollBar( hwnd
, nBar
, (MinVal
!= MaxVal
) );
889 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
893 /*************************************************************************
894 * GetScrollRange (USER.65)
896 void GetScrollRange(HWND hwnd
, int nBar
, LPINT lpMin
, LPINT lpMax
)
900 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
901 if (lpMin
) *lpMin
= infoPtr
->MinVal
;
902 if (lpMax
) *lpMax
= infoPtr
->MaxVal
;
906 /*************************************************************************
907 * ShowScrollBar (USER.267)
909 void ShowScrollBar( HWND hwnd
, WORD wBar
, BOOL fShow
)
911 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
914 dprintf_scroll( stddeb
, "ShowScrollBar: hwnd="NPFMT
" bar=%d on=%d\n", hwnd
, wBar
, fShow
);
919 ShowWindow( hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
925 if (wndPtr
->dwStyle
& WS_HSCROLL
) return;
926 wndPtr
->dwStyle
|= WS_HSCROLL
;
930 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
931 wndPtr
->dwStyle
&= ~WS_HSCROLL
;
938 if (wndPtr
->dwStyle
& WS_VSCROLL
) return;
939 wndPtr
->dwStyle
|= WS_VSCROLL
;
943 if (!(wndPtr
->dwStyle
& WS_VSCROLL
)) return;
944 wndPtr
->dwStyle
&= ~WS_VSCROLL
;
951 if ((wndPtr
->dwStyle
& WS_HSCROLL
)
952 && (wndPtr
->dwStyle
& WS_VSCROLL
)) return;
953 wndPtr
->dwStyle
|= WS_HSCROLL
| WS_VSCROLL
;
957 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)
958 && !(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
959 wndPtr
->dwStyle
&= ~(WS_HSCROLL
| WS_VSCROLL
);
964 return; /* Nothing to do! */
966 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
967 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
971 /*************************************************************************
972 * EnableScrollBar (USER.482)
974 BOOL
EnableScrollBar( HWND hwnd
, INT nBar
, UINT flags
)
979 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return FALSE
;
980 dprintf_scroll( stddeb
, "EnableScrollBar: "NPFMT
" %d %d\n", hwnd
, nBar
, flags
);
981 flags
&= ESB_DISABLE_BOTH
;
982 if (infoPtr
->flags
== flags
) return FALSE
;
983 infoPtr
->flags
= flags
;
985 /* Redraw the whole scroll bar */
986 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
987 SCROLL_DrawScrollBar( hwnd
, hdc
, nBar
);
988 ReleaseDC( hwnd
, hdc
);