2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS uxtheme.dll
4 * FILE: dll/win32/uxtheme/ncscrollbar.c
5 * PURPOSE: uxtheme scrollbar support
6 * PROGRAMMER: Giannis Adamopoulos
7 * This file is heavily based on code from the wine project:
8 * Copyright 1993 Martin Ayotte
9 * Copyright 1994, 1996 Alexandre Julliard
16 static void ScreenToWindow( HWND hWnd
, POINT
* pt
)
19 GetWindowRect(hWnd
, &rcWnd
);
24 static BOOL
SCROLL_IsVertical(HWND hwnd
, INT nBar
)
38 static LONG
SCROLL_getObjectId(INT nBar
)
52 /***********************************************************************
55 static BOOL
SCROLL_PtInRectEx( LPRECT lpRect
, POINT pt
, BOOL vertical
)
60 /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
61 * still be considered in the scrollbar. */
64 scrollbarWidth
= lpRect
->right
- lpRect
->left
;
65 rect
.left
-= scrollbarWidth
*8;
66 rect
.right
+= scrollbarWidth
*8;
67 rect
.top
-= scrollbarWidth
*2;
68 rect
.bottom
+= scrollbarWidth
*2;
72 scrollbarWidth
= lpRect
->bottom
- lpRect
->top
;
73 rect
.left
-= scrollbarWidth
*2;
74 rect
.right
+= scrollbarWidth
*2;
75 rect
.top
-= scrollbarWidth
*8;
76 rect
.bottom
+= scrollbarWidth
*8;
78 return PtInRect( &rect
, pt
);
82 /***********************************************************************
85 * Scroll-bar hit testing (don't confuse this with WM_NCHITTEST!).
87 static enum SCROLL_HITTEST
SCROLL_HitTest( HWND hwnd
, SCROLLBARINFO
* psbi
, BOOL vertical
,
88 POINT pt
, BOOL bDragging
)
90 if ( (bDragging
&& !SCROLL_PtInRectEx( &psbi
->rcScrollBar
, pt
, vertical
)) ||
91 (!PtInRect( &psbi
->rcScrollBar
, pt
)) )
93 return SCROLL_NOWHERE
;
98 if (pt
.y
< psbi
->rcScrollBar
.top
+ psbi
->dxyLineButton
)
99 return SCROLL_TOP_ARROW
;
100 if (pt
.y
>= psbi
->rcScrollBar
.bottom
- psbi
->dxyLineButton
)
101 return SCROLL_BOTTOM_ARROW
;
102 if (!psbi
->xyThumbTop
)
103 return SCROLL_TOP_RECT
;
104 pt
.y
-= psbi
->rcScrollBar
.top
;
105 if (pt
.y
< psbi
->xyThumbTop
)
106 return SCROLL_TOP_RECT
;
107 if (pt
.y
>= psbi
->xyThumbBottom
)
108 return SCROLL_BOTTOM_RECT
;
110 else /* horizontal */
112 if (pt
.x
< psbi
->rcScrollBar
.left
+ psbi
->dxyLineButton
)
113 return SCROLL_TOP_ARROW
;
114 if (pt
.x
>= psbi
->rcScrollBar
.right
- psbi
->dxyLineButton
)
115 return SCROLL_BOTTOM_ARROW
;
116 if (!psbi
->xyThumbTop
)
117 return SCROLL_TOP_RECT
;
118 pt
.x
-= psbi
->rcScrollBar
.left
;
119 if (pt
.x
< psbi
->xyThumbTop
)
120 return SCROLL_TOP_RECT
;
121 if (pt
.x
>= psbi
->xyThumbBottom
)
122 return SCROLL_BOTTOM_RECT
;
127 static void SCROLL_ThemeDrawPart(PDRAW_CONTEXT pcontext
, int iPartId
,int iStateId
, SCROLLBARINFO
* psbi
, int htCurrent
, int htDown
, int htHot
, RECT
* r
)
129 if(psbi
->rgstate
[htCurrent
] & STATE_SYSTEM_UNAVAILABLE
)
130 iStateId
+= BUTTON_DISABLED
- BUTTON_NORMAL
;
131 else if (htHot
== htCurrent
)
132 iStateId
+= BUTTON_HOT
- BUTTON_NORMAL
;
133 else if (htDown
== htCurrent
)
134 iStateId
+= BUTTON_PRESSED
- BUTTON_NORMAL
;
136 DrawThemeBackground(pcontext
->scrolltheme
, pcontext
->hDC
, iPartId
, iStateId
, r
, NULL
);
139 /***********************************************************************
142 * Draw the scroll bar arrows.
144 static void SCROLL_DrawArrows( PDRAW_CONTEXT pcontext
, SCROLLBARINFO
* psbi
,
145 BOOL vertical
, int htDown
, int htHot
)
150 r
= psbi
->rcScrollBar
;
153 r
.bottom
= r
.top
+ psbi
->dxyLineButton
;
154 iStateId
= ABS_UPNORMAL
;
158 r
.right
= r
.left
+ psbi
->dxyLineButton
;
159 iStateId
= ABS_LEFTNORMAL
;
162 SCROLL_ThemeDrawPart(pcontext
, SBP_ARROWBTN
, iStateId
, psbi
, SCROLL_TOP_ARROW
, htDown
, htHot
, &r
);
164 r
= psbi
->rcScrollBar
;
167 r
.top
= r
.bottom
- psbi
->dxyLineButton
;
168 iStateId
= ABS_DOWNNORMAL
;
172 iStateId
= ABS_RIGHTNORMAL
;
173 r
.left
= r
.right
- psbi
->dxyLineButton
;
176 SCROLL_ThemeDrawPart(pcontext
, SBP_ARROWBTN
, iStateId
, psbi
, SCROLL_BOTTOM_ARROW
, htDown
, htHot
, &r
);
179 static void SCROLL_DrawInterior( PDRAW_CONTEXT pcontext
, SCROLLBARINFO
* psbi
,
180 INT thumbPos
, BOOL vertical
,
181 int htDown
, int htHot
)
185 /* thumbPos is relative to the edge of the scrollbar */
187 r
= psbi
->rcScrollBar
;
190 thumbPos
+= pcontext
->wi
.rcClient
.top
- pcontext
->wi
.rcWindow
.top
;
191 r
.top
+= psbi
->dxyLineButton
;
192 r
.bottom
-= (psbi
->dxyLineButton
);
196 thumbPos
+= pcontext
->wi
.rcClient
.left
- pcontext
->wi
.rcWindow
.left
;
197 r
.left
+= psbi
->dxyLineButton
;
198 r
.right
-= psbi
->dxyLineButton
;
201 /* Draw the scroll rectangles and thumb */
203 if (!thumbPos
) /* No thumb to draw */
206 SCROLL_ThemeDrawPart(pcontext
, vertical
? SBP_UPPERTRACKVERT
: SBP_UPPERTRACKHORZ
, BUTTON_NORMAL
, psbi
, SCROLL_THUMB
, 0, 0, &rcPart
);
213 rcPart
.bottom
= thumbPos
;
214 SCROLL_ThemeDrawPart(pcontext
, SBP_UPPERTRACKVERT
, BUTTON_NORMAL
, psbi
, SCROLL_TOP_RECT
, htDown
, htHot
, &rcPart
);
215 r
.top
= rcPart
.bottom
;
218 rcPart
.top
+= psbi
->xyThumbBottom
- psbi
->xyThumbTop
;
219 SCROLL_ThemeDrawPart(pcontext
, SBP_LOWERTRACKVERT
, BUTTON_NORMAL
, psbi
, SCROLL_BOTTOM_RECT
, htDown
, htHot
, &rcPart
);
220 r
.bottom
= rcPart
.top
;
222 SCROLL_ThemeDrawPart(pcontext
, SBP_THUMBBTNVERT
, BUTTON_NORMAL
, psbi
, SCROLL_THUMB
, htDown
, htHot
, &r
);
223 SCROLL_ThemeDrawPart(pcontext
, SBP_GRIPPERVERT
, BUTTON_NORMAL
, psbi
, SCROLL_THUMB
, htDown
, htHot
, &r
);
225 else /* horizontal */
228 rcPart
.right
= thumbPos
;
229 SCROLL_ThemeDrawPart(pcontext
, SBP_UPPERTRACKHORZ
, BUTTON_NORMAL
, psbi
, SCROLL_TOP_RECT
, htDown
, htHot
, &rcPart
);
230 r
.left
= rcPart
.right
;
233 rcPart
.left
+= psbi
->xyThumbBottom
- psbi
->xyThumbTop
;
234 SCROLL_ThemeDrawPart(pcontext
, SBP_LOWERTRACKHORZ
, BUTTON_NORMAL
, psbi
, SCROLL_BOTTOM_RECT
, htDown
, htHot
, &rcPart
);
235 r
.right
= rcPart
.left
;
237 SCROLL_ThemeDrawPart(pcontext
, SBP_THUMBBTNHORZ
, BUTTON_NORMAL
, psbi
, SCROLL_THUMB
, htDown
, htHot
, &r
);
238 SCROLL_ThemeDrawPart(pcontext
, SBP_GRIPPERHORZ
, BUTTON_NORMAL
, psbi
, SCROLL_THUMB
, htDown
, htHot
, &r
);
242 static void SCROLL_DrawMovingThumb(PWND_CONTEXT pwndContext
, PDRAW_CONTEXT pcontext
, SCROLLBARINFO
* psbi
, BOOL vertical
)
244 INT pos
= pwndContext
->SCROLL_TrackingPos
;
248 max_size
= psbi
->rcScrollBar
.bottom
- psbi
->rcScrollBar
.top
;
250 max_size
= psbi
->rcScrollBar
.right
- psbi
->rcScrollBar
.left
;
252 max_size
-= psbi
->xyThumbBottom
- psbi
->xyThumbTop
+ psbi
->dxyLineButton
;
254 if( pos
< (psbi
->dxyLineButton
) )
255 pos
= (psbi
->dxyLineButton
);
256 else if( pos
> max_size
)
259 SCROLL_DrawInterior(pcontext
, psbi
, pos
, vertical
, SCROLL_THUMB
, 0);
261 pwndContext
->SCROLL_MovingThumb
= !pwndContext
->SCROLL_MovingThumb
;
266 ThemeDrawScrollBar(PDRAW_CONTEXT pcontext
, INT nBar
, POINT
* pt
)
271 enum SCROLL_HITTEST htHot
= SCROLL_NOWHERE
;
272 PWND_CONTEXT pwndContext
;
274 if (((nBar
== SB_VERT
) && !(pcontext
->wi
.dwStyle
& WS_VSCROLL
)) ||
275 ((nBar
== SB_HORZ
) && !(pcontext
->wi
.dwStyle
& WS_HSCROLL
))) return;
277 if (!(pwndContext
= ThemeGetWndContext(pcontext
->hWnd
)))
280 if (pwndContext
->SCROLL_TrackingWin
)
283 /* Retrieve scrollbar info */
284 sbi
.cbSize
= sizeof(sbi
);
285 si
.cbSize
= sizeof(si
);
287 GetScrollInfo(pcontext
->hWnd
, nBar
, &si
);
288 GetScrollBarInfo(pcontext
->hWnd
, SCROLL_getObjectId(nBar
), &sbi
);
289 vertical
= SCROLL_IsVertical(pcontext
->hWnd
, nBar
);
290 if(sbi
.rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
&&
291 sbi
.rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
296 /* The scrollbar rect is in screen coordinates */
297 OffsetRect(&sbi
.rcScrollBar
, -pcontext
->wi
.rcWindow
.left
, -pcontext
->wi
.rcWindow
.top
);
301 ScreenToWindow(pcontext
->hWnd
, pt
);
302 htHot
= SCROLL_HitTest(pcontext
->hWnd
, &sbi
, vertical
, *pt
, FALSE
);
305 /* do not draw if the scrollbar rectangle is empty */
306 if(IsRectEmpty(&sbi
.rcScrollBar
)) return;
308 /* Draw the scrollbar */
309 SCROLL_DrawArrows( pcontext
, &sbi
, vertical
, 0, htHot
);
310 SCROLL_DrawInterior( pcontext
, &sbi
, sbi
.xyThumbTop
, vertical
, 0, htHot
);
315 /***********************************************************************
318 static POINT
SCROLL_ClipPos( LPRECT lpRect
, POINT pt
)
320 if( pt
.x
< lpRect
->left
)
323 if( pt
.x
> lpRect
->right
)
324 pt
.x
= lpRect
->right
;
326 if( pt
.y
< lpRect
->top
)
329 if( pt
.y
> lpRect
->bottom
)
330 pt
.y
= lpRect
->bottom
;
337 /***********************************************************************
340 * Compute the current scroll position based on the thumb position in pixels
341 * from the top of the scroll-bar.
343 static UINT
SCROLL_GetThumbVal( SCROLLINFO
*psi
, RECT
*rect
,
344 BOOL vertical
, INT pos
)
347 INT pixels
= vertical
? rect
->bottom
-rect
->top
: rect
->right
-rect
->left
;
350 if ((pixels
-= 2*(GetSystemMetrics(SM_CXVSCROLL
) - SCROLL_ARROW_THUMB_OVERLAP
)) <= 0)
355 thumbSize
= MulDiv(pixels
,psi
->nPage
,(psi
->nMax
-psi
->nMin
+1));
356 if (thumbSize
< SCROLL_MIN_THUMB
) thumbSize
= SCROLL_MIN_THUMB
;
358 else thumbSize
= GetSystemMetrics(SM_CXVSCROLL
);
360 if ((pixels
-= thumbSize
) <= 0) return psi
->nMin
;
362 pos
= max( 0, pos
- (GetSystemMetrics(SM_CXVSCROLL
) - SCROLL_ARROW_THUMB_OVERLAP
) );
363 if (pos
> pixels
) pos
= pixels
;
366 range
= psi
->nMax
- psi
->nMin
;
368 range
= psi
->nMax
- psi
->nMin
- psi
->nPage
+ 1;
370 return psi
->nMin
+ MulDiv(pos
, range
, pixels
);
374 SCROLL_HandleScrollEvent(PWND_CONTEXT pwndContext
, HWND hwnd
, INT nBar
, UINT msg
, POINT pt
)
376 /* Previous mouse position for timer events */
378 /* Thumb position when tracking started. */
379 static UINT trackThumbPos
;
380 /* Position in the scroll-bar of the last button-down event. */
381 static INT lastClickPos
;
382 /* Position in the scroll-bar of the last mouse event. */
383 static INT lastMousePos
;
385 enum SCROLL_HITTEST hittest
;
386 HWND hwndOwner
, hwndCtl
;
390 DRAW_CONTEXT context
;
392 si
.cbSize
= sizeof(si
);
393 sbi
.cbSize
= sizeof(sbi
);
395 GetScrollInfo(hwnd
, nBar
, &si
);
396 GetScrollBarInfo(hwnd
, SCROLL_getObjectId(nBar
), &sbi
);
397 vertical
= SCROLL_IsVertical(hwnd
, nBar
);
398 if(sbi
.rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
&&
399 sbi
.rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
404 if ((pwndContext
->SCROLL_trackHitTest
== SCROLL_NOWHERE
) && (msg
!= WM_LBUTTONDOWN
))
407 ThemeInitDrawContext(&context
, hwnd
, 0);
409 /* The scrollbar rect is in screen coordinates */
410 OffsetRect(&sbi
.rcScrollBar
, -context
.wi
.rcWindow
.left
, -context
.wi
.rcWindow
.top
);
412 hwndOwner
= (nBar
== SB_CTL
) ? GetParent(hwnd
) : hwnd
;
413 hwndCtl
= (nBar
== SB_CTL
) ? hwnd
: 0;
417 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
418 HideCaret(hwnd
); /* hide caret while holding down LBUTTON */
419 pwndContext
->SCROLL_trackVertical
= vertical
;
420 pwndContext
->SCROLL_trackHitTest
= hittest
= SCROLL_HitTest( hwnd
, &sbi
, vertical
, pt
, FALSE
);
421 lastClickPos
= vertical
? (pt
.y
- sbi
.rcScrollBar
.top
) : (pt
.x
- sbi
.rcScrollBar
.left
);
422 lastMousePos
= lastClickPos
;
423 trackThumbPos
= sbi
.xyThumbTop
;
429 hittest
= SCROLL_HitTest( hwnd
, &sbi
, vertical
, pt
, TRUE
);
434 hittest
= SCROLL_NOWHERE
;
436 /* if scrollbar has focus, show back caret */
437 if (hwnd
==GetFocus())
443 hittest
= SCROLL_HitTest( hwnd
, &sbi
, vertical
, pt
, FALSE
);
447 return; /* Should never happen */
450 //TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
451 // hwnd, nBar, SPY_GetMsgName(msg,hwnd), pt.x, pt.y, hittest );
453 switch(pwndContext
->SCROLL_trackHitTest
)
455 case SCROLL_NOWHERE
: /* No tracking in progress */
458 case SCROLL_TOP_ARROW
:
459 if (hittest
== pwndContext
->SCROLL_trackHitTest
)
461 SCROLL_DrawArrows( &context
, &sbi
, vertical
, pwndContext
->SCROLL_trackHitTest
, 0 );
462 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
464 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
465 SB_LINEUP
, (LPARAM
)hwndCtl
);
468 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
469 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
, NULL
);
473 SCROLL_DrawArrows( &context
, &sbi
, vertical
, 0, 0 );
474 KillSystemTimer( hwnd
, SCROLL_TIMER
);
479 case SCROLL_TOP_RECT
:
480 SCROLL_DrawInterior( &context
, &sbi
, sbi
.xyThumbTop
, vertical
, pwndContext
->SCROLL_trackHitTest
, 0);
481 if (hittest
== pwndContext
->SCROLL_trackHitTest
)
483 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
485 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
486 SB_PAGEUP
, (LPARAM
)hwndCtl
);
488 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
489 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
, NULL
);
491 else KillSystemTimer( hwnd
, SCROLL_TIMER
);
495 if (msg
== WM_LBUTTONDOWN
)
497 pwndContext
->SCROLL_TrackingWin
= hwnd
;
498 pwndContext
->SCROLL_TrackingBar
= nBar
;
499 pwndContext
->SCROLL_TrackingPos
= trackThumbPos
+ lastMousePos
- lastClickPos
;
500 pwndContext
->SCROLL_TrackingVal
= SCROLL_GetThumbVal( &si
, &sbi
.rcScrollBar
,
501 vertical
, pwndContext
->SCROLL_TrackingPos
);
502 if (!pwndContext
->SCROLL_MovingThumb
)
503 SCROLL_DrawMovingThumb(pwndContext
, &context
, &sbi
, vertical
);
505 else if (msg
== WM_LBUTTONUP
)
507 if (pwndContext
->SCROLL_MovingThumb
)
508 SCROLL_DrawMovingThumb(pwndContext
, &context
, &sbi
, vertical
);
510 SCROLL_DrawInterior( &context
, &sbi
, sbi
.xyThumbTop
, vertical
, 0, pwndContext
->SCROLL_trackHitTest
);
512 else /* WM_MOUSEMOVE */
516 if (!SCROLL_PtInRectEx( &sbi
.rcScrollBar
, pt
, vertical
))
520 pt
= SCROLL_ClipPos( &sbi
.rcScrollBar
, pt
);
521 pos
= vertical
? (pt
.y
- sbi
.rcScrollBar
.top
) : (pt
.x
- sbi
.rcScrollBar
.left
);
523 if ( (pos
!= lastMousePos
) || (!pwndContext
->SCROLL_MovingThumb
) )
525 if (pwndContext
->SCROLL_MovingThumb
)
526 SCROLL_DrawMovingThumb(pwndContext
, &context
, &sbi
, vertical
);
528 pwndContext
->SCROLL_TrackingPos
= trackThumbPos
+ pos
- lastClickPos
;
529 pwndContext
->SCROLL_TrackingVal
= SCROLL_GetThumbVal( &si
, &sbi
.rcScrollBar
,
531 pwndContext
->SCROLL_TrackingPos
);
532 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
533 MAKEWPARAM( SB_THUMBTRACK
, pwndContext
->SCROLL_TrackingVal
),
535 if (!pwndContext
->SCROLL_MovingThumb
)
536 SCROLL_DrawMovingThumb(pwndContext
, &context
, &sbi
, vertical
);
541 case SCROLL_BOTTOM_RECT
:
542 if (hittest
== pwndContext
->SCROLL_trackHitTest
)
544 SCROLL_DrawInterior( &context
, &sbi
, sbi
.xyThumbTop
, vertical
, pwndContext
->SCROLL_trackHitTest
, 0 );
545 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
547 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
548 SB_PAGEDOWN
, (LPARAM
)hwndCtl
);
550 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
551 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
, NULL
);
555 SCROLL_DrawInterior( &context
, &sbi
, sbi
.xyThumbTop
, vertical
, 0, 0 );
556 KillSystemTimer( hwnd
, SCROLL_TIMER
);
560 case SCROLL_BOTTOM_ARROW
:
561 if (hittest
== pwndContext
->SCROLL_trackHitTest
)
563 SCROLL_DrawArrows( &context
, &sbi
, vertical
, pwndContext
->SCROLL_trackHitTest
, 0 );
564 if ((msg
== WM_LBUTTONDOWN
) || (msg
== WM_SYSTIMER
))
566 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
567 SB_LINEDOWN
, (LPARAM
)hwndCtl
);
570 SetSystemTimer( hwnd
, SCROLL_TIMER
, (msg
== WM_LBUTTONDOWN
) ?
571 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
, NULL
);
575 SCROLL_DrawArrows( &context
, &sbi
, vertical
, 0, 0 );
576 KillSystemTimer( hwnd
, SCROLL_TIMER
);
581 if (msg
== WM_LBUTTONDOWN
)
584 if (hittest
== SCROLL_THUMB
)
586 UINT val
= SCROLL_GetThumbVal( &si
, &sbi
.rcScrollBar
, vertical
,
587 trackThumbPos
+ lastMousePos
- lastClickPos
);
588 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
589 MAKEWPARAM( SB_THUMBTRACK
, val
), (LPARAM
)hwndCtl
);
593 if (msg
== WM_LBUTTONUP
)
595 hittest
= pwndContext
->SCROLL_trackHitTest
;
596 pwndContext
->SCROLL_trackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
598 if (hittest
== SCROLL_THUMB
)
600 UINT val
= SCROLL_GetThumbVal( &si
, &sbi
.rcScrollBar
, vertical
,
601 trackThumbPos
+ lastMousePos
- lastClickPos
);
602 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
603 MAKEWPARAM( SB_THUMBPOSITION
, val
), (LPARAM
)hwndCtl
);
605 /* SB_ENDSCROLL doesn't report thumb position */
606 SendMessageW( hwndOwner
, vertical
? WM_VSCROLL
: WM_HSCROLL
,
607 SB_ENDSCROLL
, (LPARAM
)hwndCtl
);
609 /* Terminate tracking */
610 pwndContext
->SCROLL_TrackingWin
= 0;
613 ThemeCleanupDrawContext(&context
);
617 SCROLL_TrackScrollBar( HWND hwnd
, INT scrollbar
, POINT pt
)
620 PWND_CONTEXT pwndContext
= ThemeGetWndContext(hwnd
);
624 ScreenToWindow(hwnd
, &pt
);
626 SCROLL_HandleScrollEvent(pwndContext
, hwnd
, scrollbar
, WM_LBUTTONDOWN
, pt
);
630 if (!GetMessageW( &msg
, 0, 0, 0 )) break;
631 if (CallMsgFilterW( &msg
, MSGF_SCROLLBAR
)) continue;
632 if (msg
.message
== WM_LBUTTONUP
||
633 msg
.message
== WM_MOUSEMOVE
||
634 (msg
.message
== WM_SYSTIMER
&& msg
.wParam
== SCROLL_TIMER
))
636 pt
.x
= GET_X_LPARAM(msg
.lParam
);
637 pt
.y
= GET_Y_LPARAM(msg
.lParam
);
638 ClientToScreen(hwnd
, &pt
);
639 ScreenToWindow(hwnd
, &pt
);
640 SCROLL_HandleScrollEvent(pwndContext
, hwnd
, scrollbar
, msg
.message
, pt
);
644 TranslateMessage( &msg
);
645 DispatchMessageW( &msg
);
647 if (!IsWindow( hwnd
))
652 } while (msg
.message
!= WM_LBUTTONUP
&& GetCapture() == hwnd
);
655 void NC_TrackScrollBar( HWND hwnd
, WPARAM wParam
, POINT pt
)
659 if ((wParam
& 0xfff0) == SC_HSCROLL
)
661 if ((wParam
& 0x0f) != HTHSCROLL
) return;
664 else /* SC_VSCROLL */
666 if ((wParam
& 0x0f) != HTVSCROLL
) return;
669 SCROLL_TrackScrollBar( hwnd
, scrollbar
, pt
);