2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: subsys/win32k/ntuser/scrollbar.c
6 * PROGRAMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
7 * Jason Filby (jasonfilby@yahoo.com)
11 DBG_DEFAULT_CHANNEL(UserScrollbar
);
13 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
14 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
15 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
16 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
17 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
18 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
19 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
21 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
22 holding the button down */
23 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
25 #define SCROLL_TIMER 0 /* Scroll timer id */
27 /* Minimum size of the rectangle between the arrows */
28 #define SCROLL_MIN_RECT 4
30 /* Minimum size of the thumb in pixels */
31 #define SCROLL_MIN_THUMB 6
33 /* Overlap between arrows and thumb */
34 #define SCROLL_ARROW_THUMB_OVERLAP 0
39 #define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
41 /* What to do after SetScrollInfo() */
42 #define SA_SSI_HIDE 0x0001
43 #define SA_SSI_SHOW 0x0002
44 #define SA_SSI_REFRESH 0x0004
45 #define SA_SSI_REPAINT_ARROWS 0x0008
47 #define SBRG_SCROLLBAR 0 /* The scrollbar itself */
48 #define SBRG_TOPRIGHTBTN 1 /* The top or right button */
49 #define SBRG_PAGEUPRIGHT 2 /* The page up or page right region */
50 #define SBRG_SCROLLBOX 3 /* The scroll box */
51 #define SBRG_PAGEDOWNLEFT 4 /* The page down or page left region */
52 #define SBRG_BOTTOMLEFTBTN 5 /* The bottom or left button */
54 #define CHANGERGSTATE(item, status) \
55 if(Info->rgstate[(item)] != (status)) \
57 Info->rgstate[(item)] = (status);
59 /* FUNCTIONS *****************************************************************/
61 /* Ported from WINE20020904 */
62 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
63 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
64 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
65 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
67 static inline void mirror_rect( const RECT
*window_rect
, RECT
*rect
)
69 int width
= window_rect
->right
- window_rect
->left
;
71 rect
->left
= width
- rect
->right
;
72 rect
->right
= width
- tmp
;
76 IntGetSBData(PWND pwnd
, INT Bar
)
81 pSBInfo
= pwnd
->pSBInfo
;
85 return &pSBInfo
->Horz
;
87 return &pSBInfo
->Vert
;
89 if ( pwnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
91 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
94 pSBWnd
= (PSBWND
)pwnd
;
95 return (PSBDATA
)&pSBWnd
->SBCalc
;
97 ERR("IntGetSBData Bad Bar!\n");
103 IntGetScrollBarRect (PWND Wnd
, INT nBar
, RECTL
*lprect
)
106 *lprect
= Wnd
->rcClient
;
108 RECTL_vOffsetRect( lprect
, -Wnd
->rcWindow
.left
, -Wnd
->rcWindow
.top
);
109 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
110 mirror_rect( &Wnd
->rcWindow
, lprect
);
115 lprect
->top
= lprect
->bottom
;
116 lprect
->bottom
+= UserGetSystemMetrics (SM_CYHSCROLL
);
117 if (Wnd
->style
& WS_BORDER
)
122 else if (Wnd
->style
& WS_VSCROLL
)
130 if(Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
)
132 lprect
->right
= lprect
->left
;
133 lprect
->left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
137 lprect
->left
= lprect
->right
;
138 lprect
->right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
140 if (Wnd
->style
& WS_BORDER
)
145 else if (Wnd
->style
& WS_HSCROLL
)
153 IntGetClientRect (Wnd
, lprect
);
154 vertical
= !!(Wnd
->style
& SBS_VERT
);
165 IntCalculateThumb(PWND Wnd
, LONG idObject
, PSCROLLBARINFO psbi
, PSBDATA pSBData
)
167 INT Thumb
, ThumbBox
, ThumbPos
, cxy
, mx
;
173 Thumb
= UserGetSystemMetrics(SM_CXHSCROLL
);
174 cxy
= psbi
->rcScrollBar
.right
- psbi
->rcScrollBar
.left
;
177 Thumb
= UserGetSystemMetrics(SM_CYVSCROLL
);
178 cxy
= psbi
->rcScrollBar
.bottom
- psbi
->rcScrollBar
.top
;
181 IntGetClientRect(Wnd
, &ClientRect
);
182 if(Wnd
->style
& SBS_VERT
)
184 Thumb
= UserGetSystemMetrics(SM_CYVSCROLL
);
185 cxy
= ClientRect
.bottom
- ClientRect
.top
;
189 Thumb
= UserGetSystemMetrics(SM_CXHSCROLL
);
190 cxy
= ClientRect
.right
- ClientRect
.left
;
198 /* Calculate Thumb */
199 if(cxy
<= (2 * Thumb
))
202 psbi
->xyThumbTop
= 0;
203 psbi
->xyThumbBottom
= 0;
208 ThumbBox
= pSBData
->page
? MINTRACKTHUMB
: UserGetSystemMetrics(SM_CXHTHUMB
);
214 ThumbBox
= max(EngMulDiv(cxy
, pSBData
->page
, pSBData
->posMax
- pSBData
->posMin
+ 1), ThumbBox
);
219 mx
= pSBData
->posMax
- max(pSBData
->page
- 1, 0);
220 if(pSBData
->posMin
< mx
)
221 ThumbPos
= Thumb
+ EngMulDiv(cxy
- ThumbBox
, pSBData
->pos
- pSBData
->posMin
, mx
- pSBData
->posMin
);
223 ThumbPos
= Thumb
+ ThumbBox
;
226 psbi
->xyThumbTop
= ThumbPos
;
227 psbi
->xyThumbBottom
= ThumbPos
+ ThumbBox
;
231 psbi
->xyThumbTop
= 0;
232 psbi
->xyThumbBottom
= 0;
235 psbi
->dxyLineButton
= Thumb
;
241 IntUpdateSBInfo(PWND Window, int wBar)
247 ASSERT(Window->pSBInfo);
248 ASSERT(Window->pSBInfoex);
250 sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
251 pSBData = IntGetSBData(Window, wBar);
252 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
253 IntCalculateThumb(Window, wBar, sbi, pSBData);
257 co_IntGetScrollInfo(PWND Window
, INT nBar
, PSBDATA pSBData
, LPSCROLLINFO lpsi
)
262 ASSERT_REFS_CO(Window
);
264 if(!SBID_IS_VALID(nBar
))
266 EngSetLastError(ERROR_INVALID_PARAMETER
);
267 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar
);
271 if (!Window
->pSBInfo
)
273 ERR("IntGetScrollInfo No window scrollbar info!\n");
277 psi
= IntGetScrollInfoFromWindow(Window
, nBar
);
279 if (lpsi
->fMask
== SIF_ALL
)
281 Mask
= SIF_PAGE
| SIF_POS
| SIF_RANGE
| SIF_TRACKPOS
;
288 if (0 != (Mask
& SIF_PAGE
))
290 lpsi
->nPage
= psi
->nPage
;
293 if (0 != (Mask
& SIF_POS
))
295 lpsi
->nPos
= psi
->nPos
;
298 if (0 != (Mask
& SIF_RANGE
))
300 lpsi
->nMin
= psi
->nMin
;
301 lpsi
->nMax
= psi
->nMax
;
304 if (0 != (Mask
& SIF_TRACKPOS
))
306 lpsi
->nTrackPos
= psi
->nTrackPos
;
313 NEWco_IntGetScrollInfo(
320 PSBTRACK pSBTrack
= pWnd
->head
.pti
->pSBTrack
;
322 if (!SBID_IS_VALID(nBar
))
324 EngSetLastError(ERROR_INVALID_PARAMETER
);
325 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar
);
329 if (!pWnd
->pSBInfo
|| !pSBTrack
) return FALSE
;
333 if (0 != (Mask
& SIF_PAGE
))
335 lpsi
->nPage
= pSBData
->page
;
338 if (0 != (Mask
& SIF_POS
))
340 lpsi
->nPos
= pSBData
->pos
;
343 if (0 != (Mask
& SIF_RANGE
))
345 lpsi
->nMin
= pSBData
->posMin
;
346 lpsi
->nMax
= pSBData
->posMax
;
349 if (0 != (Mask
& SIF_TRACKPOS
))
352 pSBTrack
->nBar
== nBar
&&
353 pSBTrack
->spwndTrack
== pWnd
)
354 lpsi
->nTrackPos
= pSBTrack
->posNew
;
356 lpsi
->nTrackPos
= pSBData
->pos
;
358 return (Mask
& SIF_ALL
) !=0;
361 static DWORD FASTCALL
362 co_IntSetScrollInfo(PWND Window
, INT nBar
, LPCSCROLLINFO lpsi
, BOOL bRedraw
)
365 * Update the scrollbar state and set action flags according to
366 * what has to be done graphics wise.
375 BOOL bChangeParams
= FALSE
; /* Don't show/hide scrollbar if params don't change */
379 ASSERT_REFS_CO(Window
);
381 if(!SBID_IS_VALID(nBar
))
383 EngSetLastError(ERROR_INVALID_PARAMETER
);
384 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar
);
388 if(!co_IntCreateScrollBars(Window
))
393 if (lpsi
->cbSize
!= sizeof(SCROLLINFO
) &&
394 lpsi
->cbSize
!= (sizeof(SCROLLINFO
) - sizeof(lpsi
->nTrackPos
)))
396 EngSetLastError(ERROR_INVALID_PARAMETER
);
399 if (lpsi
->fMask
& ~(SIF_ALL
| SIF_DISABLENOSCROLL
| SIF_PREVIOUSPOS
))
401 EngSetLastError(ERROR_INVALID_PARAMETER
);
405 psbi
= IntGetScrollbarInfoFromWindow(Window
, nBar
);
406 Info
= IntGetScrollInfoFromWindow(Window
, nBar
);
407 pSBData
= IntGetSBData(Window
, nBar
);
409 /* Set the page size */
410 if (lpsi
->fMask
& SIF_PAGE
)
412 if (Info
->nPage
!= lpsi
->nPage
)
414 Info
->nPage
= lpsi
->nPage
;
415 pSBData
->page
= lpsi
->nPage
;
416 bChangeParams
= TRUE
;
420 /* Set the scroll pos */
421 if (lpsi
->fMask
& SIF_POS
)
423 if (Info
->nPos
!= lpsi
->nPos
)
426 Info
->nPos
= lpsi
->nPos
;
427 pSBData
->pos
= lpsi
->nPos
;
428 bChangeParams
= TRUE
;
432 /* Set the scroll range */
433 if (lpsi
->fMask
& SIF_RANGE
)
435 if (lpsi
->nMin
> lpsi
->nMax
)
437 Info
->nMin
= lpsi
->nMin
;
438 Info
->nMax
= lpsi
->nMin
;
439 pSBData
->posMin
= lpsi
->nMin
;
440 pSBData
->posMax
= lpsi
->nMin
;
441 bChangeParams
= TRUE
;
443 else if (Info
->nMin
!= lpsi
->nMin
|| Info
->nMax
!= lpsi
->nMax
)
445 Info
->nMin
= lpsi
->nMin
;
446 Info
->nMax
= lpsi
->nMax
;
447 pSBData
->posMin
= lpsi
->nMin
;
448 pSBData
->posMax
= lpsi
->nMax
;
449 bChangeParams
= TRUE
;
453 /* Make sure the page size is valid */
454 MaxPage
= abs(Info
->nMax
- Info
->nMin
) + 1;
455 if (Info
->nPage
> MaxPage
)
457 pSBData
->page
= Info
->nPage
= MaxPage
;
460 /* Make sure the pos is inside the range */
461 MaxPos
= Info
->nMax
+ 1 - (int)max(Info
->nPage
, 1);
462 ASSERT(MaxPos
>= Info
->nMin
);
463 if (Info
->nPos
< Info
->nMin
)
465 pSBData
->pos
= Info
->nPos
= Info
->nMin
;
467 else if (Info
->nPos
> MaxPos
)
469 pSBData
->pos
= Info
->nPos
= MaxPos
;
473 * Don't change the scrollbar state if SetScrollInfo is just called
474 * with SIF_DISABLENOSCROLL
476 if (!(lpsi
->fMask
& SIF_ALL
))
479 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
;
482 /* Check if the scrollbar should be hidden or disabled */
483 if (lpsi
->fMask
& (SIF_RANGE
| SIF_PAGE
| SIF_DISABLENOSCROLL
))
485 new_flags
= Window
->pSBInfo
->WSBflags
;
486 if (Info
->nMin
>= (int)(Info
->nMax
- max(Info
->nPage
- 1, 0)))
488 /* Hide or disable scroll-bar */
489 if (lpsi
->fMask
& SIF_DISABLENOSCROLL
)
491 new_flags
= ESB_DISABLE_BOTH
;
492 bChangeParams
= TRUE
;
494 else if ((nBar
!= SB_CTL
) && bChangeParams
)
496 action
= SA_SSI_HIDE
;
499 else /* Show and enable scroll-bar only if no page only changed. */
500 if (lpsi
->fMask
!= SIF_PAGE
)
502 new_flags
= ESB_ENABLE_BOTH
;
503 if ((nBar
!= SB_CTL
) && bChangeParams
)
505 action
|= SA_SSI_SHOW
;
509 if (Window
->pSBInfo
->WSBflags
!= new_flags
) /* Check arrow flags */
511 Window
->pSBInfo
->WSBflags
= new_flags
;
512 action
|= SA_SSI_REPAINT_ARROWS
;
517 if ( action
& SA_SSI_HIDE
)
519 co_UserShowScrollBar(Window
, nBar
, FALSE
, FALSE
);
523 if ( action
& SA_SSI_SHOW
)
524 if ( co_UserShowScrollBar(Window
, nBar
, TRUE
, TRUE
) )
525 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
; /* SetWindowPos() already did the painting */
527 { // FIXME: Arrows and interior.
528 RECTL UpdateRect
= psbi
->rcScrollBar
;
529 UpdateRect
.left
-= Window
->rcClient
.left
- Window
->rcWindow
.left
;
530 UpdateRect
.right
-= Window
->rcClient
.left
- Window
->rcWindow
.left
;
531 UpdateRect
.top
-= Window
->rcClient
.top
- Window
->rcWindow
.top
;
532 UpdateRect
.bottom
-= Window
->rcClient
.top
- Window
->rcWindow
.top
;
533 co_UserRedrawWindow(Window
, &UpdateRect
, 0, RDW_INVALIDATE
| RDW_FRAME
);
535 /* else if( action & SA_SSI_REPAINT_ARROWS )
537 RECTL UpdateRect = psbi->rcScrollBar;
538 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
539 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
540 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
541 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
542 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
545 /* Return current position */
546 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
;
550 co_IntGetScrollBarInfo(PWND Window
, LONG idObject
, PSCROLLBARINFO psbi
)
555 ASSERT_REFS_CO(Window
);
557 Bar
= SBOBJ_TO_SBID(idObject
);
559 if(!SBID_IS_VALID(Bar
))
561 EngSetLastError(ERROR_INVALID_PARAMETER
);
562 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar
);
566 if(!co_IntCreateScrollBars(Window
))
568 ERR("Failed to create scrollbars for window.\n");
572 sbi
= IntGetScrollbarInfoFromWindow(Window
, Bar
);
573 pSBData
= IntGetSBData(Window
, Bar
);
575 IntGetScrollBarRect(Window
, Bar
, &(sbi
->rcScrollBar
));
576 IntCalculateThumb(Window
, Bar
, sbi
, pSBData
);
578 RtlCopyMemory(psbi
, sbi
, sizeof(SCROLLBARINFO
));
584 co_IntSetScrollBarInfo(PWND Window
, LONG idObject
, PSETSCROLLBARINFO psbi
)
589 ASSERT_REFS_CO(Window
);
591 Bar
= SBOBJ_TO_SBID(idObject
);
593 if(!SBID_IS_VALID(Bar
))
595 EngSetLastError(ERROR_INVALID_PARAMETER
);
596 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar
);
600 if(!co_IntCreateScrollBars(Window
))
602 ERR("Failed to create scrollbars for window.\n");
606 sbi
= IntGetScrollbarInfoFromWindow(Window
, Bar
);
607 psi
= IntGetScrollInfoFromWindow(Window
, Bar
);
609 psi
->nTrackPos
= psbi
->nTrackPos
;
610 sbi
->reserved
= psbi
->reserved
;
611 RtlCopyMemory(&sbi
->rgstate
, &psbi
->rgstate
, sizeof(psbi
->rgstate
));
617 co_IntCreateScrollBars(PWND Window
)
624 ASSERT_REFS_CO(Window
);
626 if (Window
->pSBInfo
&& Window
->pSBInfoex
)
628 /* No need to create it anymore */
632 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
633 Size
= 3 * (sizeof(SBINFOEX
));
634 if(!(Window
->pSBInfoex
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_SBARINFO
)))
636 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window
->head
.h
);
640 RtlZeroMemory(Window
->pSBInfoex
, Size
);
642 if(!(Window
->pSBInfo
= DesktopHeapAlloc( Window
->head
.rpdesk
, sizeof(SBINFO
))))
644 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window
->head
.h
);
648 RtlZeroMemory(Window
->pSBInfo
, sizeof(SBINFO
));
649 Window
->pSBInfo
->Vert
.posMax
= 100;
650 Window
->pSBInfo
->Horz
.posMax
= 100;
652 co_WinPosGetNonClientSize(Window
,
656 for(s
= SB_HORZ
; s
<= SB_VERT
; s
++)
658 psbi
= IntGetScrollbarInfoFromWindow(Window
, s
);
659 psbi
->cbSize
= sizeof(SCROLLBARINFO
);
660 for (i
= 0; i
< CCHILDREN_SCROLLBAR
+ 1; i
++)
661 psbi
->rgstate
[i
] = 0;
663 pSBData
= IntGetSBData(Window
, s
);
665 IntGetScrollBarRect(Window
, s
, &(psbi
->rcScrollBar
));
666 IntCalculateThumb(Window
, s
, psbi
, pSBData
);
673 IntDestroyScrollBars(PWND Window
)
675 if (Window
->pSBInfo
&& Window
->pSBInfoex
)
677 DesktopHeapFree(Window
->head
.rpdesk
, Window
->pSBInfo
);
678 Window
->pSBInfo
= NULL
;
679 ExFreePoolWithTag(Window
->pSBInfoex
, TAG_SBARINFO
);
680 Window
->pSBInfoex
= NULL
;
687 IntEnableScrollBar(BOOL Horz
, PSCROLLBARINFO Info
, UINT wArrows
)
692 case ESB_DISABLE_BOTH
:
693 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
694 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
696 case ESB_DISABLE_RTDN
:
699 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
703 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
706 case ESB_DISABLE_LTUP
:
709 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
713 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
716 case ESB_ENABLE_BOTH
:
717 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, 0);
718 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, 0);
724 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
726 co_UserShowScrollBar(PWND Wnd
, int nBar
, BOOL fShowH
, BOOL fShowV
)
728 ULONG old_style
, set_bits
= 0, clear_bits
= 0;
736 //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
738 co_WinPosShowWindow(Wnd
, fShowH
? SW_SHOW
: SW_HIDE
);
743 if (fShowH
) set_bits
|= WS_HSCROLL
;
744 else clear_bits
|= WS_HSCROLL
;
745 if( nBar
== SB_HORZ
) break;
748 if (fShowV
) set_bits
|= WS_VSCROLL
;
749 else clear_bits
|= WS_VSCROLL
;
752 EngSetLastError(ERROR_INVALID_PARAMETER
);
756 old_style
= IntSetStyle( Wnd
, set_bits
, clear_bits
);
757 if ((old_style
& clear_bits
) != 0 || (old_style
& set_bits
) != set_bits
)
759 ///// Is this needed? Was tested w/o!
760 //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
761 //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
763 /* Frame has been changed, let the window redraw itself */
764 co_WinPosSetWindowPos(Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
765 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
| SWP_NOSENDCHANGING
);
772 IntDrawScrollInterior(PWND pWnd
, HDC hDC
, INT nBar
, BOOL Vertical
, PSCROLLBARINFO ScrollBarInfo
)
774 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
775 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
777 HBRUSH hSaveBrush
, hBrush
;
778 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
780 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
782 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
783 BottomSelected
= TRUE
;
786 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
787 * The window-owned scrollbars need to call DefWndControlColor
788 * to correctly setup default scrollbar colors
792 hBrush
= GetControlBrush( pWnd
, hDC
, WM_CTLCOLORSCROLLBAR
);
794 hBrush
= IntGetSysColorBrush(COLOR_SCROLLBAR
);
798 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
801 hSaveBrush
= NtGdiSelectBrush(hDC
, hBrush
);
803 /* Calculate the scroll rectangle */
806 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
807 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
808 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
809 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
813 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
814 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
815 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
816 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
819 /* Draw the scroll rectangles and thumb */
820 if (!ScrollBarInfo
->xyThumbBottom
)
822 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
823 Rect
.bottom
- Rect
.top
, PATCOPY
);
825 /* Cleanup and return */
826 NtGdiSelectBrush(hDC
, hSaveBrush
);
830 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
832 if (ScrollBarInfo
->dxyLineButton
)
838 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
839 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
840 Rect
.top
+= ThumbTop
;
841 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
842 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
843 Rect
.bottom
= Rect
.top
+ ThumbSize
;
849 NtGdiPatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
850 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
858 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
859 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
860 Rect
.left
+= ThumbTop
;
861 NtGdiPatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
862 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
863 BottomSelected
? BLACKNESS
: PATCOPY
);
864 Rect
.right
= Rect
.left
+ ThumbSize
;
870 NtGdiPatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
871 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
879 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
882 NtGdiSelectBrush(hDC
, hSaveBrush
);
887 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
890 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
892 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
895 ScrollDirFlagLT
= DFCS_SCROLLUP
;
896 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
897 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
898 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
902 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
903 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
904 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
905 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
908 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
910 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
912 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
914 ScrollDirFlagLT
|= DFCS_INACTIVE
;
916 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
918 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
920 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
922 ScrollDirFlagRB
|= DFCS_INACTIVE
;
925 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
926 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
930 IntScrollGetObjectId(INT SBType
)
932 if (SBType
== SB_VERT
)
933 return OBJID_VSCROLL
;
934 if (SBType
== SB_HORZ
)
935 return OBJID_HSCROLL
;
940 IntDrawScrollBar(PWND Wnd
, HDC DC
, INT Bar
)
948 pti
= PsGetCurrentThreadWin32Thread();
951 * Get scroll bar info.
964 Vertical
= (Wnd
->style
& SBS_VERT
) != 0;
971 if (!co_IntGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), &Info
))
976 if (RECTL_bIsEmptyRect(&Info
.rcScrollBar
))
981 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
986 if (Info
.dxyLineButton
)
988 IntDrawScrollArrows(DC
, &Info
, Vertical
);
994 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
997 * If scroll bar has focus, reposition the caret.
999 if ( Wnd
== pti
->MessageQueue
->spwndFocus
&& Bar
== SB_CTL
)
1003 co_IntSetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
1007 co_IntSetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
1014 ScrollBarWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1016 LRESULT lResult
= 0;
1018 pWnd
= UserGetWindowObject(hWnd
);
1019 if (!pWnd
) return 0;
1027 pWnd
->pSBInfo
->WSBflags
= wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
;
1039 NtUserGetScrollBarInfo(HWND hWnd
, LONG idObject
, PSCROLLBARINFO psbi
)
1045 DECLARE_RETURN(BOOL
);
1046 USER_REFERENCE_ENTRY Ref
;
1048 TRACE("Enter NtUserGetScrollBarInfo\n");
1049 UserEnterExclusive();
1051 Status
= MmCopyFromCaller(&sbi
, psbi
, sizeof(SCROLLBARINFO
));
1052 if(!NT_SUCCESS(Status
) || (sbi
.cbSize
!= sizeof(SCROLLBARINFO
)))
1054 SetLastNtError(Status
);
1058 if(!(Window
= UserGetWindowObject(hWnd
)))
1063 UserRefObjectCo(Window
, &Ref
);
1064 Ret
= co_IntGetScrollBarInfo(Window
, idObject
, &sbi
);
1065 UserDerefObjectCo(Window
);
1067 Status
= MmCopyToCaller(psbi
, &sbi
, sizeof(SCROLLBARINFO
));
1068 if(!NT_SUCCESS(Status
))
1070 SetLastNtError(Status
);
1077 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_
);
1095 DECLARE_RETURN(BOOL
);
1096 USER_REFERENCE_ENTRY Ref
;
1098 TRACE("Enter NtUserGetScrollInfo\n");
1103 RtlCopyMemory(&psi
, lpsi
, sizeof(SCROLLINFO
));
1106 RtlCopyMemory(&SBDataSafe
, pSBData
, sizeof(SBDATA
));
1109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1111 ERR("NtUserGetScrollInfo Failed size.\n");
1112 SetLastNtError(_SEH2_GetExceptionCode());
1113 _SEH2_YIELD(RETURN(FALSE
));
1117 if(!(Window
= UserGetWindowObject(hWnd
)))
1119 ERR("NtUserGetScrollInfo Bad window.\n");
1123 UserRefObjectCo(Window
, &Ref
);
1124 Ret
= co_IntGetScrollInfo(Window
, fnBar
, &SBDataSafe
, &psi
);
1125 UserDerefObjectCo(Window
);
1129 RtlCopyMemory(lpsi
, &psi
, sizeof(SCROLLINFO
));
1131 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1133 ERR("NtUserGetScrollInfo Failed copy to user.\n");
1134 SetLastNtError(_SEH2_GetExceptionCode());
1135 _SEH2_YIELD(RETURN(FALSE
));
1142 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_
);
1149 NtUserEnableScrollBar(
1156 PSCROLLBARINFO InfoV
= NULL
, InfoH
= NULL
;
1158 DECLARE_RETURN(BOOL
);
1159 USER_REFERENCE_ENTRY Ref
;
1161 TRACE("Enter NtUserEnableScrollBar\n");
1162 UserEnterExclusive();
1164 if (!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
1165 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
1166 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
1170 UserRefObjectCo(Window
, &Ref
);
1172 if (!co_IntCreateScrollBars(Window
))
1177 OrigArrows
= Window
->pSBInfo
->WSBflags
;
1178 Window
->pSBInfo
->WSBflags
= wArrows
;
1180 if (wSBflags
== SB_CTL
)
1182 if ((wArrows
== ESB_DISABLE_BOTH
|| wArrows
== ESB_ENABLE_BOTH
))
1183 IntEnableWindow(hWnd
, (wArrows
== ESB_ENABLE_BOTH
));
1188 if(wSBflags
!= SB_BOTH
&& !SBID_IS_VALID(wSBflags
))
1190 EngSetLastError(ERROR_INVALID_PARAMETER
);
1191 ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags
);
1198 InfoV
= IntGetScrollbarInfoFromWindow(Window
, SB_VERT
);
1201 InfoH
= IntGetScrollbarInfoFromWindow(Window
, SB_HORZ
);
1204 InfoV
= IntGetScrollbarInfoFromWindow(Window
, SB_VERT
);
1211 Chg
= IntEnableScrollBar(FALSE
, InfoV
, wArrows
);
1214 Chg
= (IntEnableScrollBar(TRUE
, InfoH
, wArrows
) || Chg
);
1216 ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags
, wArrows
, Chg
);
1218 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1221 if (OrigArrows
== wArrows
) RETURN( FALSE
);
1226 UserDerefObjectCo(Window
);
1228 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_
);
1235 NtUserSetScrollInfo(
1243 SCROLLINFO ScrollInfo
;
1244 DECLARE_RETURN(DWORD
);
1245 USER_REFERENCE_ENTRY Ref
;
1247 TRACE("Enter NtUserSetScrollInfo\n");
1248 UserEnterExclusive();
1250 if(!(Window
= UserGetWindowObject(hWnd
)) || // FIXME:
1251 Window
== UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
1252 Window
== UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
1256 UserRefObjectCo(Window
, &Ref
);
1258 Status
= MmCopyFromCaller(&ScrollInfo
, lpsi
, sizeof(SCROLLINFO
) - sizeof(ScrollInfo
.nTrackPos
));
1259 if(!NT_SUCCESS(Status
))
1261 SetLastNtError(Status
);
1265 RETURN(co_IntSetScrollInfo(Window
, fnBar
, &ScrollInfo
, bRedraw
));
1269 UserDerefObjectCo(Window
);
1271 TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_
);
1278 NtUserShowScrollBar(HWND hWnd
, int nBar
, DWORD bShow
)
1281 DECLARE_RETURN(DWORD
);
1283 USER_REFERENCE_ENTRY Ref
;
1285 TRACE("Enter NtUserShowScrollBar\n");
1286 UserEnterExclusive();
1288 if (!(Window
= UserGetWindowObject(hWnd
)))
1293 UserRefObjectCo(Window
, &Ref
);
1294 ret
= co_UserShowScrollBar(Window
, nBar
, (nBar
== SB_VERT
) ? 0 : bShow
,
1295 (nBar
== SB_HORZ
) ? 0 : bShow
);
1296 UserDerefObjectCo(Window
);
1301 TRACE("Leave NtUserShowScrollBar, ret%lu\n", _ret_
);
1308 //// Ugly NtUser API ////
1312 NtUserSetScrollBarInfo(
1315 SETSCROLLBARINFO
*info
)
1318 SETSCROLLBARINFO Safeinfo
;
1323 DECLARE_RETURN(BOOL
);
1324 USER_REFERENCE_ENTRY Ref
;
1326 TRACE("Enter NtUserSetScrollBarInfo\n");
1327 UserEnterExclusive();
1329 if(!(Window
= UserGetWindowObject(hWnd
)))
1333 UserRefObjectCo(Window
, &Ref
);
1335 Obj
= SBOBJ_TO_SBID(idObject
);
1336 if(!SBID_IS_VALID(Obj
))
1338 EngSetLastError(ERROR_INVALID_PARAMETER
);
1339 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj
);
1343 if(!co_IntCreateScrollBars(Window
))
1348 Status
= MmCopyFromCaller(&Safeinfo
, info
, sizeof(SETSCROLLBARINFO
));
1349 if(!NT_SUCCESS(Status
))
1351 SetLastNtError(Status
);
1355 sbi
= IntGetScrollbarInfoFromWindow(Window
, Obj
);
1356 psi
= IntGetScrollInfoFromWindow(Window
, Obj
);
1358 psi
->nTrackPos
= Safeinfo
.nTrackPos
;
1359 sbi
->reserved
= Safeinfo
.reserved
;
1360 RtlCopyMemory(&sbi
->rgstate
, &Safeinfo
.rgstate
, sizeof(Safeinfo
.rgstate
));
1366 UserDerefObjectCo(Window
);
1368 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_
);