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 */
73 /* Thumb-tracking info */
74 static HWND hwndTracking
= 0;
75 static int nBarTracking
= 0;
76 static UINT uTrackingPos
= 0;
78 /***********************************************************************
81 static void SCROLL_LoadBitmaps(void)
83 hUpArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROW
));
84 hDnArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROW
));
85 hLfArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROW
));
86 hRgArrow
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROW
));
87 hUpArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWD
));
88 hDnArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWD
));
89 hLfArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWD
));
90 hRgArrowD
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWD
));
91 hUpArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_UPARROWI
));
92 hDnArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_DNARROWI
));
93 hLfArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_LFARROWI
));
94 hRgArrowI
= LoadBitmap((HINSTANCE
)NULL
, MAKEINTRESOURCE(OBM_RGARROWI
));
98 /***********************************************************************
99 * SCROLL_GetScrollInfo
101 static SCROLLINFO
*SCROLL_GetScrollInfo( HWND hwnd
, int nBar
)
104 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
106 if (!wndPtr
) return NULL
;
109 case SB_HORZ
: handle
= wndPtr
->hHScroll
; break;
110 case SB_VERT
: handle
= wndPtr
->hVScroll
; break;
111 case SB_CTL
: return (SCROLLINFO
*)wndPtr
->wExtra
;
112 default: return NULL
;
115 if (!handle
) /* Create the info structure if needed */
117 if ((handle
= USER_HEAP_ALLOC( sizeof(SCROLLINFO
) )))
119 SCROLLINFO
*infoPtr
= (SCROLLINFO
*) USER_HEAP_LIN_ADDR( handle
);
120 infoPtr
->MinVal
= infoPtr
->CurVal
= 0;
121 infoPtr
->MaxVal
= 100;
122 infoPtr
->flags
= ESB_ENABLE_BOTH
;
123 if (nBar
== SB_HORZ
) wndPtr
->hHScroll
= handle
;
124 else wndPtr
->hVScroll
= handle
;
126 if (!hUpArrow
) SCROLL_LoadBitmaps();
128 return (SCROLLINFO
*) USER_HEAP_LIN_ADDR( handle
);
132 /***********************************************************************
133 * SCROLL_GetScrollBarRect
135 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
136 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
137 * 'arrowSize' returns the width or height of an arrow (depending on the
138 * orientation of the scrollbar), and 'thumbPos' returns the position of
139 * the thumb relative to the left or to the top.
140 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
142 static BOOL
SCROLL_GetScrollBarRect( HWND hwnd
, int nBar
, RECT
*lprect
,
143 WORD
*arrowSize
, WORD
*thumbPos
)
147 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
152 lprect
->left
= wndPtr
->rectClient
.left
- wndPtr
->rectWindow
.left
- 1;
153 lprect
->top
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
;
154 lprect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
+1;
155 lprect
->bottom
= lprect
->top
+ SYSMETRICS_CYHSCROLL
+ 1;
160 lprect
->left
= wndPtr
->rectClient
.right
- wndPtr
->rectWindow
.left
;
161 lprect
->top
= wndPtr
->rectClient
.top
- wndPtr
->rectWindow
.top
- 1;
162 lprect
->right
= lprect
->left
+ SYSMETRICS_CXVSCROLL
+ 1;
163 lprect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectWindow
.top
+1;
168 GetClientRect( hwnd
, lprect
);
169 vertical
= ((wndPtr
->dwStyle
& SBS_VERT
) != 0);
176 if (vertical
) pixels
= lprect
->bottom
- lprect
->top
;
177 else pixels
= lprect
->right
- lprect
->left
;
179 if (pixels
> 2*SYSMETRICS_CXVSCROLL
+ SCROLL_MIN_RECT
)
181 *arrowSize
= SYSMETRICS_CXVSCROLL
;
183 else if (pixels
> SCROLL_MIN_RECT
)
185 *arrowSize
= (pixels
- SCROLL_MIN_RECT
) / 2;
189 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) > 0)
191 SCROLLINFO
*info
= SCROLL_GetScrollInfo( hwnd
, nBar
);
192 if ((info
->flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
194 else if (info
->MinVal
== info
->MaxVal
)
195 *thumbPos
= *arrowSize
;
197 *thumbPos
= *arrowSize
+ pixels
* (info
->CurVal
- info
->MinVal
) /
198 (info
->MaxVal
- info
->MinVal
);
205 /***********************************************************************
208 * Compute the current scroll position based on the thumb position in pixels
209 * from the top of the scroll-bar.
211 static UINT
SCROLL_GetThumbVal( SCROLLINFO
*infoPtr
, RECT
*rect
,
212 BOOL vertical
, WORD pos
)
214 int pixels
= vertical
? rect
->bottom
-rect
->top
: rect
->right
-rect
->left
;
215 if ((pixels
-= 3*SYSMETRICS_CXVSCROLL
+1) <= 0) return infoPtr
->MinVal
;
216 pos
= MAX( 0, pos
- SYSMETRICS_CXVSCROLL
);
217 if (pos
> pixels
) pos
= pixels
;
218 dprintf_scroll(stddeb
,"GetThumbVal: pos=%d ret=%d\n", pos
,
220 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
222 return (infoPtr
->MinVal
223 + (UINT
)(((int)pos
* (infoPtr
->MaxVal
-infoPtr
->MinVal
) + pixels
/2)
228 /***********************************************************************
231 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
233 static enum SCROLL_HITTEST
SCROLL_HitTest( HWND hwnd
, int nBar
, POINT pt
)
235 WORD arrowSize
, thumbPos
;
238 BOOL vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
239 &arrowSize
, &thumbPos
);
240 if (!PtInRect( &rect
, pt
)) return SCROLL_NOWHERE
;
244 if (pt
.y
<= rect
.top
+ arrowSize
+ 1) return SCROLL_TOP_ARROW
;
245 if (pt
.y
>= rect
.bottom
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
246 if (!thumbPos
) return SCROLL_TOP_RECT
;
248 if (pt
.y
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
249 if (pt
.y
> thumbPos
+SYSMETRICS_CYHSCROLL
) return SCROLL_BOTTOM_RECT
;
252 else /* horizontal */
254 if (pt
.x
<= rect
.left
+ arrowSize
) return SCROLL_TOP_ARROW
;
255 if (pt
.x
>= rect
.right
- arrowSize
) return SCROLL_BOTTOM_ARROW
;
256 if (!thumbPos
) return SCROLL_TOP_RECT
;
258 if (pt
.x
< (INT
)thumbPos
) return SCROLL_TOP_RECT
;
259 if (pt
.x
> thumbPos
+SYSMETRICS_CXVSCROLL
) return SCROLL_BOTTOM_RECT
;
265 /***********************************************************************
268 * Draw the scroll bar arrows.
270 static void SCROLL_DrawArrows( HDC hdc
, SCROLLINFO
*infoPtr
, RECT
*rect
,
271 WORD arrowSize
, BOOL vertical
,
272 BOOL top_pressed
, BOOL bottom_pressed
)
274 HDC hdcMem
= CreateCompatibleDC( hdc
);
275 HBITMAP hbmpPrev
= SelectObject( hdcMem
, vertical
?
276 TOP_ARROW(infoPtr
->flags
, top_pressed
)
277 : LEFT_ARROW(infoPtr
->flags
, top_pressed
));
278 SetStretchBltMode( hdc
, STRETCH_DELETESCANS
);
279 StretchBlt( hdc
, rect
->left
, rect
->top
,
280 vertical
? rect
->right
-rect
->left
: arrowSize
+1,
281 vertical
? arrowSize
+1 : rect
->bottom
-rect
->top
,
283 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
286 SelectObject( hdcMem
, vertical
?
287 BOTTOM_ARROW( infoPtr
->flags
, bottom_pressed
)
288 : RIGHT_ARROW( infoPtr
->flags
, bottom_pressed
) );
290 StretchBlt( hdc
, rect
->left
, rect
->bottom
- arrowSize
- 1,
291 rect
->right
- rect
->left
, arrowSize
+ 1,
293 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
296 StretchBlt( hdc
, rect
->right
- arrowSize
- 1, rect
->top
,
297 arrowSize
+ 1, rect
->bottom
- rect
->top
,
299 SYSMETRICS_CXVSCROLL
+ 1, SYSMETRICS_CYHSCROLL
+ 1,
301 SelectObject( hdcMem
, hbmpPrev
);
306 /***********************************************************************
307 * SCROLL_DrawMovingThumb
309 * Draw the moving thumb rectangle.
311 static void SCROLL_DrawMovingThumb( HDC hdc
, RECT
*rect
, BOOL vertical
,
312 WORD arrowSize
, WORD thumbPos
)
318 if (r
.top
< rect
->top
+ arrowSize
) r
.top
= rect
->top
+ arrowSize
;
319 if (r
.top
+ SYSMETRICS_CYHSCROLL
>= rect
->bottom
- arrowSize
)
320 r
.top
= rect
->bottom
- arrowSize
- SYSMETRICS_CYHSCROLL
- 1;
321 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
326 if (r
.left
< rect
->left
+ arrowSize
) r
.left
= rect
->left
+ arrowSize
;
327 if (r
.left
+ SYSMETRICS_CXVSCROLL
>= rect
->right
- arrowSize
)
328 r
.left
= rect
->right
- arrowSize
- SYSMETRICS_CXVSCROLL
- 1;
329 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
331 InflateRect( &r
, -1, -1 );
332 DrawFocusRect( hdc
, &r
);
336 /***********************************************************************
337 * SCROLL_DrawInterior
339 * Draw the scroll bar interior (everything except the arrows).
341 static void SCROLL_DrawInterior( HWND hwnd
, HDC hdc
, int nBar
, RECT
*rect
,
342 WORD arrowSize
, WORD thumbPos
, WORD flags
,
343 BOOL vertical
, BOOL top_selected
,
344 BOOL bottom_selected
)
348 /* Select the correct brush and pen */
350 SelectObject( hdc
, sysColorObjects
.hpenWindowFrame
);
351 if ((flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
)
353 /* This ought to be the color of the parent window */
354 SelectObject( hdc
, sysColorObjects
.hbrushWindow
);
358 if (nBar
== SB_CTL
) /* Only scrollbar controls send WM_CTLCOLOR */
361 HBRUSH hbrush
= (HBRUSH
)SendMessage( GetParent(hwnd
),
362 WM_CTLCOLORSCROLLBAR
,
363 (WPARAM
)hdc
, (LPARAM
)hwnd
);
365 HBRUSH hbrush
= SendMessage( GetParent(hwnd
), WM_CTLCOLOR
, hdc
,
366 MAKELONG(hwnd
, CTLCOLOR_SCROLLBAR
) );
368 SelectObject( hdc
, hbrush
);
370 else SelectObject( hdc
, sysColorObjects
.hbrushScrollbar
);
373 /* Calculate the scroll rectangle */
379 r
.bottom
-= arrowSize
;
384 r
.right
-= arrowSize
;
387 /* Draw the scroll bar frame */
389 MoveTo( hdc
, r
.left
, r
.top
);
390 LineTo( hdc
, r
.right
-1, r
.top
);
391 LineTo( hdc
, r
.right
-1, r
.bottom
-1 );
392 LineTo( hdc
, r
.left
, r
.bottom
-1 );
393 LineTo( hdc
, r
.left
, r
.top
);
395 /* Draw the scroll rectangles and thumb */
397 if (!thumbPos
) /* No thumb to draw */
399 PatBlt( hdc
, r
.left
+1, r
.top
+1, r
.right
- r
.left
- 2,
400 r
.bottom
- r
.top
- 2, PATCOPY
);
406 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
407 r
.right
- r
.left
- 2,
408 thumbPos
- arrowSize
,
409 top_selected
? 0x0f0000 : PATCOPY
);
410 r
.top
+= thumbPos
- arrowSize
;
411 PatBlt( hdc
, r
.left
+ 1, r
.top
+ SYSMETRICS_CYHSCROLL
+ 1,
412 r
.right
- r
.left
- 2,
413 r
.bottom
- r
.top
- SYSMETRICS_CYHSCROLL
- 2,
414 bottom_selected
? 0x0f0000 : PATCOPY
);
415 r
.bottom
= r
.top
+ SYSMETRICS_CYHSCROLL
+ 1;
417 else /* horizontal */
419 PatBlt( hdc
, r
.left
+ 1, r
.top
+ 1,
420 thumbPos
- arrowSize
,
421 r
.bottom
- r
.top
- 2,
422 top_selected
? 0x0f0000 : PATCOPY
);
423 r
.left
+= thumbPos
- arrowSize
;
424 PatBlt( hdc
, r
.left
+ SYSMETRICS_CYHSCROLL
+ 1, r
.top
+ 1,
425 r
.right
- r
.left
- SYSMETRICS_CYHSCROLL
- 2,
426 r
.bottom
- r
.top
- 2,
427 bottom_selected
? 0x0f0000 : PATCOPY
);
428 r
.right
= r
.left
+ SYSMETRICS_CXVSCROLL
+ 1;
433 SelectObject( hdc
, sysColorObjects
.hbrushBtnFace
);
434 Rectangle( hdc
, r
.left
, r
.top
, r
.right
, r
.bottom
);
435 InflateRect( &r
, -1, -1 );
436 GRAPH_DrawReliefRect( hdc
, &r
, 1, 2, FALSE
);
437 if ((hwndTracking
== hwnd
) && (nBarTracking
== nBar
))
438 SCROLL_DrawMovingThumb( hdc
, rect
, vertical
, arrowSize
, uTrackingPos
);
442 /***********************************************************************
443 * SCROLL_DrawScrollBar
445 * Redraw the whole scrollbar.
447 void SCROLL_DrawScrollBar( HWND hwnd
, HDC hdc
, int nBar
)
449 WORD arrowSize
, thumbPos
;
452 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
453 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
455 if (!wndPtr
|| !infoPtr
||
456 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
457 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
459 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
460 &arrowSize
, &thumbPos
);
461 /* Draw the arrows */
463 if (arrowSize
) SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
,
464 vertical
, FALSE
, FALSE
);
466 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
467 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
471 /***********************************************************************
472 * SCROLL_RefreshScrollBar
474 * Repaint the scroll bar interior after a SetScrollRange() or
475 * SetScrollPos() call.
477 static void SCROLL_RefreshScrollBar( HWND hwnd
, int nBar
)
479 WORD arrowSize
, thumbPos
;
483 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
484 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
486 if (!wndPtr
|| !infoPtr
||
487 ((nBar
== SB_VERT
) && !(wndPtr
->dwStyle
& WS_VSCROLL
)) ||
488 ((nBar
== SB_HORZ
) && !(wndPtr
->dwStyle
& WS_HSCROLL
))) return;
490 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
491 &arrowSize
, &thumbPos
);
492 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
494 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
495 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
496 ReleaseDC( hwnd
, hdc
);
500 /***********************************************************************
501 * SCROLL_HandleKbdEvent
503 * Handle a keyboard event (only for SB_CTL scrollbars).
505 static void SCROLL_HandleKbdEvent( HWND hwnd
, WORD wParam
)
507 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
512 case VK_PRIOR
: msg
= SB_PAGEUP
; break;
513 case VK_NEXT
: msg
= SB_PAGEDOWN
; break;
514 case VK_HOME
: msg
= SB_TOP
; break;
515 case VK_END
: msg
= SB_BOTTOM
; break;
516 case VK_UP
: msg
= SB_LINEUP
; break;
517 case VK_DOWN
: msg
= SB_LINEDOWN
; break;
522 SendMessage( GetParent(hwnd
),
523 (wndPtr
->dwStyle
& SBS_VERT
) ? WM_VSCROLL
: WM_HSCROLL
,
524 (WPARAM
)msg
, (LPARAM
)hwnd
);
526 SendMessage( GetParent(hwnd
),
527 (wndPtr
->dwStyle
& SBS_VERT
) ? WM_VSCROLL
: WM_HSCROLL
,
528 msg
, MAKELONG( 0, hwnd
));
533 /***********************************************************************
534 * SCROLL_HandleScrollEvent
536 * Handle a mouse or timer event for the scrollbar.
537 * 'pt' is the location of the mouse event in client (for SB_CTL) or
538 * windows coordinates.
540 void SCROLL_HandleScrollEvent( HWND hwnd
, int nBar
, WORD msg
, POINT pt
)
542 /* Previous mouse position for timer events */
544 /* Hit test code of the last button-down event */
545 static enum SCROLL_HITTEST trackHitTest
;
546 /* Thumb position when tracking started. */
547 static UINT trackThumbPos
;
548 /* Position in the scroll-bar of the last button-down event. */
549 static int lastClickPos
;
550 /* Position in the scroll-bar of the last mouse event. */
551 static int lastMousePos
;
553 enum SCROLL_HITTEST hittest
;
554 HWND hwndOwner
, hwndCtl
;
556 WORD arrowSize
, thumbPos
;
560 SCROLLINFO
*infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
);
561 if (!infoPtr
) return;
562 if ((trackHitTest
== SCROLL_NOWHERE
) && (msg
!= WM_LBUTTONDOWN
)) return;
564 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
565 vertical
= SCROLL_GetScrollBarRect( hwnd
, nBar
, &rect
,
566 &arrowSize
, &thumbPos
);
567 hwndOwner
= (nBar
== SB_CTL
) ? GetParent(hwnd
) : hwnd
;
568 hwndCtl
= (nBar
== SB_CTL
) ? hwnd
: 0;
572 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
573 trackHitTest
= hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
574 lastClickPos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
575 lastMousePos
= lastClickPos
;
576 trackThumbPos
= thumbPos
;
579 if (nBar
== SB_CTL
) SetFocus( hwnd
);
583 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
588 hittest
= SCROLL_NOWHERE
;
594 hittest
= SCROLL_HitTest( hwnd
, nBar
, pt
);
598 return; /* Should never happen */
601 dprintf_scroll( stddeb
, "ScrollBar Event: hwnd="NPFMT
" bar=%d msg=%x pt=%ld,%ld hit=%d\n",
602 hwnd
, nBar
, msg
, (LONG
)pt
.x
, (LONG
)pt
.y
, hittest
);
606 case SCROLL_NOWHERE
: /* No tracking in progress */
609 case SCROLL_TOP_ARROW
:
610 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
611 (hittest
== trackHitTest
), FALSE
);
612 if (hittest
== trackHitTest
)
614 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
617 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
618 (WPARAM
)SB_LINEUP
, (LPARAM
)hwndCtl
);
620 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
621 SB_LINEUP
, MAKELONG( 0, hwndCtl
));
623 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
624 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
628 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
631 case SCROLL_TOP_RECT
:
632 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
633 infoPtr
->flags
, vertical
,
634 (hittest
== trackHitTest
), FALSE
);
635 if (hittest
== trackHitTest
)
637 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
640 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
641 (WPARAM
)SB_PAGEUP
, (LPARAM
)hwndCtl
);
643 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
644 SB_PAGEUP
, MAKELONG( 0, hwndCtl
));
646 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
647 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
651 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
655 if (msg
== WM_LBUTTONDOWN
)
657 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
658 trackThumbPos
+ lastMousePos
- lastClickPos
);
662 else if (msg
== WM_LBUTTONUP
)
665 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
666 infoPtr
->flags
, vertical
, FALSE
, FALSE
);
668 else /* WM_MOUSEMOVE */
672 if (!PtInRect( &rect
, pt
)) pos
= lastClickPos
;
673 else pos
= vertical
? (pt
.y
- rect
.top
) : (pt
.x
- rect
.left
);
674 if (pos
!= lastMousePos
)
676 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
, arrowSize
,
677 trackThumbPos
+ lastMousePos
- lastClickPos
);
679 val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
680 trackThumbPos
+ lastMousePos
- lastClickPos
);
681 /* Save tracking info */
682 uTrackingPos
= trackThumbPos
+ pos
- lastClickPos
;
684 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
685 MAKEWPARAM(SB_THUMBTRACK
,val
), (LPARAM
)hwndCtl
);
687 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
688 SB_THUMBTRACK
, MAKELONG( val
, hwndCtl
));
690 SCROLL_DrawMovingThumb( hdc
, &rect
, vertical
,
691 arrowSize
, uTrackingPos
);
696 case SCROLL_BOTTOM_RECT
:
697 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, &rect
, arrowSize
, thumbPos
,
698 infoPtr
->flags
, vertical
,
699 FALSE
, (hittest
== trackHitTest
) );
700 if (hittest
== trackHitTest
)
702 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
705 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
706 (WPARAM
)SB_PAGEDOWN
, (LPARAM
)hwndCtl
);
708 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
709 SB_PAGEDOWN
, MAKELONG( 0, hwndCtl
));
711 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
712 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
716 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
719 case SCROLL_BOTTOM_ARROW
:
720 SCROLL_DrawArrows( hdc
, infoPtr
, &rect
, arrowSize
, vertical
,
721 FALSE
, (hittest
== trackHitTest
) );
722 if (hittest
== trackHitTest
)
724 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
727 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
728 (WPARAM
)SB_LINEDOWN
, (LPARAM
)hwndCtl
);
730 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
731 SB_LINEDOWN
, MAKELONG( 0, hwndCtl
));
733 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
734 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
738 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
742 if (msg
== WM_LBUTTONUP
)
744 if (trackHitTest
== SCROLL_THUMB
)
746 UINT val
= SCROLL_GetThumbVal( infoPtr
, &rect
, vertical
,
747 trackThumbPos
+ lastMousePos
- lastClickPos
);
749 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
750 MAKEWPARAM(SB_THUMBPOSITION
,val
), (LPARAM
)hwndCtl
);
752 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
753 SB_THUMBPOSITION
, MAKELONG( val
, hwndCtl
) );
758 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
759 (WPARAM
)SB_ENDSCROLL
, (LPARAM
)hwndCtl
);
761 SendMessage( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
762 SB_ENDSCROLL
, MAKELONG( 0, hwndCtl
) );
764 trackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
767 ReleaseDC( hwnd
, hdc
);
771 /***********************************************************************
774 LONG
ScrollBarWndProc( HWND hwnd
, WORD message
, WORD wParam
, LONG lParam
)
777 Pt
.x
= LOWORD(lParam
); Pt
.y
= HIWORD(lParam
);
778 /* ^ Can't use MAKEPOINT macro in WINELIB32 */
784 CREATESTRUCT
*lpCreat
= (CREATESTRUCT
*)PTR_SEG_TO_LIN(lParam
);
785 if (lpCreat
->style
& SBS_SIZEBOX
)
787 fprintf( stdnimp
, "Unimplemented style SBS_SIZEBOX.\n" );
788 return 0; /* FIXME */
791 if (lpCreat
->style
& SBS_VERT
)
793 if (lpCreat
->style
& SBS_LEFTALIGN
)
794 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
795 SYSMETRICS_CXVSCROLL
+1, lpCreat
->cy
, FALSE
);
796 else if (lpCreat
->style
& SBS_RIGHTALIGN
)
798 lpCreat
->x
+lpCreat
->cx
-SYSMETRICS_CXVSCROLL
-1,
800 SYSMETRICS_CXVSCROLL
+ 1, lpCreat
->cy
, FALSE
);
804 if (lpCreat
->style
& SBS_TOPALIGN
)
805 MoveWindow( hwnd
, lpCreat
->x
, lpCreat
->y
,
806 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
807 else if (lpCreat
->style
& SBS_BOTTOMALIGN
)
810 lpCreat
->y
+lpCreat
->cy
-SYSMETRICS_CYHSCROLL
-1,
811 lpCreat
->cx
, SYSMETRICS_CYHSCROLL
+1, FALSE
);
814 if (!hUpArrow
) SCROLL_LoadBitmaps();
815 dprintf_scroll( stddeb
, "ScrollBar creation, hwnd="NPFMT
"\n", hwnd
);
822 SCROLL_HandleScrollEvent( hwnd
, SB_CTL
, message
, Pt
);
826 SCROLL_HandleKbdEvent( hwnd
, wParam
);
833 return DLGC_WANTARROWS
; /* Windows returns this value */
838 HDC hdc
= BeginPaint( hwnd
, &ps
);
839 SCROLL_DrawScrollBar( hwnd
, hdc
, SB_CTL
);
840 EndPaint( hwnd
, &ps
);
844 case 0x400: /* SB_SETSCROLLPOS */
845 case 0x401: /* SB_GETSCROLLPOS */
846 case 0x402: /* SB_GETSCROLLRANGE */
847 case 0x403: /* SB_ENABLE */
848 case 0x404: /* SB_REDRAW */
849 fprintf(stdnimp
,"ScrollBarWndProc: undocumented message %04x, please report\n", message
);
852 return DefWindowProc( hwnd
, message
, wParam
, lParam
);
858 /*************************************************************************
859 * SetScrollPos (USER.62)
861 int SetScrollPos( HWND hwnd
, int nBar
, int nPos
, BOOL bRedraw
)
866 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
868 dprintf_scroll( stddeb
,"SetScrollPos min=%d max=%d pos=%d\n",
869 infoPtr
->MinVal
, infoPtr
->MaxVal
, nPos
);
871 if (nPos
< infoPtr
->MinVal
) nPos
= infoPtr
->MinVal
;
872 else if (nPos
> infoPtr
->MaxVal
) nPos
= infoPtr
->MaxVal
;
873 oldPos
= infoPtr
->CurVal
;
874 infoPtr
->CurVal
= nPos
;
875 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
880 /*************************************************************************
881 * GetScrollPos (USER.63)
883 int GetScrollPos( HWND hwnd
, int nBar
)
887 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return 0;
888 return infoPtr
->CurVal
;
892 /*************************************************************************
893 * SetScrollRange (USER.64)
895 void SetScrollRange(HWND hwnd
, int nBar
, int MinVal
, int MaxVal
, BOOL bRedraw
)
899 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
901 dprintf_scroll( stddeb
,"SetScrollRange hwnd="NPFMT
" bar=%d min=%d max=%d\n",
902 hwnd
, nBar
, MinVal
, MaxVal
);
904 /* Invalid range -> range is set to (0,0) */
905 if ((MinVal
> MaxVal
) || ((long)MaxVal
- MinVal
> 32767L))
907 if (infoPtr
->CurVal
< MinVal
) infoPtr
->CurVal
= MinVal
;
908 else if (infoPtr
->CurVal
> MaxVal
) infoPtr
->CurVal
= MaxVal
;
909 infoPtr
->MinVal
= MinVal
;
910 infoPtr
->MaxVal
= MaxVal
;
912 /* Non-client scroll-bar is hidden if min==max */
913 if (nBar
!= SB_CTL
) ShowScrollBar( hwnd
, nBar
, (MinVal
!= MaxVal
) );
914 if (bRedraw
) SCROLL_RefreshScrollBar( hwnd
, nBar
);
918 /*************************************************************************
919 * GetScrollRange (USER.65)
921 void GetScrollRange(HWND hwnd
, int nBar
, LPINT lpMin
, LPINT lpMax
)
925 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return;
926 if (lpMin
) *lpMin
= infoPtr
->MinVal
;
927 if (lpMax
) *lpMax
= infoPtr
->MaxVal
;
931 /*************************************************************************
932 * ShowScrollBar (USER.267)
934 void ShowScrollBar( HWND hwnd
, WORD wBar
, BOOL fShow
)
936 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
939 dprintf_scroll( stddeb
, "ShowScrollBar: hwnd="NPFMT
" bar=%d on=%d\n", hwnd
, wBar
, fShow
);
944 ShowWindow( hwnd
, fShow
? SW_SHOW
: SW_HIDE
);
950 if (wndPtr
->dwStyle
& WS_HSCROLL
) return;
951 wndPtr
->dwStyle
|= WS_HSCROLL
;
955 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
956 wndPtr
->dwStyle
&= ~WS_HSCROLL
;
963 if (wndPtr
->dwStyle
& WS_VSCROLL
) return;
964 wndPtr
->dwStyle
|= WS_VSCROLL
;
968 if (!(wndPtr
->dwStyle
& WS_VSCROLL
)) return;
969 wndPtr
->dwStyle
&= ~WS_VSCROLL
;
976 if ((wndPtr
->dwStyle
& WS_HSCROLL
)
977 && (wndPtr
->dwStyle
& WS_VSCROLL
)) return;
978 wndPtr
->dwStyle
|= WS_HSCROLL
| WS_VSCROLL
;
982 if (!(wndPtr
->dwStyle
& WS_HSCROLL
)
983 && !(wndPtr
->dwStyle
& WS_HSCROLL
)) return;
984 wndPtr
->dwStyle
&= ~(WS_HSCROLL
| WS_VSCROLL
);
989 return; /* Nothing to do! */
991 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
992 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
996 /*************************************************************************
997 * EnableScrollBar (USER.482)
999 BOOL
EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
1001 SCROLLINFO
*infoPtr
;
1004 if (!(infoPtr
= SCROLL_GetScrollInfo( hwnd
, nBar
))) return FALSE
;
1005 dprintf_scroll( stddeb
, "EnableScrollBar: "NPFMT
" %d %d\n", hwnd
, nBar
, flags
);
1006 flags
&= ESB_DISABLE_BOTH
;
1007 if (infoPtr
->flags
== flags
) return FALSE
;
1008 infoPtr
->flags
= flags
;
1010 /* Redraw the whole scroll bar */
1011 hdc
= (nBar
== SB_CTL
) ? GetDC(hwnd
) : GetWindowDC(hwnd
);
1012 SCROLL_DrawScrollBar( hwnd
, hdc
, nBar
);
1013 ReleaseDC( hwnd
, hdc
);