2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
5 * FILE: win32ss/user/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 *****************************************************************/
62 IntEnableScrollBar(BOOL Horz
, PSCROLLBARINFO Info
, UINT wArrows
);
65 IntRefeshScrollInterior(PWND pWnd
, INT nBar
, PSCROLLBARINFO psbi
);
68 /* Ported from WINE20020904 */
69 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
70 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
71 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
72 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
74 static inline void mirror_rect( const RECT
*window_rect
, RECT
*rect
)
76 int width
= window_rect
->right
- window_rect
->left
;
78 rect
->left
= width
- rect
->right
;
79 rect
->right
= width
- tmp
;
83 IntGetSBData(PWND pwnd
, INT Bar
)
88 pSBInfo
= pwnd
->pSBInfo
;
92 return &pSBInfo
->Horz
;
94 return &pSBInfo
->Vert
;
96 if ( pwnd
->cbwndExtra
< (sizeof(SBWND
)-sizeof(WND
)) )
98 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
101 pSBWnd
= (PSBWND
)pwnd
;
102 return (PSBDATA
)&pSBWnd
->SBCalc
;
104 ERR("IntGetSBData Bad Bar!\n");
110 IntGetScrollBarRect (PWND Wnd
, INT nBar
, RECTL
*lprect
)
113 *lprect
= Wnd
->rcClient
;
115 RECTL_vOffsetRect( lprect
, -Wnd
->rcWindow
.left
, -Wnd
->rcWindow
.top
);
116 if (Wnd
->ExStyle
& WS_EX_LAYOUTRTL
)
117 mirror_rect( &Wnd
->rcWindow
, lprect
);
122 lprect
->top
= lprect
->bottom
;
123 lprect
->bottom
+= UserGetSystemMetrics (SM_CYHSCROLL
);
124 if (Wnd
->style
& WS_BORDER
)
129 else if (Wnd
->style
& WS_VSCROLL
)
137 if(Wnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
)
139 lprect
->right
= lprect
->left
;
140 lprect
->left
-= UserGetSystemMetrics(SM_CXVSCROLL
);
144 lprect
->left
= lprect
->right
;
145 lprect
->right
+= UserGetSystemMetrics(SM_CXVSCROLL
);
147 if (Wnd
->style
& WS_BORDER
)
152 else if (Wnd
->style
& WS_HSCROLL
)
160 IntGetClientRect (Wnd
, lprect
);
161 vertical
= !!(Wnd
->style
& SBS_VERT
);
172 IntCalculateThumb(PWND Wnd
, LONG idObject
, PSCROLLBARINFO psbi
, PSBDATA pSBData
)
174 INT Thumb
, ThumbBox
, ThumbPos
, cxy
, mx
;
180 Thumb
= UserGetSystemMetrics(SM_CXHSCROLL
);
181 cxy
= psbi
->rcScrollBar
.right
- psbi
->rcScrollBar
.left
;
184 Thumb
= UserGetSystemMetrics(SM_CYVSCROLL
);
185 cxy
= psbi
->rcScrollBar
.bottom
- psbi
->rcScrollBar
.top
;
188 IntGetClientRect(Wnd
, &ClientRect
);
189 if(Wnd
->style
& SBS_VERT
)
191 Thumb
= UserGetSystemMetrics(SM_CYVSCROLL
);
192 cxy
= ClientRect
.bottom
- ClientRect
.top
;
196 Thumb
= UserGetSystemMetrics(SM_CXHSCROLL
);
197 cxy
= ClientRect
.right
- ClientRect
.left
;
205 /* Calculate Thumb */
206 if(cxy
<= (2 * Thumb
))
209 psbi
->xyThumbTop
= 0;
210 psbi
->xyThumbBottom
= 0;
213 else if (psbi
->rgstate
[SBRG_TOPRIGHTBTN
] == STATE_SYSTEM_UNAVAILABLE
&&
214 psbi
->rgstate
[SBRG_BOTTOMLEFTBTN
] == STATE_SYSTEM_UNAVAILABLE
&&
215 pSBData
->posMin
>= (int)(pSBData
->posMax
- max(pSBData
->page
- 1, 0)))
217 /* Nothing to scroll */
218 psbi
->xyThumbTop
= 0;
219 psbi
->xyThumbBottom
= 0;
223 ThumbBox
= pSBData
->page
? MINTRACKTHUMB
: UserGetSystemMetrics(SM_CXHTHUMB
);
229 ThumbBox
= max(EngMulDiv(cxy
, pSBData
->page
, pSBData
->posMax
- pSBData
->posMin
+ 1), ThumbBox
);
234 mx
= pSBData
->posMax
- max(pSBData
->page
- 1, 0);
235 if(pSBData
->posMin
< mx
)
236 ThumbPos
= Thumb
+ EngMulDiv(cxy
- ThumbBox
, pSBData
->pos
- pSBData
->posMin
, mx
- pSBData
->posMin
);
238 ThumbPos
= Thumb
+ ThumbBox
;
241 psbi
->xyThumbTop
= ThumbPos
;
242 psbi
->xyThumbBottom
= ThumbPos
+ ThumbBox
;
246 psbi
->xyThumbTop
= 0;
247 psbi
->xyThumbBottom
= 0;
250 psbi
->dxyLineButton
= Thumb
;
256 IntUpdateSBInfo(PWND Window, int wBar)
262 ASSERT(Window->pSBInfo);
263 ASSERT(Window->pSBInfoex);
265 sbi = IntGetScrollbarInfoFromWindow(Window, wBar);
266 pSBData = IntGetSBData(Window, wBar);
267 IntGetScrollBarRect(Window, wBar, &(sbi->rcScrollBar));
268 IntCalculateThumb(Window, wBar, sbi, pSBData);
272 co_IntGetScrollInfo(PWND Window
, INT nBar
, PSBDATA pSBData
, LPSCROLLINFO lpsi
)
277 ASSERT_REFS_CO(Window
);
279 if(!SBID_IS_VALID(nBar
))
281 EngSetLastError(ERROR_INVALID_PARAMETER
);
282 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar
);
286 if (!Window
->pSBInfo
)
288 ERR("IntGetScrollInfo No window scrollbar info!\n");
292 psi
= IntGetScrollInfoFromWindow(Window
, nBar
);
294 if (lpsi
->fMask
== SIF_ALL
)
296 Mask
= SIF_PAGE
| SIF_POS
| SIF_RANGE
| SIF_TRACKPOS
;
303 if (0 != (Mask
& SIF_PAGE
))
305 lpsi
->nPage
= psi
->nPage
;
308 if (0 != (Mask
& SIF_POS
))
310 lpsi
->nPos
= psi
->nPos
;
313 if (0 != (Mask
& SIF_RANGE
))
315 lpsi
->nMin
= psi
->nMin
;
316 lpsi
->nMax
= psi
->nMax
;
319 if (0 != (Mask
& SIF_TRACKPOS
))
321 lpsi
->nTrackPos
= psi
->nTrackPos
;
328 NEWco_IntGetScrollInfo(
335 PSBTRACK pSBTrack
= pWnd
->head
.pti
->pSBTrack
;
337 if (!SBID_IS_VALID(nBar
))
339 EngSetLastError(ERROR_INVALID_PARAMETER
);
340 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", nBar
);
344 if (!pWnd
->pSBInfo
|| !pSBTrack
) return FALSE
;
348 if (0 != (Mask
& SIF_PAGE
))
350 lpsi
->nPage
= pSBData
->page
;
353 if (0 != (Mask
& SIF_POS
))
355 lpsi
->nPos
= pSBData
->pos
;
358 if (0 != (Mask
& SIF_RANGE
))
360 lpsi
->nMin
= pSBData
->posMin
;
361 lpsi
->nMax
= pSBData
->posMax
;
364 if (0 != (Mask
& SIF_TRACKPOS
))
367 pSBTrack
->nBar
== nBar
&&
368 pSBTrack
->spwndTrack
== pWnd
)
369 lpsi
->nTrackPos
= pSBTrack
->posNew
;
371 lpsi
->nTrackPos
= pSBData
->pos
;
373 return (Mask
& SIF_ALL
) !=0;
376 /*************************************************************************
377 * SCROLL_GetScrollBarInfo
379 * Internal helper for the API function
382 * hwnd [I] Handle of window with scrollbar(s)
383 * idObject [I] One of OBJID_CLIENT, OBJID_HSCROLL, or OBJID_VSCROLL
384 * info [IO] cbSize specifies the size of the structure
390 static BOOL
SCROLL_GetScrollBarInfo(HWND hwnd
, LONG idObject
, LPSCROLLBARINFO info
)
392 LPSCROLLBAR_INFO infoPtr
;
395 DWORD style
= GetWindowLongW(hwnd
, GWL_STYLE
);
401 case OBJID_CLIENT
: nBar
= SB_CTL
; break;
402 case OBJID_HSCROLL
: nBar
= SB_HORZ
; break;
403 case OBJID_VSCROLL
: nBar
= SB_VERT
; break;
404 default: return FALSE
;
407 /* handle invalid data structure */
408 if (info
->cbSize
!= sizeof(*info
))
411 SCROLL_GetScrollBarRect(hwnd
, nBar
, &info
->rcScrollBar
, &nDummy
,
412 &info
->dxyLineButton
, &info
->xyThumbTop
);
413 /* rcScrollBar needs to be in screen coordinates */
414 GetWindowRect(hwnd
, &rect
);
415 OffsetRect(&info
->rcScrollBar
, rect
.left
, rect
.top
);
417 info
->xyThumbBottom
= info
->xyThumbTop
+ info
->dxyLineButton
;
419 infoPtr
= SCROLL_GetInternalInfo(hwnd
, nBar
, TRUE
);
423 /* Scroll bar state */
424 info
->rgstate
[0] = 0;
425 if ((nBar
== SB_HORZ
&& !(style
& WS_HSCROLL
))
426 || (nBar
== SB_VERT
&& !(style
& WS_VSCROLL
)))
427 info
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
428 if (infoPtr
->minVal
>= infoPtr
->maxVal
- max(infoPtr
->page
- 1, 0))
430 if (!(info
->rgstate
[0] & STATE_SYSTEM_INVISIBLE
))
431 info
->rgstate
[0] |= STATE_SYSTEM_UNAVAILABLE
;
433 info
->rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
435 if (nBar
== SB_CTL
&& !IsWindowEnabled(hwnd
))
436 info
->rgstate
[0] |= STATE_SYSTEM_UNAVAILABLE
;
438 pressed
= ((nBar
== SB_VERT
) == SCROLL_trackVertical
&& GetCapture() == hwnd
);
440 /* Top/left arrow button state. MSDN says top/right, but I don't believe it */
441 info
->rgstate
[1] = 0;
442 if (pressed
&& SCROLL_trackHitTest
== SCROLL_TOP_ARROW
)
443 info
->rgstate
[1] |= STATE_SYSTEM_PRESSED
;
444 if (infoPtr
->flags
& ESB_DISABLE_LTUP
)
445 info
->rgstate
[1] |= STATE_SYSTEM_UNAVAILABLE
;
447 /* Page up/left region state. MSDN says up/right, but I don't believe it */
448 info
->rgstate
[2] = 0;
449 if (infoPtr
->curVal
== infoPtr
->minVal
)
450 info
->rgstate
[2] |= STATE_SYSTEM_INVISIBLE
;
451 if (pressed
&& SCROLL_trackHitTest
== SCROLL_TOP_RECT
)
452 info
->rgstate
[2] |= STATE_SYSTEM_PRESSED
;
455 info
->rgstate
[3] = 0;
456 if (pressed
&& SCROLL_trackHitTest
== SCROLL_THUMB
)
457 info
->rgstate
[3] |= STATE_SYSTEM_PRESSED
;
459 /* Page down/right region state. MSDN says down/left, but I don't believe it */
460 info
->rgstate
[4] = 0;
461 if (infoPtr
->curVal
>= infoPtr
->maxVal
- 1)
462 info
->rgstate
[4] |= STATE_SYSTEM_INVISIBLE
;
463 if (pressed
&& SCROLL_trackHitTest
== SCROLL_BOTTOM_RECT
)
464 info
->rgstate
[4] |= STATE_SYSTEM_PRESSED
;
466 /* Bottom/right arrow button state. MSDN says bottom/left, but I don't believe it */
467 info
->rgstate
[5] = 0;
468 if (pressed
&& SCROLL_trackHitTest
== SCROLL_BOTTOM_ARROW
)
469 info
->rgstate
[5] |= STATE_SYSTEM_PRESSED
;
470 if (infoPtr
->flags
& ESB_DISABLE_RTDN
)
471 info
->rgstate
[5] |= STATE_SYSTEM_UNAVAILABLE
;
476 static DWORD FASTCALL
477 co_IntSetScrollInfo(PWND Window
, INT nBar
, LPCSCROLLINFO lpsi
, BOOL bRedraw
)
480 * Update the scrollbar state and set action flags according to
481 * what has to be done graphics wise.
490 BOOL bChangeParams
= FALSE
; /* Don't show/hide scrollbar if params don't change */
494 ASSERT_REFS_CO(Window
);
496 if(!SBID_IS_VALID(nBar
))
498 EngSetLastError(ERROR_INVALID_PARAMETER
);
499 ERR("Trying to set scrollinfo for unknown scrollbar type %d", nBar
);
503 if(!co_IntCreateScrollBars(Window
))
508 if (lpsi
->cbSize
!= sizeof(SCROLLINFO
) &&
509 lpsi
->cbSize
!= (sizeof(SCROLLINFO
) - sizeof(lpsi
->nTrackPos
)))
511 EngSetLastError(ERROR_INVALID_PARAMETER
);
514 if (lpsi
->fMask
& ~(SIF_ALL
| SIF_DISABLENOSCROLL
| SIF_PREVIOUSPOS
))
516 EngSetLastError(ERROR_INVALID_PARAMETER
);
520 psbi
= IntGetScrollbarInfoFromWindow(Window
, nBar
);
521 Info
= IntGetScrollInfoFromWindow(Window
, nBar
);
522 pSBData
= IntGetSBData(Window
, nBar
);
524 /* Set the page size */
525 if (lpsi
->fMask
& SIF_PAGE
)
527 if (Info
->nPage
!= lpsi
->nPage
)
529 Info
->nPage
= lpsi
->nPage
;
530 pSBData
->page
= lpsi
->nPage
;
531 bChangeParams
= TRUE
;
535 /* Set the scroll pos */
536 if (lpsi
->fMask
& SIF_POS
)
538 if (Info
->nPos
!= lpsi
->nPos
)
541 Info
->nPos
= lpsi
->nPos
;
542 pSBData
->pos
= lpsi
->nPos
;
546 /* Set the scroll range */
547 if (lpsi
->fMask
& SIF_RANGE
)
549 if (lpsi
->nMin
> lpsi
->nMax
)
551 Info
->nMin
= lpsi
->nMin
;
552 Info
->nMax
= lpsi
->nMin
;
553 pSBData
->posMin
= lpsi
->nMin
;
554 pSBData
->posMax
= lpsi
->nMin
;
555 bChangeParams
= TRUE
;
557 else if (Info
->nMin
!= lpsi
->nMin
|| Info
->nMax
!= lpsi
->nMax
)
559 Info
->nMin
= lpsi
->nMin
;
560 Info
->nMax
= lpsi
->nMax
;
561 pSBData
->posMin
= lpsi
->nMin
;
562 pSBData
->posMax
= lpsi
->nMax
;
563 bChangeParams
= TRUE
;
567 /* Make sure the page size is valid */
568 MaxPage
= abs(Info
->nMax
- Info
->nMin
) + 1;
569 if (Info
->nPage
> MaxPage
)
571 pSBData
->page
= Info
->nPage
= MaxPage
;
574 /* Make sure the pos is inside the range */
575 MaxPos
= Info
->nMax
+ 1 - (int)max(Info
->nPage
, 1);
576 ASSERT(MaxPos
>= Info
->nMin
);
577 if (Info
->nPos
< Info
->nMin
)
579 pSBData
->pos
= Info
->nPos
= Info
->nMin
;
581 else if (Info
->nPos
> MaxPos
)
583 pSBData
->pos
= Info
->nPos
= MaxPos
;
587 * Don't change the scrollbar state if SetScrollInfo is just called
588 * with SIF_DISABLENOSCROLL
590 if (!(lpsi
->fMask
& SIF_ALL
))
593 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
;
596 /* Check if the scrollbar should be hidden or disabled */
597 if (lpsi
->fMask
& (SIF_RANGE
| SIF_PAGE
| SIF_DISABLENOSCROLL
))
599 new_flags
= Window
->pSBInfo
->WSBflags
;
600 if (Info
->nMin
>= (int)(Info
->nMax
- max(Info
->nPage
- 1, 0)))
602 /* Hide or disable scroll-bar */
603 if (lpsi
->fMask
& SIF_DISABLENOSCROLL
)
605 new_flags
= ESB_DISABLE_BOTH
;
606 bChangeParams
= TRUE
;
608 else if ((nBar
!= SB_CTL
) && bChangeParams
)
610 action
= SA_SSI_HIDE
;
613 else /* Show and enable scroll-bar only if no page only changed. */
614 if (lpsi
->fMask
!= SIF_PAGE
)
616 if ((nBar
!= SB_CTL
) && bChangeParams
)
618 new_flags
= ESB_ENABLE_BOTH
;
619 action
|= SA_SSI_SHOW
;
621 else if (nBar
== SB_CTL
)
623 new_flags
= ESB_ENABLE_BOTH
;
627 if (Window
->pSBInfo
->WSBflags
!= new_flags
) /* Check arrow flags */
629 Window
->pSBInfo
->WSBflags
= new_flags
;
630 action
|= SA_SSI_REPAINT_ARROWS
;
635 if ( action
& SA_SSI_HIDE
)
637 co_UserShowScrollBar(Window
, nBar
, FALSE
, FALSE
);
641 if ( action
& SA_SSI_SHOW
)
642 if ( co_UserShowScrollBar(Window
, nBar
, TRUE
, TRUE
) )
643 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
; /* SetWindowPos() already did the painting */
646 if (action
& SA_SSI_REPAINT_ARROWS
)
647 { // Redraw the entire bar.
648 RECTL UpdateRect
= psbi
->rcScrollBar
;
649 UpdateRect
.left
-= Window
->rcClient
.left
- Window
->rcWindow
.left
;
650 UpdateRect
.right
-= Window
->rcClient
.left
- Window
->rcWindow
.left
;
651 UpdateRect
.top
-= Window
->rcClient
.top
- Window
->rcWindow
.top
;
652 UpdateRect
.bottom
-= Window
->rcClient
.top
- Window
->rcWindow
.top
;
653 co_UserRedrawWindow(Window
, &UpdateRect
, 0, RDW_INVALIDATE
| RDW_FRAME
);
657 // Redraw only the interior part of the bar.
658 IntRefeshScrollInterior(Window
, nBar
, psbi
);
661 /* else if( action & SA_SSI_REPAINT_ARROWS )
663 RECTL UpdateRect = psbi->rcScrollBar;
664 UpdateRect.left -= Window->rcClient.left - Window->rcWindow.left;
665 UpdateRect.right -= Window->rcClient.left - Window->rcWindow.left;
666 UpdateRect.top -= Window->rcClient.top - Window->rcWindow.top;
667 UpdateRect.bottom -= Window->rcClient.top - Window->rcWindow.top;
668 co_UserRedrawWindow(Window, &UpdateRect, 0, RDW_INVALIDATE | RDW_FRAME);
672 if (bChangeParams
&& (nBar
== SB_HORZ
|| nBar
== SB_VERT
) && (lpsi
->fMask
& SIF_DISABLENOSCROLL
))
674 IntEnableScrollBar(nBar
== SB_HORZ
, psbi
, Window
->pSBInfo
->WSBflags
);
677 /* Return current position */
678 return lpsi
->fMask
& SIF_PREVIOUSPOS
? OldPos
: pSBData
->pos
;
682 co_IntGetScrollBarInfo(PWND Window
, LONG idObject
, PSCROLLBARINFO psbi
)
687 ASSERT_REFS_CO(Window
);
689 Bar
= SBOBJ_TO_SBID(idObject
);
691 if(!SBID_IS_VALID(Bar
))
693 EngSetLastError(ERROR_INVALID_PARAMETER
);
694 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar
);
698 if(!co_IntCreateScrollBars(Window
))
700 ERR("Failed to create scrollbars for window.\n");
704 sbi
= IntGetScrollbarInfoFromWindow(Window
, Bar
);
705 pSBData
= IntGetSBData(Window
, Bar
);
707 IntGetScrollBarRect(Window
, Bar
, &(sbi
->rcScrollBar
));
708 IntCalculateThumb(Window
, Bar
, sbi
, pSBData
);
710 /* Scroll bar state */
711 psbi
->rgstate
[0] = 0;
712 if ((Bar
== SB_HORZ
&& !(Window
->style
& WS_HSCROLL
))
713 || (Bar
== SB_VERT
&& !(Window
->style
& WS_VSCROLL
)))
714 psbi
->rgstate
[0] |= STATE_SYSTEM_INVISIBLE
;
715 if (pSBData
->posMin
>= pSBData
->posMax
- max(pSBData
->page
- 1, 0))
717 if (!(psbi
->rgstate
[0] & STATE_SYSTEM_INVISIBLE
))
718 psbi
->rgstate
[0] |= STATE_SYSTEM_UNAVAILABLE
;
720 psbi
->rgstate
[0] |= STATE_SYSTEM_OFFSCREEN
;
722 if (Bar
== SB_CTL
&& !(Window
->style
& WS_DISABLED
))
723 psbi
->rgstate
[0] |= STATE_SYSTEM_UNAVAILABLE
;
725 RtlCopyMemory(psbi
, sbi
, sizeof(SCROLLBARINFO
));
731 co_IntSetScrollBarInfo(PWND Window
, LONG idObject
, PSETSCROLLBARINFO psbi
)
736 ASSERT_REFS_CO(Window
);
738 Bar
= SBOBJ_TO_SBID(idObject
);
740 if(!SBID_IS_VALID(Bar
))
742 EngSetLastError(ERROR_INVALID_PARAMETER
);
743 ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar
);
747 if(!co_IntCreateScrollBars(Window
))
749 ERR("Failed to create scrollbars for window.\n");
753 sbi
= IntGetScrollbarInfoFromWindow(Window
, Bar
);
754 psi
= IntGetScrollInfoFromWindow(Window
, Bar
);
756 psi
->nTrackPos
= psbi
->nTrackPos
;
757 sbi
->reserved
= psbi
->reserved
;
758 RtlCopyMemory(&sbi
->rgstate
, &psbi
->rgstate
, sizeof(psbi
->rgstate
));
764 co_IntCreateScrollBars(PWND Window
)
771 ASSERT_REFS_CO(Window
);
773 if (Window
->pSBInfo
&& Window
->pSBInfoex
)
775 /* No need to create it anymore */
779 /* Allocate memory for all scrollbars (HORZ, VERT, CONTROL) */
780 Size
= 3 * (sizeof(SBINFOEX
));
781 if(!(Window
->pSBInfoex
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_SBARINFO
)))
783 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window
->head
.h
);
787 RtlZeroMemory(Window
->pSBInfoex
, Size
);
789 if(!(Window
->pSBInfo
= DesktopHeapAlloc( Window
->head
.rpdesk
, sizeof(SBINFO
))))
791 ERR("Unable to allocate memory for scrollbar information for window %p\n", Window
->head
.h
);
795 RtlZeroMemory(Window
->pSBInfo
, sizeof(SBINFO
));
796 Window
->pSBInfo
->Vert
.posMax
= 100;
797 Window
->pSBInfo
->Horz
.posMax
= 100;
799 co_WinPosGetNonClientSize(Window
,
803 for(s
= SB_HORZ
; s
<= SB_VERT
; s
++)
805 psbi
= IntGetScrollbarInfoFromWindow(Window
, s
);
806 psbi
->cbSize
= sizeof(SCROLLBARINFO
);
807 for (i
= 0; i
< CCHILDREN_SCROLLBAR
+ 1; i
++)
808 psbi
->rgstate
[i
] = 0;
810 pSBData
= IntGetSBData(Window
, s
);
812 IntGetScrollBarRect(Window
, s
, &(psbi
->rcScrollBar
));
813 IntCalculateThumb(Window
, s
, psbi
, pSBData
);
820 IntDestroyScrollBars(PWND Window
)
822 if (Window
->pSBInfo
&& Window
->pSBInfoex
)
824 DesktopHeapFree(Window
->head
.rpdesk
, Window
->pSBInfo
);
825 Window
->pSBInfo
= NULL
;
826 ExFreePoolWithTag(Window
->pSBInfoex
, TAG_SBARINFO
);
827 Window
->pSBInfoex
= NULL
;
834 IntEnableScrollBar(BOOL Horz
, PSCROLLBARINFO Info
, UINT wArrows
)
839 case ESB_DISABLE_BOTH
:
840 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
841 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
843 case ESB_DISABLE_RTDN
:
846 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
850 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
853 case ESB_DISABLE_LTUP
:
856 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, STATE_SYSTEM_UNAVAILABLE
);
860 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, STATE_SYSTEM_UNAVAILABLE
);
863 case ESB_ENABLE_BOTH
:
864 CHANGERGSTATE(SBRG_TOPRIGHTBTN
, 0);
865 CHANGERGSTATE(SBRG_BOTTOMLEFTBTN
, 0);
871 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
873 co_UserShowScrollBar(PWND Wnd
, int nBar
, BOOL fShowH
, BOOL fShowV
)
875 ULONG old_style
, set_bits
= 0, clear_bits
= 0;
883 //IntUpdateSBInfo(Wnd, SB_CTL); // Is this needed? Was tested w/o!
885 co_WinPosShowWindow(Wnd
, fShowH
? SW_SHOW
: SW_HIDE
);
890 if (fShowH
) set_bits
|= WS_HSCROLL
;
891 else clear_bits
|= WS_HSCROLL
;
892 if( nBar
== SB_HORZ
) break;
895 if (fShowV
) set_bits
|= WS_VSCROLL
;
896 else clear_bits
|= WS_VSCROLL
;
899 EngSetLastError(ERROR_INVALID_PARAMETER
);
900 return FALSE
; /* Nothing to do! */
903 old_style
= IntSetStyle( Wnd
, set_bits
, clear_bits
);
904 if ((old_style
& clear_bits
) != 0 || (old_style
& set_bits
) != set_bits
)
906 ///// Is this needed? Was tested w/o!
907 //if (Wnd->style & WS_HSCROLL) IntUpdateSBInfo(Wnd, SB_HORZ);
908 //if (Wnd->style & WS_VSCROLL) IntUpdateSBInfo(Wnd, SB_VERT);
910 /* Frame has been changed, let the window redraw itself */
911 co_WinPosSetWindowPos( Wnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
912 | SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_FRAMECHANGED
);
915 return FALSE
; /* no frame changes */
919 IntDrawScrollInterior(PWND pWnd
, HDC hDC
, INT nBar
, BOOL Vertical
, PSCROLLBARINFO ScrollBarInfo
)
921 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
922 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
924 HBRUSH hSaveBrush
, hBrush
;
925 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
927 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
929 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
930 BottomSelected
= TRUE
;
933 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
934 * The window-owned scrollbars need to call DefWndControlColor
935 * to correctly setup default scrollbar colors
939 hBrush
= GetControlBrush( pWnd
, hDC
, WM_CTLCOLORSCROLLBAR
);
941 hBrush
= IntGetSysColorBrush(COLOR_SCROLLBAR
);
945 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
948 hSaveBrush
= NtGdiSelectBrush(hDC
, hBrush
);
950 /* Calculate the scroll rectangle */
953 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
954 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
955 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
956 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
960 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
961 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
962 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
963 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
966 /* Draw the scroll rectangles and thumb */
967 if (!ScrollBarInfo
->xyThumbBottom
)
969 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
970 Rect
.bottom
- Rect
.top
, PATCOPY
);
972 /* Cleanup and return */
973 NtGdiSelectBrush(hDC
, hSaveBrush
);
977 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
979 if (ScrollBarInfo
->dxyLineButton
)
985 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
986 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
987 Rect
.top
+= ThumbTop
;
988 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
989 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
990 Rect
.bottom
= Rect
.top
+ ThumbSize
;
996 NtGdiPatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
997 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
1005 NtGdiPatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
1006 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
1007 Rect
.left
+= ThumbTop
;
1008 NtGdiPatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
1009 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
1010 BottomSelected
? BLACKNESS
: PATCOPY
);
1011 Rect
.right
= Rect
.left
+ ThumbSize
;
1017 NtGdiPatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
1018 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
1024 /* Draw the thumb */
1026 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
1029 NtGdiSelectBrush(hDC
, hSaveBrush
);
1033 static VOID FASTCALL
1034 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
1036 RECT RectLT
, RectRB
;
1037 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
1039 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
1042 ScrollDirFlagLT
= DFCS_SCROLLUP
;
1043 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
1044 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
1045 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
1049 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
1050 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
1051 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
1052 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
1055 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
1057 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
1059 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
1061 ScrollDirFlagLT
|= DFCS_INACTIVE
;
1063 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
1065 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
1067 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
1069 ScrollDirFlagRB
|= DFCS_INACTIVE
;
1072 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
1073 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
1076 static LONG FASTCALL
1077 IntScrollGetObjectId(INT SBType
)
1079 if (SBType
== SB_VERT
)
1080 return OBJID_VSCROLL
;
1081 if (SBType
== SB_HORZ
)
1082 return OBJID_HSCROLL
;
1083 return OBJID_CLIENT
;
1087 IntRefeshScrollInterior(PWND pWnd
, INT nBar
, PSCROLLBARINFO psbi
)
1090 BOOL Vertical
= ((nBar
== SB_CTL
) ? ((pWnd
->style
& SBS_VERT
) != 0) : (nBar
== SB_VERT
));
1092 hdc
= UserGetDCEx(pWnd
, NULL
, DCX_CACHE
| ((nBar
== SB_CTL
) ? 0 : DCX_WINDOW
));
1094 { /* Get updated info. */
1095 co_IntGetScrollBarInfo(pWnd
, IntScrollGetObjectId(nBar
), psbi
);
1096 IntDrawScrollInterior(pWnd
, hdc
, nBar
, Vertical
, psbi
);
1097 UserReleaseDC(pWnd
, hdc
, FALSE
);
1102 IntDrawScrollBar(PWND Wnd
, HDC DC
, INT Bar
)
1110 pti
= PsGetCurrentThreadWin32Thread();
1113 * Get scroll bar info.
1126 Vertical
= (Wnd
->style
& SBS_VERT
) != 0;
1133 if (!co_IntGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), &Info
))
1138 if (RECTL_bIsEmptyRect(&Info
.rcScrollBar
))
1143 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
1148 if (Info
.dxyLineButton
)
1150 IntDrawScrollArrows(DC
, &Info
, Vertical
);
1154 * Draw the interior.
1156 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
1159 * If scroll bar has focus, reposition the caret.
1161 if ( Wnd
== pti
->MessageQueue
->spwndFocus
&& Bar
== SB_CTL
)
1165 co_IntSetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
1169 co_IntSetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
1176 ScrollBarWndProc(HWND hWnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1178 LRESULT lResult
= 0;
1180 pWnd
= UserGetWindowObject(hWnd
);
1181 if (!pWnd
) return 0;
1189 pWnd
->pSBInfo
->WSBflags
= wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
;
1201 NtUserGetScrollBarInfo(HWND hWnd
, LONG idObject
, PSCROLLBARINFO psbi
)
1207 DECLARE_RETURN(BOOL
);
1208 USER_REFERENCE_ENTRY Ref
;
1210 TRACE("Enter NtUserGetScrollBarInfo\n");
1211 UserEnterExclusive();
1213 Status
= MmCopyFromCaller(&sbi
, psbi
, sizeof(SCROLLBARINFO
));
1214 if(!NT_SUCCESS(Status
) || (sbi
.cbSize
!= sizeof(SCROLLBARINFO
)))
1216 SetLastNtError(Status
);
1220 if(!(Window
= UserGetWindowObject(hWnd
)))
1225 UserRefObjectCo(Window
, &Ref
);
1226 Ret
= co_IntGetScrollBarInfo(Window
, idObject
, &sbi
);
1227 UserDerefObjectCo(Window
);
1229 Status
= MmCopyToCaller(psbi
, &sbi
, sizeof(SCROLLBARINFO
));
1230 if(!NT_SUCCESS(Status
))
1232 SetLastNtError(Status
);
1239 TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_
);
1257 DECLARE_RETURN(BOOL
);
1258 USER_REFERENCE_ENTRY Ref
;
1260 TRACE("Enter NtUserGetScrollInfo\n");
1265 RtlCopyMemory(&psi
, lpsi
, sizeof(SCROLLINFO
));
1268 RtlCopyMemory(&SBDataSafe
, pSBData
, sizeof(SBDATA
));
1271 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1273 ERR("NtUserGetScrollInfo Failed size.\n");
1274 SetLastNtError(_SEH2_GetExceptionCode());
1275 _SEH2_YIELD(RETURN(FALSE
));
1279 if(!(Window
= UserGetWindowObject(hWnd
)))
1281 ERR("NtUserGetScrollInfo Bad window.\n");
1285 UserRefObjectCo(Window
, &Ref
);
1286 Ret
= co_IntGetScrollInfo(Window
, fnBar
, &SBDataSafe
, &psi
);
1287 UserDerefObjectCo(Window
);
1291 RtlCopyMemory(lpsi
, &psi
, sizeof(SCROLLINFO
));
1293 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1295 ERR("NtUserGetScrollInfo Failed copy to user.\n");
1296 SetLastNtError(_SEH2_GetExceptionCode());
1297 _SEH2_YIELD(RETURN(FALSE
));
1304 TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_
);
1311 NtUserEnableScrollBar(
1318 PSCROLLBARINFO InfoV
= NULL
, InfoH
= NULL
;
1320 DECLARE_RETURN(BOOL
);
1321 USER_REFERENCE_ENTRY Ref
;
1323 TRACE("Enter NtUserEnableScrollBar\n");
1324 UserEnterExclusive();
1326 if (!(Window
= UserGetWindowObject(hWnd
)) ||
1327 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
1331 UserRefObjectCo(Window
, &Ref
);
1333 if (!co_IntCreateScrollBars(Window
))
1338 OrigArrows
= Window
->pSBInfo
->WSBflags
;
1339 Window
->pSBInfo
->WSBflags
= wArrows
;
1341 if (wSBflags
== SB_CTL
)
1343 if ((wArrows
== ESB_DISABLE_BOTH
|| wArrows
== ESB_ENABLE_BOTH
))
1344 IntEnableWindow(hWnd
, (wArrows
== ESB_ENABLE_BOTH
));
1349 if(wSBflags
!= SB_BOTH
&& !SBID_IS_VALID(wSBflags
))
1351 EngSetLastError(ERROR_INVALID_PARAMETER
);
1352 ERR("Trying to set scrollinfo for unknown scrollbar type %u", wSBflags
);
1359 InfoV
= IntGetScrollbarInfoFromWindow(Window
, SB_VERT
);
1362 InfoH
= IntGetScrollbarInfoFromWindow(Window
, SB_HORZ
);
1365 InfoV
= IntGetScrollbarInfoFromWindow(Window
, SB_VERT
);
1372 Chg
= IntEnableScrollBar(FALSE
, InfoV
, wArrows
);
1375 Chg
= (IntEnableScrollBar(TRUE
, InfoH
, wArrows
) || Chg
);
1377 ERR("FIXME: EnableScrollBar wSBflags %u wArrows %u Chg %d\n", wSBflags
, wArrows
, Chg
);
1379 // SCROLL_RefreshScrollBar( hwnd, nBar, TRUE, TRUE );
1382 if (OrigArrows
== wArrows
) RETURN( FALSE
);
1387 UserDerefObjectCo(Window
);
1389 TRACE("Leave NtUserEnableScrollBar, ret=%i\n",_ret_
);
1396 NtUserSetScrollInfo(
1404 SCROLLINFO ScrollInfo
;
1405 DECLARE_RETURN(DWORD
);
1406 USER_REFERENCE_ENTRY Ref
;
1408 TRACE("Enter NtUserSetScrollInfo\n");
1409 UserEnterExclusive();
1411 if(!(Window
= UserGetWindowObject(hWnd
)) ||
1412 UserIsDesktopWindow(Window
) || UserIsMessageWindow(Window
))
1416 UserRefObjectCo(Window
, &Ref
);
1418 Status
= MmCopyFromCaller(&ScrollInfo
, lpsi
, sizeof(SCROLLINFO
) - sizeof(ScrollInfo
.nTrackPos
));
1419 if(!NT_SUCCESS(Status
))
1421 SetLastNtError(Status
);
1425 RETURN(co_IntSetScrollInfo(Window
, fnBar
, &ScrollInfo
, bRedraw
));
1429 UserDerefObjectCo(Window
);
1431 TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_
);
1438 NtUserShowScrollBar(HWND hWnd
, int nBar
, DWORD bShow
)
1441 DECLARE_RETURN(DWORD
);
1443 USER_REFERENCE_ENTRY Ref
;
1445 TRACE("Enter NtUserShowScrollBar\n");
1446 UserEnterExclusive();
1448 if (!(Window
= UserGetWindowObject(hWnd
)))
1453 UserRefObjectCo(Window
, &Ref
);
1454 ret
= co_UserShowScrollBar(Window
, nBar
, (nBar
== SB_VERT
) ? 0 : bShow
,
1455 (nBar
== SB_HORZ
) ? 0 : bShow
);
1456 UserDerefObjectCo(Window
);
1461 TRACE("Leave NtUserShowScrollBar, ret%lu\n", _ret_
);
1468 //// Ugly NtUser API ////
1472 NtUserSetScrollBarInfo(
1475 SETSCROLLBARINFO
*info
)
1478 SETSCROLLBARINFO Safeinfo
;
1483 DECLARE_RETURN(BOOL
);
1484 USER_REFERENCE_ENTRY Ref
;
1486 TRACE("Enter NtUserSetScrollBarInfo\n");
1487 UserEnterExclusive();
1489 if(!(Window
= UserGetWindowObject(hWnd
)))
1493 UserRefObjectCo(Window
, &Ref
);
1495 Obj
= SBOBJ_TO_SBID(idObject
);
1496 if(!SBID_IS_VALID(Obj
))
1498 EngSetLastError(ERROR_INVALID_PARAMETER
);
1499 ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj
);
1503 if(!co_IntCreateScrollBars(Window
))
1508 Status
= MmCopyFromCaller(&Safeinfo
, info
, sizeof(SETSCROLLBARINFO
));
1509 if(!NT_SUCCESS(Status
))
1511 SetLastNtError(Status
);
1515 sbi
= IntGetScrollbarInfoFromWindow(Window
, Obj
);
1516 psi
= IntGetScrollInfoFromWindow(Window
, Obj
);
1518 psi
->nTrackPos
= Safeinfo
.nTrackPos
;
1519 sbi
->reserved
= Safeinfo
.reserved
;
1520 RtlCopyMemory(&sbi
->rgstate
, &Safeinfo
.rgstate
, sizeof(Safeinfo
.rgstate
));
1526 UserDerefObjectCo(Window
);
1528 TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_
);