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"
26 static HBITMAP hUpArrow
= 0;
27 static HBITMAP hDnArrow
= 0;
28 static HBITMAP hLfArrow
= 0;
29 static HBITMAP hRgArrow
= 0;
30 static HBITMAP hUpArrowD
= 0;
31 static HBITMAP hDnArrowD
= 0;
32 static HBITMAP hLfArrowD
= 0;
33 static HBITMAP hRgArrowD
= 0;
34 static HBITMAP hUpArrowI
= 0;
35 static HBITMAP hDnArrowI
= 0;
36 static HBITMAP hLfArrowI
= 0;
37 static HBITMAP hRgArrowI
= 0;
39 #define TOP_ARROW(flags,pressed) \
40 (((flags)&ESB_DISABLE_UP) ? hUpArrowI : ((pressed) ? hUpArrowD:hUpArrow))
41 #define BOTTOM_ARROW(flags,pressed) \
42 (((flags)&ESB_DISABLE_DOWN) ? hDnArrowI : ((pressed) ? hDnArrowD:hDnArrow))
43 #define LEFT_ARROW(flags,pressed) \
44 (((flags)&ESB_DISABLE_LEFT) ? hLfArrowI : ((pressed) ? hLfArrowD:hLfArrow))
45 #define RIGHT_ARROW(flags,pressed) \
46 (((flags)&ESB_DISABLE_RIGHT) ? hRgArrowI : ((pressed) ? hRgArrowD:hRgArrow))
49 /* Minimum size of the rectangle between the arrows */
50 #define SCROLL_MIN_RECT 4
52 /* Delay (in ms) before first repetition when holding the button down */
53 #define SCROLL_FIRST_DELAY 200
55 /* Delay (in ms) between scroll repetitions */
56 #define SCROLL_REPEAT_DELAY 100
59 #define SCROLL_TIMER 0
61 /* Scroll-bar hit testing */
64 SCROLL_NOWHERE
, /* Outside the scroll bar */
65 SCROLL_TOP_ARROW
, /* Top or left arrow */
66 SCROLL_TOP_RECT
, /* Rectangle between the top arrow and the thumb */
67 SCROLL_THUMB
, /* Thumb rectangle */
68 SCROLL_BOTTOM_RECT
, /* Rectangle between the thumb and the bottom arrow */
69 SCROLL_BOTTOM_ARROW
/* Bottom or right arrow */
72 /* Thumb-tracking info */
73 static HWND hwndTracking
= 0;
74 static int nBarTracking
= 0;
75 static UINT uTrackingPos
= 0;
77 /***********************************************************************
80 static void SCROLL_LoadBitmaps(void)
82 hUpArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROW
));
83 hDnArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROW
));
84 hLfArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROW
));
85 hRgArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROW
));
86 hUpArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWD
));
87 hDnArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWD
));
88 hLfArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWD
));
89 hRgArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWD
));
90 hUpArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWI
));
91 hDnArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWI
));
92 hLfArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWI
));
93 hRgArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWI
));
97 /***********************************************************************
98 * SCROLL_GetPtrScrollInfo
100 static SCROLLINFO
*SCROLL_GetPtrScrollInfo( WND
* wndPtr
, int nBar
)
104 if (!wndPtr
) return NULL
;
107 case SB_HORZ
: infoPtr
= (SCROLLINFO
*)wndPtr
->pHScroll
; break;
108 case SB_VERT
: infoPtr
= (SCROLLINFO
*)wndPtr
->pVScroll
; break;
109 case SB_CTL
: infoPtr
= (SCROLLINFO
*)wndPtr
->wExtra
; break;
110 default: return NULL
;
113 if (!infoPtr
) /* Create the info structure if needed */
115 if ((infoPtr
= HeapAlloc( SystemHeap
, 0, sizeof(SCROLLINFO
) )))
117 infoPtr
->MinVal
= infoPtr
->CurVal
= 0;
118 infoPtr
->MaxVal
= 100;
119 infoPtr
->flags
= ESB_ENABLE_BOTH
;
120 if (nBar
== SB_HORZ
) wndPtr
->pHScroll
= infoPtr
;
121 else wndPtr
->pVScroll
= infoPtr
;
123 if (!hUpArrow
) SCROLL_LoadBitmaps();
129 /***********************************************************************
130 * SCROLL_GetScrollInfo
132 static SCROLLINFO
*SCROLL_GetScrollInfo( HWND hwnd
, int nBar
)
134 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
135 return SCROLL_GetPtrScrollInfo( wndPtr
, nBar
);
139 /***********************************************************************
140 * SCROLL_GetScrollBarRect
142 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
143 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
144 * 'arrowSize' returns the width or height of an arrow (depending on the
145 * orientation of the scrollbar), and 'thumbPos' returns the position of
146 * the thumb relative to the left or to the top.
147 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
149 static BOOL
SCROLL_GetScrollBarRect( HWND hwnd
, int nBar
, RECT16
*lprect
,
150 WORD
*arrowSize
, WORD
*thumbPos
)
154 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
159 lprect
->left
= wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
- 1;
160 lprect
->top
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
;
161 lprect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
+1;
162 lprect
->bottom
= lprect
->top
+ SYSMETRICS_CYHSCROLL
+ 1;
167 lprect
->left
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
;
168 lprect
->top
= wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
- 1;
169 lprect
->right
= lprect
->left
+ SYSMETRICS_CXVSCROLL
+ 1;
170 lprect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
+1;
175 GetClientRect16( hwnd
, lprect
);
176 vertical
= ((wndPtr
->dwStyle
& SBS_VERT
) != 0);
183 if (vertical
) pixels
= lprect
->bottom
- lprect
->top
;
184 else pixels
= lprect
->right
- lprect
->left
;
186 if (pixels
> 2*SYSMETRICS_CXVSCROLL
+ SCROLL_MIN_RECT
)
188 *arrowSize
= SYSMETRICS_CXVSCROLL
;
190 else if (pixels
> SCROLL_MIN_RECT
)
192 *arrowSize
= (pixels
- SCROLL_MIN_RECT
) / 2;
196 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) > 0)
198 SCROLLINFO
*info
= SCROLL_GetPtrScrollInfo( wndPtr
, nBar
);
199 if ((info
->flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
201 else if (info
->MinVal
== info
->MaxVal
)
202 *thumbPos
= *arrowSize
;
204 *thumbPos
= *arrowSize
+ pixels
* (info
->CurVal
- info
->MinVal
) /
205 (info
->MaxVal
- info
->MinVal
);
212 /***********************************************************************
215 * Compute the current scroll position based on the thumb position in pixels
216 * from the top of the scroll-bar.
218 static UINT
SCROLL_GetThumbVal( SCROLLINFO
*infoPtr
, RECT16
*rect
,
219 BOOL vertical
, WORD pos
)
221 int pixels
= vertical
? rect
->bottom
-rect
->top
: rect
->right
-rect
->left
;
222 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) <= 0) return infoPtr
->MinVal
;
223 pos
= MAX( 0, pos
- SYSMETRICS_CXVSCROLL
);
224 if (pos
> pixels
) pos
= pixels
;
225 dprintf_scroll(stddeb
,"GetThumbVal: pos=%d ret=%d\n", pos
,
227 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
229 return (infoPtr
->MinVal
230 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
235 /***********************************************************************
238 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
240 static enum SCROLL_HITTEST
SCROLL_HitTest( HWND hwnd
, int nBar
, POINT16 pt
)
242 WORD arrowSize
, thumbPos
;
245 BOOL vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
246 &arrowSize
, &thumbPos
);
247 if (!PtInRect16( &rect
, pt
)) return SCROLL_NOWHERE
;
251 if (pt
.y
<= rect
.top
+ arrowSize
+ 1) return SCROLL_TOP_ARROW
;
252 if (pt
.y
>= rect
.bottom
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
253 if (!thumbPos
) return SCROLL_TOP_RECT
;
255 if (pt
.y
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
256 if (pt
.y
> thumbPos
+SYSMETRICS_CYHSCROLL
) return SCROLL_BOTTOM_RECT
;
259 else /* horizontal */
261 if (pt
.x
<= rect
.left
+ arrowSize
) return SCROLL_TOP_ARROW
;
262 if (pt
.x
>= rect
.right
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
263 if (!thumbPos
) return SCROLL_TOP_RECT
;
265 if (pt
.x
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
266 if (pt
.x
> thumbPos
+SYSMETRICS_CXVSCROLL
) return SCROLL_BOTTOM_RECT
;
272 /***********************************************************************
275 * Draw the scroll bar arrows.
277 static void SCROLL_DrawArrows( HDC hdc
, SCROLLINFO
*infoPtr
, RECT16
*rect
,
278 WORD arrowSize
, BOOL vertical
,
279 BOOL top_pressed
, BOOL bottom_pressed
)
281 HDC hdcMem
= CreateCompatibleDC( hdc
);
282 HBITMAP hbmpPrev
= SelectObject( hdcMem
, vertical
?
283 TOP_ARROW(infoPtr
->flags
, top_pressed
)
284 : LEFT_ARROW(infoPtr
->flags
, top_pressed
));
285 SetStretchBltMode( hdc
, STRETCH_DELETESCANS
);
286 StretchBlt( hdc
, rect
->left
, rect
->top
,
287 vertical
? rect
->right
-rect
->left
: arrowSize
+1,
288 vertical
? arrowSize
+1 : rect
->bottom
-rect
->top
,
290 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
293 SelectObject( hdcMem
, vertical
?
294 BOTTOM_ARROW( infoPtr
->flags
, bottom_pressed
)
295 : RIGHT_ARROW( infoPtr
->flags
, bottom_pressed
) );
297 StretchBlt( hdc
, rect
->left
, rect
->bottom
- arrowSize
- 1,
298 rect
->right
- rect
->left
, arrowSize
+ 1,
300 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
303 StretchBlt( hdc
, rect
->right
- arrowSize
- 1, rect
->top
,
304 arrowSize
+ 1, rect
->bottom
- rect
->top
,
306 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
308 SelectObject( hdcMem
, hbmpPrev
);
313 /***********************************************************************
314 * SCROLL_DrawMovingThumb
316 * Draw the moving thumb rectangle.
318 static void SCROLL_DrawMovingThumb( HDC hdc
, RECT16
*rect
, BOOL vertical
,
319 WORD arrowSize
, WORD thumbPos
)
325 if (r
.top
< rect
->top
+ arrowSize
) r
.top
= rect
->top
+ arrowSize
;
326 if (r
.top
+ SYSMETRICS_CYHSCROLL
>= rect
->bottom
- arrowSize
)
327 r
.top
= rect
->bottom
- arrowSize
- SYSMETRICS_CYHSCROLL
- 1;
328 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
333 if (r
.left
< rect
->left
+ arrowSize
) r
.left
= rect
->left
+ arrowSize
;
334 if (r
.left
+ SYSMETRICS_CXVSCROLL
>= rect
->right
- arrowSize
)
335 r
.left
= rect
->right
- arrowSize
- SYSMETRICS_CXVSCROLL
- 1;
336 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
338 InflateRect16( &r
, -1, -1 );
339 DrawFocusRect16( hdc
, &r
);
343 /***********************************************************************
344 * SCROLL_DrawInterior
346 * Draw the scroll bar interior (everything except the arrows).
348 static void SCROLL_DrawInterior( HWND hwnd
, HDC hdc
, int nBar
, RECT16
*rect
,
349 WORD arrowSize
, WORD thumbPos
, WORD flags
,
350 BOOL vertical
, BOOL top_selected
,
351 BOOL bottom_selected
)
355 /* Select the correct brush and pen */
357 SelectObject( hdc
, sysColorObjects
.hpenWindowFrame
);
358 if ((flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
360 /* This ought to be the color of the parent window */
361 SelectObject( hdc
, sysColorObjects
.hbrushWindow
);
365 if (nBar
== SB_CTL
) /* Only scrollbar controls send WM_CTLCOLOR */
367 HBRUSH hbrush
= SendMessage32A( GetParent(hwnd
),
368 WM_CTLCOLORSCROLLBAR
, hdc
, hwnd
);
369 SelectObject( hdc
, hbrush
);
371 else SelectObject( hdc
, sysColorObjects
.hbrushScrollbar
);
374 /* Calculate the scroll rectangle */
380 r
.bottom
-= arrowSize
;
385 r
.right
-= arrowSize
;
388 /* Draw the scroll bar frame */
390 MoveTo( hdc
, r
.left
, r
.top
);
391 LineTo( hdc
, r
.right
-1, r
.top
);
392 LineTo( hdc
, r
.right
-1, r
.bottom
-1 );
393 LineTo( hdc
, r
.left
, r
.bottom
-1 );
394 LineTo( hdc
, r
.left
, r
.top
);
396 /* Draw the scroll rectangles and thumb */
398 if (!thumbPos
) /* No thumb to draw */
400 PatBlt( hdc
, r
.left
+1, r
.top
+1, r
.right
- r
.left
- 2,
401 r
.bottom
- r
.top
- 2, PATCOPY
);
407 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
408 r
.right
- r
.left
- 2,
409 thumbPos
- arrowSize
,
410 top_selected
? 0x0f0000 : PATCOPY
);
411 r
.top
+= thumbPos
- arrowSize
;
412 PatBlt( hdc
, r
.left
+ 1, r
.top
+ SYSMETRICS_CYHSCROLL
+ 1,
413 r
.right
- r
.left
- 2,
414 r
.bottom
- r
.top
- SYSMETRICS_CYHSCROLL
- 2,
415 bottom_selected
? 0x0f0000 : PATCOPY
);
416 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
418 else /* horizontal */
420 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
421 thumbPos
- arrowSize
,
422 r
.bottom
- r
.top
- 2,
423 top_selected
? 0x0f0000 : PATCOPY
);
424 r
.left
+= thumbPos
- arrowSize
;
425 PatBlt( hdc
, r
.left
+ SYSMETRICS_CYHSCROLL
+ 1, r
.top
+ 1,
426 r
.right
- r
.left
- SYSMETRICS_CYHSCROLL
- 2,
427 r
.bottom
- r
.top
- 2,
428 bottom_selected
? 0x0f0000 : PATCOPY
);
429 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
434 SelectObject( hdc
, sysColorObjects
.hbrushBtnFace
);
435 Rectangle( hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
436 InflateRect16( &r
, -1, -1 );
437 GRAPH_DrawReliefRect( hdc
, &r
, 1, 2, FALSE
);
438 if ((hwndTracking
== hwnd
) && (nBarTracking
== nBar
))
439 SCROLL_DrawMovingThumb( hdc
, rect
, vertical
, arrowSize
, uTrackingPos
);
443 /***********************************************************************
444 * SCROLL_DrawScrollBar
446 * Redraw the whole scrollbar.
448 void SCROLL_DrawScrollBar( HWND hwnd
, HDC hdc
, int nBar
)
450 WORD arrowSize
, thumbPos
;
453 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
454 SCROLLINFO
*infoPtr
= SCROLL_GetPtrScrollInfo( wndPtr
, nBar
);
456 if (!wndPtr
|| !infoPtr
||
457 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
458 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
460 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
461 &arrowSize
, &thumbPos
);
462 /* Draw the arrows */
464 if (arrowSize
) SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
,
465 vertical
, FALSE
, FALSE
);
467 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
468 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
472 /***********************************************************************
473 * SCROLL_RefreshScrollBar
475 * Repaint the scroll bar interior after a SetScrollRange() or
476 * SetScrollPos() call.
478 static void SCROLL_RefreshScrollBar( HWND hwnd
, int nBar
)
480 WORD arrowSize
, thumbPos
;
484 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
485 SCROLLINFO
*infoPtr
= SCROLL_GetPtrScrollInfo( wndPtr
, nBar
);
487 if (!wndPtr
|| !infoPtr
||
488 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
489 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
491 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
492 &arrowSize
, &thumbPos
);
493 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
495 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
496 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
497 ReleaseDC( hwnd
, hdc
);
501 /***********************************************************************
502 * SCROLL_HandleKbdEvent
504 * Handle a keyboard event (only for SB_CTL scrollbars).
506 static void SCROLL_HandleKbdEvent( HWND hwnd
, WORD wParam
)
508 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
513 case VK_PRIOR
: msg
= SB_PAGEUP
; break;
514 case VK_NEXT
: msg
= SB_PAGEDOWN
; break;
515 case VK_HOME
: msg
= SB_TOP
; break;
516 case VK_END
: msg
= SB_BOTTOM
; break;
517 case VK_UP
: msg
= SB_LINEUP
; break;
518 case VK_DOWN
: msg
= SB_LINEDOWN
; break;
522 SendMessage32A( GetParent(hwnd
),
523 (wndPtr
->dwStyle
& SBS_VERT
) ? WM_VSCROLL
: WM_HSCROLL
,
528 /***********************************************************************
529 * SCROLL_HandleScrollEvent
531 * Handle a mouse or timer event for the scrollbar.
532 * 'pt' is the location of the mouse event in client (for SB_CTL) or
533 * windows coordinates.
535 void SCROLL_HandleScrollEvent( HWND hwnd
, int nBar
, WORD msg
, POINT16 pt
)
537 /* Previous mouse position for timer events */
538 static POINT16 prevPt
;
539 /* Hit test code of the last button-down event */
540 static enum SCROLL_HITTEST trackHitTest
;
541 /* Thumb position when tracking started. */
542 static UINT trackThumbPos
;
543 /* Position in the scroll-bar of the last button-down event. */
544 static int lastClickPos
;
545 /* Position in the scroll-bar of the last mouse event. */
546 static int lastMousePos
;
548 enum SCROLL_HITTEST hittest
;
549 HWND hwndOwner
, hwndCtl
;
551 WORD arrowSize
, thumbPos
;
555 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
556 if (!infoPtr
) return;
557 if ((trackHitTest
== SCROLL_NOWHERE
) && (msg
!= WM_LBUTTONDOWN
)) return;
559 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
560 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
561 &arrowSize
, &thumbPos
);
562 hwndOwner
= (nBar
== SB_CTL
) ? GetParent(hwnd
) : hwnd
;
563 hwndCtl
= (nBar
== SB_CTL
) ? hwnd
: 0;
567 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
568 trackHitTest
= hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
569 lastClickPos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
570 lastMousePos
= lastClickPos
;
571 trackThumbPos
= thumbPos
;
574 if (nBar
== SB_CTL
) SetFocus( hwnd
);
578 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
583 hittest
= SCROLL_NOWHERE
;
589 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
593 return; /* Should never happen */
596 dprintf_scroll( stddeb
, "ScrollBar Event: hwnd=%04x bar=%d msg=%x pt=%d,%d hit=%d\n",
597 hwnd
, nBar
, msg
, pt
.x
, pt
.y
, hittest
);
601 case SCROLL_NOWHERE
: /* No tracking in progress */
604 case SCROLL_TOP_ARROW
:
605 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
606 (hittest
== trackHitTest
), FALSE
);
607 if (hittest
== trackHitTest
)
609 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
611 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
612 SB_LINEUP
, hwndCtl
);
613 SetSystemTimer32( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
614 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
618 else KillSystemTimer32( hwnd
, SCROLL_TIMER
);
621 case SCROLL_TOP_RECT
:
622 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
623 infoPtr
->flags
, vertical
,
624 (hittest
== trackHitTest
), FALSE
);
625 if (hittest
== trackHitTest
)
627 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
629 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
630 SB_PAGEUP
, hwndCtl
);
631 SetSystemTimer32( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
632 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
636 else KillSystemTimer32( hwnd
, SCROLL_TIMER
);
640 if (msg
== WM_LBUTTONDOWN
)
642 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
643 trackThumbPos
+ lastMousePos
- lastClickPos
);
647 else if (msg
== WM_LBUTTONUP
)
650 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
651 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
653 else /* WM_MOUSEMOVE */
657 if (!PtInRect16( &rect
, pt
)) pos
= lastClickPos
;
658 else pos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
659 if (pos
!= lastMousePos
)
661 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
662 trackThumbPos
+ lastMousePos
- lastClickPos
);
664 val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
665 trackThumbPos
+ lastMousePos
- lastClickPos
);
666 /* Save tracking info */
667 uTrackingPos
= trackThumbPos
+ pos
- lastClickPos
;
668 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
669 MAKEWPARAM( SB_THUMBTRACK
, val
), hwndCtl
);
670 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
,
671 arrowSize
, uTrackingPos
);
676 case SCROLL_BOTTOM_RECT
:
677 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
678 infoPtr
->flags
, vertical
,
679 FALSE
, (hittest
== trackHitTest
) );
680 if (hittest
== trackHitTest
)
682 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
684 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
685 SB_PAGEDOWN
, hwndCtl
);
686 SetSystemTimer32( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
687 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
691 else KillSystemTimer32( hwnd
, SCROLL_TIMER
);
694 case SCROLL_BOTTOM_ARROW
:
695 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
696 FALSE
, (hittest
== trackHitTest
) );
697 if (hittest
== trackHitTest
)
699 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
701 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
702 SB_LINEDOWN
, hwndCtl
);
703 SetSystemTimer32( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
704 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
708 else KillSystemTimer32( hwnd
, SCROLL_TIMER
);
712 if (msg
== WM_LBUTTONUP
)
714 if (trackHitTest
== SCROLL_THUMB
)
716 UINT val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
717 trackThumbPos
+ lastMousePos
- lastClickPos
);
718 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
719 MAKEWPARAM( SB_THUMBPOSITION
, val
), hwndCtl
);
722 SendMessage32A( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
723 SB_ENDSCROLL
, hwndCtl
);
724 trackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
727 ReleaseDC( hwnd
, hdc
);
731 /***********************************************************************
734 LONG
ScrollBarWndProc( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
740 CREATESTRUCT16
*lpCreat
= (CREATESTRUCT16
*)PTR_SEG_TO_LIN(lParam
);
741 if (lpCreat
->style
& SBS_SIZEBOX
)
743 fprintf( stdnimp
, "Unimplemented style SBS_SIZEBOX.\n" );
744 return 0; /* FIXME */
747 if (lpCreat
->style
& SBS_VERT
)
749 if (lpCreat
->style
& SBS_LEFTALIGN
)
750 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
751 SYSMETRICS_CXVSCROLL
+1, lpCreat
->cy
, FALSE
);
752 else if (lpCreat
->style
& SBS_RIGHTALIGN
)
754 lpCreat
->x
+lpCreat
->cx
-SYSMETRICS_CXVSCROLL
-1,
756 SYSMETRICS_CXVSCROLL
+ 1, lpCreat
->cy
, FALSE
);
760 if (lpCreat
->style
& SBS_TOPALIGN
)
761 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
762 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
763 else if (lpCreat
->style
& SBS_BOTTOMALIGN
)
766 lpCreat
->y
+lpCreat
->cy
-SYSMETRICS_CYHSCROLL
-1,
767 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
770 if (!hUpArrow
) SCROLL_LoadBitmaps();
771 dprintf_scroll( stddeb
, "ScrollBar creation, hwnd=%04x\n", hwnd
);
778 SCROLL_HandleScrollEvent( hwnd
, SB_CTL
, message
, MAKEPOINT16(lParam
) );
782 SCROLL_HandleKbdEvent( hwnd
, wParam
);
789 return DLGC_WANTARROWS
; /* Windows returns this value */
794 HDC16 hdc
= BeginPaint16( hwnd
, &ps
);
795 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_CTL
);
796 EndPaint16( hwnd
, &ps
);
800 case 0x400: /* SB_SETSCROLLPOS */
801 case 0x401: /* SB_GETSCROLLPOS */
802 case 0x402: /* SB_GETSCROLLRANGE */
803 case 0x403: /* SB_ENABLE */
804 case 0x404: /* SB_REDRAW */
805 fprintf(stdnimp
,"ScrollBarWndProc: undocumented message %04x, please report\n", message
);
808 return DefWindowProc16( hwnd
, message
, wParam
, lParam
);
814 /*************************************************************************
815 * SetScrollPos (USER.62)
817 int SetScrollPos( HWND hwnd
, int nBar
, int nPos
, BOOL bRedraw
)
822 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
824 dprintf_scroll( stddeb
,"SetScrollPos min=%d max=%d pos=%d\n",
825 infoPtr
->MinVal
, infoPtr
->MaxVal
, nPos
);
827 if (nPos
< infoPtr
->MinVal
) nPos
= infoPtr
->MinVal
;
828 else if (nPos
> infoPtr
->MaxVal
) nPos
= infoPtr
->MaxVal
;
829 oldPos
= infoPtr
->CurVal
;
830 infoPtr
->CurVal
= nPos
;
831 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
836 /*************************************************************************
837 * GetScrollPos (USER.63)
839 int GetScrollPos( HWND hwnd
, int nBar
)
843 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
844 return infoPtr
->CurVal
;
848 /*************************************************************************
849 * SetScrollRange (USER.64)
851 void SetScrollRange(HWND hwnd
, int nBar
, int MinVal
, int MaxVal
, BOOL bRedraw
)
855 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
857 dprintf_scroll( stddeb
,"SetScrollRange hwnd=%04x bar=%d min=%d max=%d\n",
858 hwnd
, nBar
, MinVal
, MaxVal
);
860 /* Invalid range -> range is set to (0,0) */
861 if ((MinVal
> MaxVal
) || ((long)MaxVal
- MinVal
> 32767L))
863 if (infoPtr
->CurVal
< MinVal
) infoPtr
->CurVal
= MinVal
;
864 else if (infoPtr
->CurVal
> MaxVal
) infoPtr
->CurVal
= MaxVal
;
865 infoPtr
->MinVal
= MinVal
;
866 infoPtr
->MaxVal
= MaxVal
;
868 /* Non-client scroll-bar is hidden if min==max */
869 if (nBar
!= SB_CTL
) ShowScrollBar( hwnd
, nBar
, (MinVal
!= MaxVal
) );
870 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
873 /*************************************************************************
874 * SCROLL_SetNCSbState
876 * This is for CalcChildScroll in windows/mdi.c
878 DWORD
SCROLL_SetNCSbState(WND
* wndPtr
, int vMin
, int vMax
, int vPos
,
879 int hMin
, int hMax
, int hPos
)
881 SCROLLINFO
*infoPtr
= SCROLL_GetPtrScrollInfo(wndPtr
, SB_VERT
);
883 wndPtr
->dwStyle
|= (WS_VSCROLL
| WS_HSCROLL
);
887 wndPtr
->dwStyle
&= ~WS_VSCROLL
; }
888 if( vPos
> vMax
) vPos
= vMax
; else if( vPos
< vMin
) vPos
= vMin
;
889 infoPtr
->MinVal
= vMin
;
890 infoPtr
->MaxVal
= vMax
;
891 infoPtr
->CurVal
= vPos
;
893 infoPtr
= SCROLL_GetPtrScrollInfo(wndPtr
, SB_HORZ
);
897 wndPtr
->dwStyle
&= ~WS_HSCROLL
; }
898 if( hPos
> hMax
) hPos
= hMax
; else if( hPos
< hMin
) hPos
= hMin
;
899 infoPtr
->MinVal
= hMin
;
900 infoPtr
->MaxVal
= hMax
;
901 infoPtr
->CurVal
= hPos
;
903 return wndPtr
->dwStyle
& (WS_VSCROLL
| WS_HSCROLL
);
906 /*************************************************************************
907 * GetScrollRange (USER.65)
909 void GetScrollRange(HWND hwnd
, int nBar
, LPINT16 lpMin
, LPINT16 lpMax
)
913 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
914 if (lpMin
) *lpMin
= infoPtr
->MinVal
;
915 if (lpMax
) *lpMax
= infoPtr
->MaxVal
;
919 /*************************************************************************
920 * ShowScrollBar (USER.267)
922 void ShowScrollBar( HWND hwnd
, WORD wBar
, BOOL fShow
)
924 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
927 dprintf_scroll( stddeb
, "ShowScrollBar: hwnd=%04x bar=%d on=%d\n", hwnd
, wBar
, fShow
);
932 ShowWindow( hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
938 if (wndPtr
->dwStyle
& WS_HSCROLL
) return;
939 wndPtr
->dwStyle
|= WS_HSCROLL
;
943 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
944 wndPtr
->dwStyle
&= ~WS_HSCROLL
;
951 if (wndPtr
->dwStyle
& WS_VSCROLL
) return;
952 wndPtr
->dwStyle
|= WS_VSCROLL
;
956 if (!(wndPtr
->dwStyle
& WS_VSCROLL
)) return;
957 wndPtr
->dwStyle
&= ~WS_VSCROLL
;
964 if ((wndPtr
->dwStyle
& WS_HSCROLL
)
965 && (wndPtr
->dwStyle
& WS_VSCROLL
)) return;
966 wndPtr
->dwStyle
|= WS_HSCROLL
| WS_VSCROLL
;
970 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)
971 && !(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
972 wndPtr
->dwStyle
&= ~(WS_HSCROLL
| WS_VSCROLL
);
977 return; /* Nothing to do! */
979 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
980 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
984 /*************************************************************************
985 * EnableScrollBar (USER.482)
987 BOOL
EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
992 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return FALSE
;
993 dprintf_scroll( stddeb
, "EnableScrollBar: %04x %d %d\n", hwnd
, nBar
, flags
);
994 flags
&= ESB_DISABLE_BOTH
;
995 if (infoPtr
->flags
== flags
) return FALSE
;
996 infoPtr
->flags
= flags
;
998 /* Redraw the whole scroll bar */
999 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
1000 SCROLL_DrawScrollBar( hwnd
, hdc
, nBar
);
1001 ReleaseDC( hwnd
, hdc
);