3 * ReactOS User32 Library
6 * Copyright 2001 Casper S. Hornstrup
7 * Copyright 2003 Thomas Weidenmueller
8 * Copyright 2003 Filip Navara
12 * Copyright 1993 Martin Ayotte
13 * Copyright 1994, 1996 Alexandre Julliard
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30 /* INCLUDES *******************************************************************/
34 #include <wine/debug.h>
35 WINE_DEFAULT_DEBUG_CHANNEL(scrollbar
);
37 /* GLOBAL VARIABLES ***********************************************************/
39 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
40 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
41 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
42 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
43 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
44 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
45 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
47 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
48 holding the button down */
49 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
51 #define SCROLL_TIMER 0 /* Scroll timer id */
53 /* Minimum size of the rectangle between the arrows */
54 #define SCROLL_MIN_RECT 4
56 /* Minimum size of the thumb in pixels */
57 #define SCROLL_MIN_THUMB 6
59 /* Thumb-tracking info */
60 static HWND ScrollTrackingWin
= 0;
61 static INT ScrollTrackingBar
= 0;
62 static INT ScrollTrackingPos
= 0;
63 static INT ScrollTrackingVal
= 0;
64 static BOOL ScrollMovingThumb
= FALSE
;
66 static DWORD ScrollTrackHitTest
= SCROLL_NOWHERE
;
67 static BOOL ScrollTrackVertical
;
69 HBRUSH
DefWndControlColor(HDC hDC
, UINT ctlType
);
71 //static LRESULT WINAPI ScrollBarWndProcW( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
72 //static LRESULT WINAPI ScrollBarWndProcA( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
74 UINT WINAPI
SetSystemTimer(HWND
,UINT_PTR
,UINT
,TIMERPROC
);
75 BOOL WINAPI
KillSystemTimer(HWND
,UINT_PTR
);
77 /*********************************************************************
78 * scrollbar class descriptor
80 const struct builtin_class_descr SCROLL_builtin_class
=
82 L
"ScrollBar", /* name */
83 CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
| CS_PARENTDC
, /* style */
84 ScrollBarWndProcA
, /* procA */
85 ScrollBarWndProcW
, /* procW */
87 IDC_ARROW
, /* cursor */
91 /* PRIVATE FUNCTIONS **********************************************************/
95 IntDrawScrollInterior(HWND hWnd
, HDC hDC
, INT nBar
, BOOL Vertical
,
96 PSCROLLBARINFO ScrollBarInfo
)
98 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
99 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
101 HBRUSH hSaveBrush
, hBrush
;
102 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
104 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
106 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
107 BottomSelected
= TRUE
;
110 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
111 * The window-owned scrollbars need to call DefWndControlColor
112 * to correctly setup default scrollbar colors
116 hBrush
= (HBRUSH
)SendMessageW(GetParent(hWnd
), WM_CTLCOLORSCROLLBAR
, (WPARAM
)hDC
, (LPARAM
)hWnd
);
118 hBrush
= GetSysColorBrush(COLOR_SCROLLBAR
);
122 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
125 hSaveBrush
= SelectObject(hDC
, hBrush
);
127 /* Calculate the scroll rectangle */
130 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
131 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
132 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
133 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
137 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
138 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
139 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
140 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
143 /* Draw the scroll rectangles and thumb */
144 if (!ScrollBarInfo
->xyThumbBottom
)
146 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
147 Rect
.bottom
- Rect
.top
, PATCOPY
);
149 /* Cleanup and return */
150 SelectObject(hDC
, hSaveBrush
);
154 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
156 if (ScrollBarInfo
->dxyLineButton
)
162 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
163 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
164 Rect
.top
+= ThumbTop
;
165 PatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
166 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
167 Rect
.bottom
= Rect
.top
+ ThumbSize
;
173 PatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
174 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
182 PatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
183 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
184 Rect
.left
+= ThumbTop
;
185 PatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
186 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
187 BottomSelected
? BLACKNESS
: PATCOPY
);
188 Rect
.right
= Rect
.left
+ ThumbSize
;
194 PatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
195 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
203 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
206 SelectObject(hDC
, hSaveBrush
);
210 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
213 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
215 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
218 ScrollDirFlagLT
= DFCS_SCROLLUP
;
219 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
220 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
221 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
225 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
226 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
227 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
228 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
231 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
233 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
235 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
237 ScrollDirFlagLT
|= DFCS_INACTIVE
;
239 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
241 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
243 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
245 ScrollDirFlagRB
|= DFCS_INACTIVE
;
248 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
249 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
253 IntScrollDrawMovingThumb(HDC Dc
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
255 INT Pos
= ScrollTrackingPos
;
261 MaxSize
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->rcScrollBar
.top
;
265 MaxSize
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->rcScrollBar
.left
;
268 MaxSize
-= ScrollBarInfo
->dxyLineButton
+ ScrollBarInfo
->xyThumbBottom
269 - ScrollBarInfo
->xyThumbTop
;
271 if (Pos
< ScrollBarInfo
->dxyLineButton
)
273 Pos
= ScrollBarInfo
->dxyLineButton
;
275 else if (MaxSize
< Pos
)
280 OldTop
= ScrollBarInfo
->xyThumbTop
;
281 ScrollBarInfo
->xyThumbBottom
= Pos
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
282 ScrollBarInfo
->xyThumbTop
= Pos
;
283 IntDrawScrollInterior(ScrollTrackingWin
, Dc
, ScrollTrackingBar
, Vertical
, ScrollBarInfo
);
284 ScrollBarInfo
->xyThumbBottom
= OldTop
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
285 ScrollBarInfo
->xyThumbTop
= OldTop
;
287 ScrollMovingThumb
= ! ScrollMovingThumb
;
291 IntScrollGetObjectId(INT SBType
)
293 if (SB_VERT
== SBType
)
295 return OBJID_VSCROLL
;
297 if (SB_HORZ
== SBType
)
299 return OBJID_HSCROLL
;
306 IntGetScrollBarInfo(HWND Wnd
, INT Bar
, PSCROLLBARINFO ScrollBarInfo
)
308 ScrollBarInfo
->cbSize
= sizeof(SCROLLBARINFO
);
310 return NtUserGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), ScrollBarInfo
);
314 IntDrawScrollBar(HWND Wnd
, HDC DC
, INT Bar
)
321 * Get scroll bar info.
334 Vertical
= (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) != 0;
340 if (! IntGetScrollBarInfo(Wnd
, Bar
, &Info
))
345 if (IsRectEmpty(&Info
.rcScrollBar
))
350 ThumbSize
= Info
.xyThumbBottom
- Info
.xyThumbTop
;
355 if (Info
.dxyLineButton
)
357 IntDrawScrollArrows(DC
, &Info
, Vertical
);
363 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
366 * If scroll bar has focus, reposition the caret.
368 if (Wnd
== GetFocus() && SB_CTL
== Bar
)
372 SetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
376 SetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
382 IntScrollPtInRectEx(LPRECT Rect
, POINT Pt
, BOOL Vertical
)
384 RECT TempRect
= *Rect
;
387 TempRect
.left
-= Rect
->right
- Rect
->left
;
388 TempRect
.right
+= Rect
->right
- Rect
->left
;
392 TempRect
.top
-= Rect
->bottom
- Rect
->top
;
393 TempRect
.bottom
+= Rect
->bottom
- Rect
->top
;
396 return PtInRect(&TempRect
, Pt
);
399 static DWORD FASTCALL
400 IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
, POINT Pt
, BOOL Dragging
)
402 INT ArrowSize
, ThumbSize
, ThumbPos
;
404 if ((Dragging
&& ! IntScrollPtInRectEx(&ScrollBarInfo
->rcScrollBar
, Pt
, Vertical
)) ||
405 ! PtInRect(&ScrollBarInfo
->rcScrollBar
, Pt
))
407 return SCROLL_NOWHERE
;
410 ThumbPos
= ScrollBarInfo
->xyThumbTop
;
411 ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ThumbPos
;
412 ArrowSize
= ScrollBarInfo
->dxyLineButton
;
416 if (Pt
.y
< ScrollBarInfo
->rcScrollBar
.top
+ ArrowSize
)
418 return SCROLL_TOP_ARROW
;
420 if (ScrollBarInfo
->rcScrollBar
.bottom
- ArrowSize
<= Pt
.y
)
422 return SCROLL_BOTTOM_ARROW
;
426 return SCROLL_TOP_RECT
;
428 Pt
.y
-= ScrollBarInfo
->rcScrollBar
.top
;
431 return SCROLL_TOP_RECT
;
433 if (ThumbPos
+ ThumbSize
<= Pt
.y
)
435 return SCROLL_BOTTOM_RECT
;
440 if (Pt
.x
< ScrollBarInfo
->rcScrollBar
.left
+ ArrowSize
)
442 return SCROLL_TOP_ARROW
;
444 if (ScrollBarInfo
->rcScrollBar
.right
- ArrowSize
<= Pt
.x
)
446 return SCROLL_BOTTOM_ARROW
;
450 return SCROLL_TOP_RECT
;
452 Pt
.x
-= ScrollBarInfo
->rcScrollBar
.left
;
455 return SCROLL_TOP_RECT
;
457 if (ThumbPos
+ ThumbSize
<= Pt
.x
)
459 return SCROLL_BOTTOM_RECT
;
467 /***********************************************************************
468 * IntScrollGetScrollBarRect
470 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
471 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
472 * 'arrowSize' returns the width or height of an arrow (depending on
473 * the orientation of the scrollbar), 'thumbSize' returns the size of
474 * the thumb, and 'thumbPos' returns the position of the thumb
475 * relative to the left or to the top.
476 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
479 IntScrollGetScrollBarRect(HWND Wnd
, INT Bar
, RECT
*Rect
,
480 INT
*ArrowSize
, INT
*ThumbSize
,
487 DWORD Style
, ExStyle
;
489 GetClientRect(Wnd
, &ClientRect
);
490 if (SB_HORZ
== Bar
|| SB_VERT
== Bar
)
492 ClientToScreen(Wnd
, (LPPOINT
) &ClientRect
.left
);
493 ClientToScreen(Wnd
, (LPPOINT
) &ClientRect
.right
);
494 GetWindowRect(Wnd
, &WindowRect
);
496 Style
= GetWindowLongPtrW(Wnd
, GWL_STYLE
);
501 Rect
->left
= ClientRect
.left
- WindowRect
.left
;
502 Rect
->top
= ClientRect
.bottom
- WindowRect
.top
;
503 Rect
->right
= ClientRect
.right
- WindowRect
.left
;
504 Rect
->bottom
= Rect
->top
+ GetSystemMetrics(SM_CYHSCROLL
);
505 if (0 != (Style
& WS_BORDER
))
510 else if (0 != (Style
& WS_VSCROLL
))
518 ExStyle
= GetWindowLongPtrW(Wnd
, GWL_EXSTYLE
);
519 if (0 != (ExStyle
& WS_EX_LEFTSCROLLBAR
))
521 Rect
->left
= ClientRect
.left
- WindowRect
.left
- GetSystemMetrics(SM_CXVSCROLL
);
525 Rect
->left
= ClientRect
.right
- WindowRect
.left
;
527 Rect
->top
= ClientRect
.top
- WindowRect
.top
;
528 Rect
->right
= Rect
->left
+ GetSystemMetrics(SM_CXVSCROLL
);
529 Rect
->bottom
= ClientRect
.bottom
- WindowRect
.top
;
530 if (0 != (Style
& WS_BORDER
))
535 else if (0 != (Style
& WS_HSCROLL
))
544 Vertical
= (0 != (Style
& SBS_VERT
));
553 Pixels
= Rect
->bottom
- Rect
->top
;
557 Pixels
= Rect
->right
- Rect
->left
;
560 if (Pixels
<= 2 * GetSystemMetrics(SM_CXVSCROLL
) + SCROLL_MIN_RECT
)
562 if (SCROLL_MIN_RECT
< Pixels
)
564 *ArrowSize
= (Pixels
- SCROLL_MIN_RECT
) / 2;
570 *ThumbPos
= *ThumbSize
= 0;
576 NtUserGetScrollInfo(Wnd
, Bar
, &Info
);
577 *ArrowSize
= GetSystemMetrics(SM_CXVSCROLL
);
578 Pixels
-= (2 * GetSystemMetrics(SM_CXVSCROLL
));
582 *ThumbSize
= MulDiv(Pixels
, Info
.nPage
, (Info
.nMax
- Info
.nMin
+ 1));
583 if (*ThumbSize
< SCROLL_MIN_THUMB
)
585 *ThumbSize
= SCROLL_MIN_THUMB
;
590 *ThumbSize
= GetSystemMetrics(SM_CXVSCROLL
);
594 if (((pixels
-= *ThumbSize
) < 0) ||
595 ((info
->flags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
))
597 if ((Pixels
-= *ThumbSize
) < 0)
600 /* Rectangle too small or scrollbar disabled -> no thumb */
601 *ThumbPos
= *ThumbSize
= 0;
605 INT Max
= Info
.nMax
- max(Info
.nPage
- 1, 0);
606 if (Max
<= Info
.nMin
)
608 *ThumbPos
= *ArrowSize
;
612 *ThumbPos
= *ArrowSize
613 + MulDiv(Pixels
, (Info
.nPos
- Info
.nMin
),
622 /***********************************************************************
623 * IntScrollGetThumbVal
625 * Compute the current scroll position based on the thumb position in pixels
626 * from the top of the scroll-bar.
629 IntScrollGetThumbVal(HWND Wnd
, INT SBType
, PSCROLLBARINFO ScrollBarInfo
,
630 BOOL Vertical
, INT Pos
)
633 INT Pixels
= Vertical
? ScrollBarInfo
->rcScrollBar
.bottom
634 - ScrollBarInfo
->rcScrollBar
.top
635 : ScrollBarInfo
->rcScrollBar
.right
636 - ScrollBarInfo
->rcScrollBar
.left
;
638 si
.cbSize
= sizeof(SCROLLINFO
);
639 si
.fMask
= SIF_RANGE
| SIF_PAGE
;
640 NtUserGetScrollInfo(Wnd
, SBType
, &si
);
641 if ((Pixels
-= 2 * ScrollBarInfo
->dxyLineButton
) <= 0)
646 if ((Pixels
-= (ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
)) <= 0)
651 Pos
= Pos
- ScrollBarInfo
->dxyLineButton
;
663 Pos
*= si
.nMax
- si
.nMin
;
667 Pos
*= si
.nMax
- si
.nMin
- si
.nPage
+ 1;
669 return si
.nMin
+ ((Pos
+ Pixels
/ 2) / Pixels
);
672 /***********************************************************************
675 static POINT
IntScrollClipPos(PRECT Rect
, POINT Pt
)
677 if (Pt
.x
< Rect
->left
)
681 else if (Rect
->right
< Pt
.x
)
686 if (Pt
.y
< Rect
->top
)
690 else if (Rect
->bottom
< Pt
.y
)
698 /***********************************************************************
699 * IntScrollDrawSizeGrip
701 * Draw the size grip.
704 IntScrollDrawSizeGrip(HWND Wnd
, HDC Dc
)
708 GetClientRect(Wnd
, &Rect
);
709 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
710 Rect
.left
= max(Rect
.left
, Rect
.right
- GetSystemMetrics(SM_CXVSCROLL
) - 1);
711 Rect
.top
= max(Rect
.top
, Rect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) - 1);
712 DrawFrameControl(Dc
, &Rect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
717 /***********************************************************************
718 * IntScrollHandleKbdEvent
720 * Handle a keyboard event (only for SB_CTL scrollbars with focus).
723 IntScrollHandleKbdEvent(
724 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
725 WPARAM wParam
/* [in] Variable input including enable state */,
726 LPARAM lParam
/* [in] Variable input including input point */)
728 TRACE("Wnd=%p wParam=%ld lParam=%ld\n", Wnd
, wParam
, lParam
);
730 /* hide caret on first KEYDOWN to prevent flicker */
731 if (0 == (lParam
& PFD_DOUBLEBUFFER_DONTCARE
))
743 wParam
= SB_PAGEDOWN
;
759 wParam
= SB_LINEDOWN
;
766 SendMessageW(GetParent(Wnd
),
767 (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) ?
768 WM_VSCROLL
: WM_HSCROLL
), wParam
, (LPARAM
) Wnd
);
771 /***********************************************************************
772 * IntScrollHandleScrollEvent
774 * Handle a mouse or timer event for the scrollbar.
775 * 'Pt' is the location of the mouse event in drawing coordinates
778 IntScrollHandleScrollEvent(HWND Wnd
, INT SBType
, UINT Msg
, POINT Pt
)
780 static POINT PrevPt
; /* Previous mouse position for timer events */
781 static UINT TrackThumbPos
; /* Thumb position when tracking started. */
782 static INT LastClickPos
; /* Position in the scroll-bar of the last
783 button-down event. */
784 static INT LastMousePos
; /* Position in the scroll-bar of the last
788 HWND WndOwner
, WndCtl
;
791 SCROLLBARINFO ScrollBarInfo
;
792 SETSCROLLBARINFO NewInfo
;
794 if (! IntGetScrollBarInfo(Wnd
, SBType
, &ScrollBarInfo
))
798 if (SCROLL_NOWHERE
== ScrollTrackHitTest
&& WM_LBUTTONDOWN
!= Msg
)
803 NewInfo
.nTrackPos
= ScrollTrackingVal
;
804 NewInfo
.reserved
= ScrollBarInfo
.reserved
;
805 memcpy(NewInfo
.rgstate
, ScrollBarInfo
.rgstate
, (CCHILDREN_SCROLLBAR
+ 1) * sizeof(DWORD
));
808 && 0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
812 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
813 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
816 ScrollTrackHitTest
= HitTest
= SCROLL_THUMB
;
819 GetClientRect(GetParent(GetParent(Wnd
)), &ScrollBarInfo
.rcScrollBar
);
824 ScrollTrackHitTest
= HitTest
= SCROLL_NOWHERE
;
825 if (Wnd
== GetFocus())
837 Dc
= GetDCEx(Wnd
, 0, DCX_CACHE
| ((SB_CTL
== SBType
) ? 0 : DCX_WINDOW
));
838 if (SB_VERT
== SBType
)
842 else if (SB_HORZ
== SBType
)
848 Vertical
= (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
));
850 WndOwner
= (SB_CTL
== SBType
) ? GetParent(Wnd
) : Wnd
;
851 WndCtl
= (SB_CTL
== SBType
) ? Wnd
: NULL
;
855 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
856 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
857 ScrollTrackVertical
= Vertical
;
858 ScrollTrackHitTest
= HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
859 LastClickPos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
860 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
861 LastMousePos
= LastClickPos
;
862 TrackThumbPos
= ScrollBarInfo
.xyThumbTop
;
864 if (SB_CTL
== SBType
&& 0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_TABSTOP
))
869 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] |= STATE_SYSTEM_PRESSED
;
870 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
871 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
875 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, TRUE
);
880 HitTest
= SCROLL_NOWHERE
;
882 /* if scrollbar has focus, show back caret */
883 if (Wnd
== GetFocus())
887 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] &= ~STATE_SYSTEM_PRESSED
;
888 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
889 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
894 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
898 return; /* Should never happen */
901 switch (ScrollTrackHitTest
)
903 case SCROLL_NOWHERE
: /* No tracking in progress */
906 case SCROLL_TOP_ARROW
:
907 if (HitTest
== ScrollTrackHitTest
)
909 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
911 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
912 SB_LINEUP
, (LPARAM
) WndCtl
);
914 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
915 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
920 KillSystemTimer(Wnd
, SCROLL_TIMER
);
924 case SCROLL_TOP_RECT
:
925 if (HitTest
== ScrollTrackHitTest
)
927 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
929 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
930 SB_PAGEUP
, (LPARAM
) WndCtl
);
932 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
933 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
938 KillSystemTimer(Wnd
, SCROLL_TIMER
);
943 if (WM_LBUTTONDOWN
== Msg
)
945 ScrollTrackingWin
= Wnd
;
946 ScrollTrackingBar
= SBType
;
947 ScrollTrackingPos
= TrackThumbPos
+ LastMousePos
- LastClickPos
;
948 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
949 Vertical
, ScrollTrackingPos
);
950 NewInfo
.nTrackPos
= ScrollTrackingVal
;
951 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
952 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
954 else if (WM_LBUTTONUP
== Msg
)
956 ScrollTrackingWin
= 0;
957 ScrollTrackingVal
= 0;
958 IntDrawScrollInterior(Wnd
, Dc
, SBType
, Vertical
, &ScrollBarInfo
);
960 else /* WM_MOUSEMOVE */
964 if (! IntScrollPtInRectEx(&ScrollBarInfo
.rcScrollBar
, Pt
, Vertical
))
970 Pt
= IntScrollClipPos(&ScrollBarInfo
.rcScrollBar
, Pt
);
971 Pos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
972 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
974 if (Pos
!= LastMousePos
|| ! ScrollMovingThumb
)
977 ScrollTrackingPos
= TrackThumbPos
+ Pos
- LastClickPos
;
978 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
979 Vertical
, ScrollTrackingPos
);
980 NewInfo
.nTrackPos
= ScrollTrackingVal
;
981 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
982 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
983 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
984 MAKEWPARAM(SB_THUMBTRACK
, ScrollTrackingVal
),
990 case SCROLL_BOTTOM_RECT
:
991 if (HitTest
== ScrollTrackHitTest
)
993 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
995 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
996 SB_PAGEDOWN
, (LPARAM
) WndCtl
);
998 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
999 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
1004 KillSystemTimer(Wnd
, SCROLL_TIMER
);
1008 case SCROLL_BOTTOM_ARROW
:
1009 if (HitTest
== ScrollTrackHitTest
)
1011 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
1013 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1014 SB_LINEDOWN
, (LPARAM
) WndCtl
);
1016 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
1017 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
1022 KillSystemTimer(Wnd
, SCROLL_TIMER
);
1027 if (WM_LBUTTONDOWN
== Msg
)
1029 if (SCROLL_THUMB
== HitTest
)
1031 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1032 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1033 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1034 MAKEWPARAM(SB_THUMBTRACK
, Val
), (LPARAM
) WndCtl
);
1038 if (WM_LBUTTONUP
== Msg
)
1040 HitTest
= ScrollTrackHitTest
;
1041 ScrollTrackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
1043 if (SCROLL_THUMB
== HitTest
)
1045 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1046 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1047 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1048 MAKEWPARAM(SB_THUMBPOSITION
, Val
), (LPARAM
) WndCtl
);
1050 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1051 SB_ENDSCROLL
, (LPARAM
) WndCtl
);
1058 /***********************************************************************
1059 * IntScrollCreateScrollBar
1061 * Create a scroll bar
1063 static void IntScrollCreateScrollBar(
1064 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
1065 LPCREATESTRUCTW lpCreate
/* [in] The style and place of the scroll bar */)
1069 Info
.cbSize
= sizeof(SCROLLINFO
);
1070 Info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
1076 NtUserSetScrollInfo(Wnd
, SB_CTL
, &Info
, FALSE
);
1078 TRACE("hwnd=%p lpCreate=%p\n", Wnd
, lpCreate
);
1081 if (lpCreate
->style
& WS_DISABLED
)
1083 info
->flags
= ESB_DISABLE_BOTH
;
1084 TRACE("Created WS_DISABLED scrollbar\n");
1088 if (0 != (lpCreate
->style
& (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
1090 if (0 != (lpCreate
->style
& SBS_SIZEBOXTOPLEFTALIGN
))
1092 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
, GetSystemMetrics(SM_CXVSCROLL
) + 1,
1093 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1095 else if (0 != (lpCreate
->style
& SBS_SIZEBOXBOTTOMRIGHTALIGN
))
1097 MoveWindow(Wnd
, lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1098 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1099 GetSystemMetrics(SM_CXVSCROLL
) + 1,
1100 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1103 else if (0 != (lpCreate
->style
& SBS_VERT
))
1105 if (0 != (lpCreate
->style
& SBS_LEFTALIGN
))
1107 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1108 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1110 else if (0 != (lpCreate
->style
& SBS_RIGHTALIGN
))
1113 lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1115 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1120 if (0 != (lpCreate
->style
& SBS_TOPALIGN
))
1122 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1123 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1125 else if (0 != (lpCreate
->style
& SBS_BOTTOMALIGN
))
1129 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1130 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1136 IntScrollGetScrollPos(HWND Wnd
, INT Bar
)
1138 SCROLLINFO ScrollInfo
;
1140 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1141 ScrollInfo
.fMask
= SIF_POS
;
1142 if (! NtUserGetScrollInfo(Wnd
, Bar
, &ScrollInfo
))
1147 return ScrollInfo
.nPos
;
1150 static BOOL FASTCALL
1151 IntScrollGetScrollRange(HWND Wnd
, int Bar
, LPINT MinPos
, LPINT MaxPos
)
1154 SCROLLINFO ScrollInfo
;
1156 if (NULL
== MinPos
|| NULL
== MaxPos
)
1158 SetLastError(ERROR_INVALID_PARAMETER
);
1162 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1163 ScrollInfo
.fMask
= SIF_RANGE
;
1164 Result
= NtUserGetScrollInfo(Wnd
, Bar
, &ScrollInfo
);
1167 *MinPos
= ScrollInfo
.nMin
;
1168 *MaxPos
= ScrollInfo
.nMax
;
1174 /* USER32 INTERNAL FUNCTIONS **************************************************/
1176 /***********************************************************************
1177 * ScrollTrackScrollBar
1179 * Track a mouse button press on a scroll-bar.
1180 * pt is in screen-coordinates for non-client scroll bars.
1183 ScrollTrackScrollBar(HWND Wnd
, INT SBType
, POINT Pt
)
1187 UINT XOffset
, YOffset
;
1190 if (SB_CTL
!= SBType
)
1192 GetWindowRect(Wnd
, &WindowRect
);
1194 Pt
.x
-= WindowRect
.left
;
1195 Pt
.y
-= WindowRect
.top
;
1197 TopLeft
.x
= WindowRect
.left
;
1198 TopLeft
.y
= WindowRect
.top
;
1199 ScreenToClient(Wnd
, &TopLeft
);
1200 XOffset
= - TopLeft
.x
;
1201 YOffset
= - TopLeft
.y
;
1209 IntScrollHandleScrollEvent(Wnd
, SBType
, WM_LBUTTONDOWN
, Pt
);
1213 if (! GetMessageW(&Msg
, 0, 0, 0))
1217 if (CallMsgFilterW(&Msg
, MSGF_SCROLLBAR
))
1227 Pt
.x
= LOWORD(Msg
.lParam
) + XOffset
;
1228 Pt
.y
= HIWORD(Msg
.lParam
) + YOffset
;
1229 IntScrollHandleScrollEvent(Wnd
, SBType
, Msg
.message
, Pt
);
1232 TranslateMessage(&Msg
);
1233 DispatchMessageW(&Msg
);
1237 if (! IsWindow(Wnd
))
1243 while (WM_LBUTTONUP
!= Msg
.message
);
1247 /***********************************************************************
1251 ScrollBarWndProc(WNDPROC DefWindowProc
, HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1253 if (! IsWindow(Wnd
))
1261 IntScrollCreateScrollBar(Wnd
, (LPCREATESTRUCTW
) lParam
);
1267 // SCROLLBAR_INFO *infoPtr;
1268 // if ((infoPtr = SCROLL_GetScrollBarInfo( hwnd, SB_CTL )))
1270 // infoPtr->flags = wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH;
1271 // SCROLL_RefreshScrollBar(hwnd, SB_CTL, TRUE, TRUE);
1274 DbgPrint("ScrollBarWndProc WM_ENABLE\n");
1275 NtUserEnableScrollBar(Wnd
,SB_CTL
,(wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
));
1276 /* Refresh Scrollbars. */
1277 hdc
= GetDCEx( Wnd
, 0, DCX_CACHE
);
1279 IntDrawScrollBar( Wnd
, hdc
, SB_CTL
);
1280 ReleaseDC( Wnd
, hdc
);
1285 case WM_LBUTTONDBLCLK
:
1286 case WM_LBUTTONDOWN
:
1290 Pt
.x
= (short)LOWORD(lParam
);
1291 Pt
.y
= (short)HIWORD(lParam
);
1292 ScrollTrackScrollBar(Wnd
, SB_CTL
, Pt
);
1302 Pt
.x
= (short)LOWORD(lParam
);
1303 Pt
.y
= (short)HIWORD(lParam
);
1304 IntScrollHandleScrollEvent(Wnd
, SB_CTL
, Msg
, Pt
);
1309 IntScrollHandleKbdEvent(Wnd
, wParam
, lParam
);
1318 /* Create a caret when a ScrollBar get focus */
1320 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1322 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1323 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1326 CreateCaret(Wnd
, (HBITMAP
) 1, ThumbSize
- 2, Rect
.bottom
- Rect
.top
- 2);
1327 SetCaretPos(ThumbPos
+ 1, Rect
.top
+ 1);
1331 CreateCaret(Wnd
, (HBITMAP
) 1, Rect
.right
- Rect
.left
- 2, ThumbSize
- 2);
1332 SetCaretPos(Rect
.top
+ 1, ThumbPos
+ 1);
1341 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1343 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1344 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1347 Rect
.left
= ThumbPos
+ 1;
1348 Rect
.right
= Rect
.left
+ ThumbSize
;
1352 Rect
.top
= ThumbPos
+ 1;
1353 Rect
.bottom
= Rect
.top
+ ThumbSize
;
1356 InvalidateRect(Wnd
, &Rect
, FALSE
);
1365 return DLGC_WANTARROWS
; /* Windows returns this value */
1372 Dc
= (0 != wParam
? (HDC
) wParam
: BeginPaint(Wnd
, &Ps
));
1374 if (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1376 IntScrollDrawSizeGrip(Wnd
, Dc
);
1378 else if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEBOX
))
1381 GetClientRect(Wnd
, &Rect
);
1382 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
1386 IntDrawScrollBar(Wnd
, Dc
, SB_CTL
/*, TRUE, TRUE*/);
1397 return SetScrollPos(Wnd
, SB_CTL
, wParam
, (BOOL
) lParam
);
1400 return IntScrollGetScrollPos(Wnd
, SB_CTL
);
1404 INT OldPos
= IntScrollGetScrollPos(Wnd
, SB_CTL
);
1405 SetScrollRange(Wnd
, SB_CTL
, wParam
, lParam
, FALSE
);
1406 if (OldPos
!= IntScrollGetScrollPos(Wnd
, SB_CTL
))
1414 return IntScrollGetScrollRange(Wnd
, SB_CTL
, (LPINT
) wParam
, (LPINT
) lParam
);
1416 case SBM_ENABLE_ARROWS
:
1417 return EnableScrollBar(Wnd
, SB_CTL
, wParam
);
1419 case SBM_SETRANGEREDRAW
:
1421 INT OldPos
= IntScrollGetScrollPos(Wnd
, SB_CTL
);
1422 SetScrollRange(Wnd
, SB_CTL
, wParam
, lParam
, TRUE
);
1423 if (OldPos
!= IntScrollGetScrollPos(Wnd
, SB_CTL
))
1430 case SBM_SETSCROLLINFO
:
1431 return NtUserSetScrollInfo(Wnd
, SB_CTL
, (SCROLLINFO
*) lParam
, wParam
);
1433 case SBM_GETSCROLLINFO
:
1434 return NtUserGetScrollInfo(Wnd
, SB_CTL
, (SCROLLINFO
*) lParam
);
1444 WARN("unknown Win32 msg %04x wp=%08lx lp=%08lx\n",
1445 Msg
, wParam
, lParam
);
1451 WARN("unknown msg %04x wp=%04lx lp=%08lx\n", Msg
, wParam
, lParam
);
1453 return DefWindowProc(Wnd
, Msg
, wParam
, lParam
);
1460 ScrollBarWndProcW(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1462 return ScrollBarWndProc(DefWindowProcW
, Wnd
, Msg
, wParam
, lParam
);
1466 ScrollBarWndProcA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1468 return ScrollBarWndProc(DefWindowProcA
, Wnd
, Msg
, wParam
, lParam
);
1472 /* PUBLIC FUNCTIONS ***********************************************************/
1477 BOOL WINAPI
EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
1479 BOOL Hook
, Ret
= FALSE
;
1483 Hook
= BeginIfHookedUserApiHook();
1485 /* Bypass SEH and go direct. */
1486 if (!Hook
) return NtUserEnableScrollBar(hwnd
, nBar
, flags
);
1490 Ret
= guah
.EnableScrollBar(hwnd
, nBar
, flags
);
1492 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1503 RealGetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1505 if (SB_CTL
== SBType
)
1507 return SendMessageW(Wnd
, SBM_GETSCROLLINFO
, 0, (LPARAM
) Info
);
1511 return NtUserGetScrollInfo(Wnd
, SBType
, Info
);
1519 GetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1521 BOOL Hook
, Ret
= FALSE
;
1525 Hook
= BeginIfHookedUserApiHook();
1527 /* Bypass SEH and go direct. */
1528 if (!Hook
) return RealGetScrollInfo(Wnd
, SBType
, Info
);
1532 Ret
= guah
.GetScrollInfo(Wnd
, SBType
, Info
);
1534 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1548 GetScrollPos(HWND Wnd
, INT Bar
)
1550 TRACE("Wnd=%p Bar=%d\n", Wnd
, Bar
);
1552 /* Refer SB_CTL requests to the window */
1555 return SendMessageW(Wnd
, SBM_GETPOS
, (WPARAM
) 0, (LPARAM
) 0);
1559 return IntScrollGetScrollPos(Wnd
, Bar
);
1567 GetScrollRange(HWND Wnd
, int Bar
, LPINT MinPos
, LPINT MaxPos
)
1569 TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd
, Bar
, MinPos
, MaxPos
);
1571 /* Refer SB_CTL requests to the window */
1574 return SendMessageW(Wnd
, SBM_GETRANGE
, (WPARAM
) MinPos
, (LPARAM
) MaxPos
);
1578 return IntScrollGetScrollRange(Wnd
, Bar
, MinPos
, MaxPos
);
1583 RealSetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1585 if (SB_CTL
== SBType
)
1587 return SendMessageW(Wnd
, SBM_SETSCROLLINFO
, (WPARAM
) bRedraw
, (LPARAM
) Info
);
1591 return NtUserSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1599 SetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1606 Hook
= BeginIfHookedUserApiHook();
1608 /* Bypass SEH and go direct. */
1609 if (!Hook
) return RealSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1613 Ret
= guah
.SetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1615 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1630 SetScrollPos(HWND hWnd
, INT nBar
, INT nPos
, BOOL bRedraw
)
1633 SCROLLINFO ScrollInfo
;
1635 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1636 ScrollInfo
.fMask
= SIF_POS
;
1639 * Call NtUserGetScrollInfo() to get the previous position that
1640 * we will later return.
1642 if (NtUserGetScrollInfo(hWnd
, nBar
, &ScrollInfo
))
1644 Result
= ScrollInfo
.nPos
;
1647 ScrollInfo
.nPos
= nPos
;
1648 /* Finally set the new position */
1649 NtUserSetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
);
1660 SetScrollRange(HWND hWnd
, INT nBar
, INT nMinPos
, INT nMaxPos
, BOOL bRedraw
)
1662 SCROLLINFO ScrollInfo
;
1664 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1665 ScrollInfo
.fMask
= SIF_RANGE
;
1666 ScrollInfo
.nMin
= nMinPos
;
1667 ScrollInfo
.nMax
= nMaxPos
;
1668 NtUserSetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
);