2 * ReactOS User32 Library
5 * Copyright 2001 Casper S. Hornstrup
6 * Copyright 2003 Thomas Weidenmueller
7 * Copyright 2003 Filip Navara
11 * Copyright 1993 Martin Ayotte
12 * Copyright 1994, 1996 Alexandre Julliard
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 /* INCLUDES *******************************************************************/
33 #include <wine/debug.h>
34 WINE_DEFAULT_DEBUG_CHANNEL(scrollbar
);
36 /* GLOBAL VARIABLES ***********************************************************/
38 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
39 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
40 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
41 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
42 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
43 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
44 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
46 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
47 holding the button down */
48 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
50 #define SCROLL_TIMER 0 /* Scroll timer id */
52 /* Minimum size of the rectangle between the arrows */
53 #define SCROLL_MIN_RECT 4
55 /* Minimum size of the thumb in pixels */
56 #define SCROLL_MIN_THUMB 6
58 /* Overlap between arrows and thumb */
59 #define SCROLL_ARROW_THUMB_OVERLAP 0
61 /* Thumb-tracking info */
62 static HWND ScrollTrackingWin
= 0;
63 static INT ScrollTrackingBar
= 0;
64 static INT ScrollTrackingPos
= 0;
65 static INT ScrollTrackingVal
= 0;
66 static BOOL ScrollMovingThumb
= FALSE
;
68 static DWORD ScrollTrackHitTest
= SCROLL_NOWHERE
;
69 static BOOL ScrollTrackVertical
;
71 HBRUSH
DefWndControlColor(HDC hDC
, UINT ctlType
);
73 UINT_PTR WINAPI
SetSystemTimer(HWND
,UINT_PTR
,UINT
,TIMERPROC
);
74 BOOL WINAPI
KillSystemTimer(HWND
,UINT_PTR
);
76 /*********************************************************************
77 * scrollbar class descriptor
79 const struct builtin_class_descr SCROLL_builtin_class
=
81 L
"ScrollBar", /* name */
82 CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
| CS_PARENTDC
, /* style */
83 ScrollBarWndProcA
, /* procA */
84 ScrollBarWndProcW
, /* procW */
85 sizeof(SBWND
)-sizeof(WND
), /* extra */
86 IDC_ARROW
, /* cursor */
90 /* PRIVATE FUNCTIONS **********************************************************/
93 IntGetSBData(PWND pwnd
, INT Bar
)
98 pSBInfo
= DesktopPtrToUser(pwnd
->pSBInfo
);
102 return &pSBInfo
->Horz
;
104 return &pSBInfo
->Vert
;
106 if ( pwnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
108 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
111 pSBWnd
= (PSBWND
)pwnd
;
112 return (PSBDATA
)&pSBWnd
->SBCalc
;
114 ERR("IntGetSBData Bad Bar!\n");
120 IntDrawScrollInterior(HWND hWnd
, HDC hDC
, INT nBar
, BOOL Vertical
,
121 PSCROLLBARINFO ScrollBarInfo
)
123 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
124 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
126 HBRUSH hSaveBrush
, hBrush
;
127 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
129 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
131 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
132 BottomSelected
= TRUE
;
135 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
136 * The window-owned scrollbars need to call DefWndControlColor
137 * to correctly setup default scrollbar colors
141 hBrush
= GetControlBrush( hWnd
, hDC
, WM_CTLCOLORSCROLLBAR
);
143 hBrush
= GetSysColorBrush(COLOR_SCROLLBAR
);
147 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
150 hSaveBrush
= SelectObject(hDC
, hBrush
);
152 /* Calculate the scroll rectangle */
155 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
156 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
157 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
158 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
162 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
163 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
164 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
165 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
168 /* Draw the scroll rectangles and thumb */
169 if (!ScrollBarInfo
->xyThumbBottom
)
171 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
172 Rect
.bottom
- Rect
.top
, PATCOPY
);
174 /* Cleanup and return */
175 SelectObject(hDC
, hSaveBrush
);
179 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
181 if (ScrollBarInfo
->dxyLineButton
)
187 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
188 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
189 Rect
.top
+= ThumbTop
;
190 PatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
191 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
192 Rect
.bottom
= Rect
.top
+ ThumbSize
;
198 PatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
199 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
207 PatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
208 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
209 Rect
.left
+= ThumbTop
;
210 PatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
211 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
212 BottomSelected
? BLACKNESS
: PATCOPY
);
213 Rect
.right
= Rect
.left
+ ThumbSize
;
219 PatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
220 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
228 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
231 SelectObject(hDC
, hSaveBrush
);
235 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
238 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
240 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
243 ScrollDirFlagLT
= DFCS_SCROLLUP
;
244 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
245 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
246 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
250 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
251 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
252 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
253 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
256 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
258 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
260 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
262 ScrollDirFlagLT
|= DFCS_INACTIVE
;
264 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
266 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
268 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
270 ScrollDirFlagRB
|= DFCS_INACTIVE
;
273 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
274 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
278 IntScrollDrawMovingThumb(HDC Dc
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
280 INT Pos
= ScrollTrackingPos
;
285 MaxSize
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->rcScrollBar
.top
;
287 MaxSize
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->rcScrollBar
.left
;
289 MaxSize
-= ScrollBarInfo
->dxyLineButton
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
291 if (Pos
< ScrollBarInfo
->dxyLineButton
)
292 Pos
= ScrollBarInfo
->dxyLineButton
;
293 else if (MaxSize
< Pos
)
296 OldTop
= ScrollBarInfo
->xyThumbTop
;
297 ScrollBarInfo
->xyThumbBottom
= Pos
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
298 ScrollBarInfo
->xyThumbTop
= Pos
;
299 IntDrawScrollInterior(ScrollTrackingWin
, Dc
, ScrollTrackingBar
, Vertical
, ScrollBarInfo
);
300 ScrollBarInfo
->xyThumbBottom
= OldTop
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
301 ScrollBarInfo
->xyThumbTop
= OldTop
;
303 ScrollMovingThumb
= !ScrollMovingThumb
;
307 IntScrollGetObjectId(INT SBType
)
309 if (SBType
== SB_VERT
)
310 return OBJID_VSCROLL
;
311 if (SBType
== SB_HORZ
)
312 return OBJID_HSCROLL
;
317 IntGetScrollBarInfo(HWND Wnd
, INT Bar
, PSCROLLBARINFO ScrollBarInfo
)
319 ScrollBarInfo
->cbSize
= sizeof(SCROLLBARINFO
);
321 return NtUserGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), ScrollBarInfo
);
325 IntDrawScrollBar(HWND Wnd
, HDC DC
, INT Bar
)
333 * Get scroll bar info.
346 Vertical
= (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) != 0;
352 if (!IntGetScrollBarInfo(Wnd
, Bar
, &Info
))
357 if (IsRectEmpty(&Info
.rcScrollBar
))
362 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
367 if (Info
.dxyLineButton
)
369 IntDrawScrollArrows(DC
, &Info
, Vertical
);
375 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
378 * If scroll bar has focus, reposition the caret.
380 if (Wnd
== GetFocus() && SB_CTL
== Bar
)
384 SetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
388 SetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
394 IntScrollPtInRectEx(LPRECT Rect
, POINT Pt
, BOOL Vertical
)
396 RECT TempRect
= *Rect
;
399 /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
400 * still be considered in the scrollbar. */
403 scrollbarWidth
= Rect
->right
- Rect
->left
;
404 TempRect
.left
-= scrollbarWidth
*8;
405 TempRect
.right
+= scrollbarWidth
*8;
406 TempRect
.top
-= scrollbarWidth
*2;
407 TempRect
.bottom
+= scrollbarWidth
*2;
411 scrollbarWidth
= Rect
->bottom
- Rect
->top
;
412 TempRect
.left
-= scrollbarWidth
*2;
413 TempRect
.right
+= scrollbarWidth
*2;
414 TempRect
.top
-= scrollbarWidth
*8;
415 TempRect
.bottom
+= scrollbarWidth
*8;
418 return PtInRect(&TempRect
, Pt
);
421 static DWORD FASTCALL
422 IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
, POINT Pt
, BOOL Dragging
)
424 INT ArrowSize
, ThumbSize
, ThumbPos
;
426 if ((Dragging
&& ! IntScrollPtInRectEx(&ScrollBarInfo
->rcScrollBar
, Pt
, Vertical
)) ||
427 ! PtInRect(&ScrollBarInfo
->rcScrollBar
, Pt
)) return SCROLL_NOWHERE
;
429 ThumbPos
= ScrollBarInfo
->xyThumbTop
;
430 ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ThumbPos
;
431 ArrowSize
= ScrollBarInfo
->dxyLineButton
;
435 if (Pt
.y
< ScrollBarInfo
->rcScrollBar
.top
+ ArrowSize
) return SCROLL_TOP_ARROW
;
436 if (Pt
.y
>= ScrollBarInfo
->rcScrollBar
.bottom
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
437 if (!ThumbPos
) return SCROLL_TOP_RECT
;
438 Pt
.y
-= ScrollBarInfo
->rcScrollBar
.top
;
439 if (Pt
.y
< ThumbPos
) return SCROLL_TOP_RECT
;
440 if (Pt
.y
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
444 if (Pt
.x
< ScrollBarInfo
->rcScrollBar
.left
+ ArrowSize
) return SCROLL_TOP_ARROW
;
445 if (Pt
.x
>= ScrollBarInfo
->rcScrollBar
.right
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
446 if (!ThumbPos
) return SCROLL_TOP_RECT
;
447 Pt
.x
-= ScrollBarInfo
->rcScrollBar
.left
;
448 if (Pt
.x
< ThumbPos
) return SCROLL_TOP_RECT
;
449 if (Pt
.x
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
456 /***********************************************************************
457 * IntScrollGetScrollBarRect
459 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
460 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
461 * 'arrowSize' returns the width or height of an arrow (depending on
462 * the orientation of the scrollbar), 'thumbSize' returns the size of
463 * the thumb, and 'thumbPos' returns the position of the thumb
464 * relative to the left or to the top.
465 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
468 IntScrollGetScrollBarRect(HWND Wnd
, INT Bar
, RECT
*Rect
,
469 INT
*ArrowSize
, INT
*ThumbSize
,
479 pWnd
= ValidateHwnd( Wnd
);
480 if (!pWnd
) return FALSE
;
481 pSBInfo
= DesktopPtrToUser(pWnd
->pSBInfo
);
483 *Rect
= pWnd
->rcClient
;
484 OffsetRect( Rect
, -pWnd
->rcWindow
.left
, -pWnd
->rcWindow
.top
);
485 if (pWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
486 mirror_rect( &pWnd
->rcWindow
, Rect
);
491 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
492 Rect
->top
= Rect
->bottom
;
493 Rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
494 if (pWnd
->style
& WS_BORDER
)
499 else if (pWnd
->style
& WS_VSCROLL
)
504 pSBData
= &pSBInfo
->Horz
;
508 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
509 if (pWnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
)
511 Rect
->right
= Rect
->left
;
512 Rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
516 Rect
->left
= Rect
->right
;
517 Rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
519 if (pWnd
->style
& WS_BORDER
)
524 else if (pWnd
->style
& WS_HSCROLL
)
529 pSBData
= &pSBInfo
->Vert
;
533 GetClientRect( Wnd
, Rect
);
534 Vertical
= (pWnd
->style
& SBS_VERT
);
535 pSBWnd
= (PSBWND
)pWnd
;
536 pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
543 if (Vertical
) Pixels
= Rect
->bottom
- Rect
->top
;
544 else Pixels
= Rect
->right
- Rect
->left
;
546 if (Pixels
<= 2 * GetSystemMetrics(SM_CXVSCROLL
) + SCROLL_MIN_RECT
)
548 if (SCROLL_MIN_RECT
< Pixels
)
549 *ArrowSize
= (Pixels
- SCROLL_MIN_RECT
) / 2;
552 *ThumbPos
= *ThumbSize
= 0;
556 *ArrowSize
= GetSystemMetrics(SM_CXVSCROLL
);
557 Pixels
-= (2 * (GetSystemMetrics(SM_CXVSCROLL
) - SCROLL_ARROW_THUMB_OVERLAP
));
560 *ThumbSize
= MulDiv(Pixels
, pSBData
->page
, (pSBData
->posMax
- pSBData
->posMin
+ 1));
561 if (*ThumbSize
< SCROLL_MIN_THUMB
) *ThumbSize
= SCROLL_MIN_THUMB
;
563 else *ThumbSize
= GetSystemMetrics(SM_CXVSCROLL
);
565 if (((Pixels
-= *ThumbSize
) < 0) ||
566 (( pSBInfo
->WSBflags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
))
568 /* Rectangle too small or scrollbar disabled -> no thumb */
569 *ThumbPos
= *ThumbSize
= 0;
573 INT Max
= pSBData
->posMax
- max(pSBData
->page
- 1, 0);
574 if (pSBData
->posMin
>= Max
)
575 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
;
577 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
578 + MulDiv(Pixels
, (pSBData
->pos
- pSBData
->posMin
),(Max
- pSBData
->posMin
));
584 /***********************************************************************
585 * IntScrollGetThumbVal
587 * Compute the current scroll position based on the thumb position in pixels
588 * from the top of the scroll-bar.
591 IntScrollGetThumbVal(HWND Wnd
, INT SBType
, PSCROLLBARINFO ScrollBarInfo
,
592 BOOL Vertical
, INT Pos
)
596 INT Pixels
= Vertical
? ScrollBarInfo
->rcScrollBar
.bottom
597 - ScrollBarInfo
->rcScrollBar
.top
598 : ScrollBarInfo
->rcScrollBar
.right
599 - ScrollBarInfo
->rcScrollBar
.left
;
601 pWnd
= ValidateHwnd( Wnd
);
602 if (!pWnd
) return FALSE
;
604 pSBData
= IntGetSBData(pWnd
, SBType
);
606 if ((Pixels
-= 2 * ScrollBarInfo
->dxyLineButton
) <= 0)
608 return pSBData
->posMin
;
611 if ((Pixels
-= (ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
)) <= 0)
613 return pSBData
->posMin
;
616 Pos
= Pos
- ScrollBarInfo
->dxyLineButton
;
621 if (Pos
> Pixels
) Pos
= Pixels
;
624 Pos
*= pSBData
->posMax
- pSBData
->posMin
;
626 Pos
*= pSBData
->posMax
- pSBData
->posMin
- pSBData
->page
+ 1;
628 return pSBData
->posMin
+ ((Pos
+ Pixels
/ 2) / Pixels
);
631 /***********************************************************************
634 static POINT
IntScrollClipPos(PRECT lpRect
, POINT pt
)
636 if( pt
.x
< lpRect
->left
)
639 if( pt
.x
> lpRect
->right
)
640 pt
.x
= lpRect
->right
;
642 if( pt
.y
< lpRect
->top
)
645 if( pt
.y
> lpRect
->bottom
)
646 pt
.y
= lpRect
->bottom
;
651 /***********************************************************************
652 * IntScrollDrawSizeGrip
654 * Draw the size grip.
657 IntScrollDrawSizeGrip(HWND Wnd
, HDC Dc
)
661 GetClientRect(Wnd
, &Rect
);
662 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
663 Rect
.left
= max(Rect
.left
, Rect
.right
- GetSystemMetrics(SM_CXVSCROLL
) - 1);
664 Rect
.top
= max(Rect
.top
, Rect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) - 1);
665 DrawFrameControl(Dc
, &Rect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
668 /***********************************************************************
669 * SCROLL_RefreshScrollBar
671 * Repaint the scroll bar interior after a SetScrollRange() or
672 * SetScrollPos() call.
674 static void SCROLL_RefreshScrollBar( HWND hwnd
, INT nBar
,
675 BOOL arrows
, BOOL interior
)
677 HDC hdc
= GetDCEx( hwnd
, 0,
678 DCX_CACHE
| ((nBar
== SB_CTL
) ? 0 : DCX_WINDOW
) );
681 IntDrawScrollBar( hwnd
, hdc
, nBar
);//, arrows, interior );
682 ReleaseDC( hwnd
, hdc
);
686 /***********************************************************************
687 * IntScrollHandleKbdEvent
689 * Handle a keyboard event (only for SB_CTL scrollbars with focus).
692 IntScrollHandleKbdEvent(
693 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
694 WPARAM wParam
/* [in] Variable input including enable state */,
695 LPARAM lParam
/* [in] Variable input including input point */)
697 TRACE("Wnd=%p wParam=%ld lParam=%ld\n", Wnd
, wParam
, lParam
);
699 /* hide caret on first KEYDOWN to prevent flicker */
700 if (0 == (lParam
& PFD_DOUBLEBUFFER_DONTCARE
))
712 wParam
= SB_PAGEDOWN
;
728 wParam
= SB_LINEDOWN
;
735 SendMessageW(GetParent(Wnd
),
736 (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) ?
737 WM_VSCROLL
: WM_HSCROLL
), wParam
, (LPARAM
) Wnd
);
740 /***********************************************************************
741 * IntScrollHandleScrollEvent
743 * Handle a mouse or timer event for the scrollbar.
744 * 'Pt' is the location of the mouse event in drawing coordinates
747 IntScrollHandleScrollEvent(HWND Wnd
, INT SBType
, UINT Msg
, POINT Pt
)
749 static POINT PrevPt
; /* Previous mouse position for timer events */
750 static UINT TrackThumbPos
; /* Thumb position when tracking started. */
751 static INT LastClickPos
; /* Position in the scroll-bar of the last
752 button-down event. */
753 static INT LastMousePos
; /* Position in the scroll-bar of the last
757 HWND WndOwner
, WndCtl
;
760 SCROLLBARINFO ScrollBarInfo
;
761 SETSCROLLBARINFO NewInfo
;
763 if (! IntGetScrollBarInfo(Wnd
, SBType
, &ScrollBarInfo
))
767 if ((ScrollTrackHitTest
== SCROLL_NOWHERE
) && (Msg
!= WM_LBUTTONDOWN
))
772 NewInfo
.nTrackPos
= ScrollTrackingVal
;
773 NewInfo
.reserved
= ScrollBarInfo
.reserved
;
774 memcpy(NewInfo
.rgstate
, ScrollBarInfo
.rgstate
, (CCHILDREN_SCROLLBAR
+ 1) * sizeof(DWORD
));
776 if (SB_CTL
== SBType
&& 0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
780 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
781 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
784 ScrollTrackHitTest
= HitTest
= SCROLL_THUMB
;
787 GetClientRect(GetParent(GetParent(Wnd
)), &ScrollBarInfo
.rcScrollBar
);
792 ScrollTrackHitTest
= HitTest
= SCROLL_NOWHERE
;
793 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
802 Dc
= GetDCEx(Wnd
, 0, DCX_CACHE
| ((SB_CTL
== SBType
) ? 0 : DCX_WINDOW
));
803 if (SB_VERT
== SBType
)
807 else if (SB_HORZ
== SBType
)
813 Vertical
= (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
));
815 WndOwner
= (SB_CTL
== SBType
) ? GetParent(Wnd
) : Wnd
;
816 WndCtl
= (SB_CTL
== SBType
) ? Wnd
: NULL
;
820 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
821 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
822 ScrollTrackVertical
= Vertical
;
823 ScrollTrackHitTest
= HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
824 LastClickPos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
825 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
826 LastMousePos
= LastClickPos
;
827 TrackThumbPos
= ScrollBarInfo
.xyThumbTop
;
829 if (SB_CTL
== SBType
&& 0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_TABSTOP
)) SetFocus(Wnd
);
831 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] |= STATE_SYSTEM_PRESSED
;
832 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
833 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
837 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, TRUE
);
842 HitTest
= SCROLL_NOWHERE
;
844 /* if scrollbar has focus, show back caret */
845 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
846 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] &= ~STATE_SYSTEM_PRESSED
;
847 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
848 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
850 IntDrawScrollArrows(Dc
, &ScrollBarInfo
, Vertical
);
856 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
860 return; /* Should never happen */
863 TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
864 Wnd
, SBType
, SPY_GetMsgName(Msg
,Wnd
), Pt
.x
, Pt
.y
, HitTest
);
866 switch (ScrollTrackHitTest
)
868 case SCROLL_NOWHERE
: /* No tracking in progress */
871 case SCROLL_TOP_ARROW
:
872 if (HitTest
== ScrollTrackHitTest
)
874 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
876 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
877 SB_LINEUP
, (LPARAM
) WndCtl
);
879 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
880 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
885 KillSystemTimer(Wnd
, SCROLL_TIMER
);
889 case SCROLL_TOP_RECT
:
890 if (HitTest
== ScrollTrackHitTest
)
892 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
894 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
895 SB_PAGEUP
, (LPARAM
) WndCtl
);
897 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
898 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
903 KillSystemTimer(Wnd
, SCROLL_TIMER
);
908 if (Msg
== WM_LBUTTONDOWN
)
910 ScrollTrackingWin
= Wnd
;
911 ScrollTrackingBar
= SBType
;
912 ScrollTrackingPos
= TrackThumbPos
+ LastMousePos
- LastClickPos
;
913 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
914 Vertical
, ScrollTrackingPos
);
915 NewInfo
.nTrackPos
= ScrollTrackingVal
;
916 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
917 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
919 else if (Msg
== WM_LBUTTONUP
)
921 ScrollTrackingWin
= 0;
922 ScrollTrackingVal
= 0;
923 IntDrawScrollInterior(Wnd
, Dc
, SBType
, Vertical
, &ScrollBarInfo
);
925 else /* WM_MOUSEMOVE */
929 if (! IntScrollPtInRectEx(&ScrollBarInfo
.rcScrollBar
, Pt
, Vertical
))
935 Pt
= IntScrollClipPos(&ScrollBarInfo
.rcScrollBar
, Pt
);
936 Pos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
937 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
939 if (Pos
!= LastMousePos
|| ! ScrollMovingThumb
)
942 ScrollTrackingPos
= TrackThumbPos
+ Pos
- LastClickPos
;
943 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
944 Vertical
, ScrollTrackingPos
);
945 NewInfo
.nTrackPos
= ScrollTrackingVal
;
946 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
947 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
948 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
949 MAKEWPARAM(SB_THUMBTRACK
, ScrollTrackingVal
),
955 case SCROLL_BOTTOM_RECT
:
956 if (HitTest
== ScrollTrackHitTest
)
958 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
960 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
961 SB_PAGEDOWN
, (LPARAM
) WndCtl
);
963 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
964 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
969 KillSystemTimer(Wnd
, SCROLL_TIMER
);
973 case SCROLL_BOTTOM_ARROW
:
974 if (HitTest
== ScrollTrackHitTest
)
976 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
978 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
979 SB_LINEDOWN
, (LPARAM
) WndCtl
);
981 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
982 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
985 else KillSystemTimer(Wnd
, SCROLL_TIMER
);
989 if (Msg
== WM_LBUTTONDOWN
)
991 if (SCROLL_THUMB
== HitTest
)
993 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
994 TrackThumbPos
+ LastMousePos
- LastClickPos
);
995 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
996 MAKEWPARAM(SB_THUMBTRACK
, Val
), (LPARAM
) WndCtl
);
1000 if (Msg
== WM_LBUTTONUP
)
1002 HitTest
= ScrollTrackHitTest
;
1003 ScrollTrackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
1005 if (SCROLL_THUMB
== HitTest
)
1007 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1008 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1009 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1010 MAKEWPARAM(SB_THUMBPOSITION
, Val
), (LPARAM
) WndCtl
);
1012 /* SB_ENDSCROLL doesn't report thumb position */
1013 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1014 SB_ENDSCROLL
, (LPARAM
) WndCtl
);
1016 /* Terminate tracking */
1017 ScrollTrackingWin
= 0;
1024 /***********************************************************************
1025 * IntScrollCreateScrollBar
1027 * Create a scroll bar
1029 static void IntScrollCreateScrollBar(
1030 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
1031 LPCREATESTRUCTW lpCreate
/* [in] The style and place of the scroll bar */)
1035 Info
.cbSize
= sizeof(SCROLLINFO
);
1036 Info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
1042 NtUserSetScrollInfo(Wnd
, SB_CTL
, &Info
, FALSE
);
1044 TRACE("hwnd=%p lpCreate=%p\n", Wnd
, lpCreate
);
1047 if (lpCreate
->style
& WS_DISABLED
)
1049 // info->flags = ESB_DISABLE_BOTH;
1050 //NtUserEnableScrollBar(Wnd,SB_CTL,(wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH));
1051 NtUserMessageCall( Wnd
, WM_ENABLE
, FALSE
, 0, 0, FNID_SCROLLBAR
, FALSE
);
1052 ERR("Created WS_DISABLED scrollbar\n");
1055 if (0 != (lpCreate
->style
& (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
1057 if (0 != (lpCreate
->style
& SBS_SIZEBOXTOPLEFTALIGN
))
1059 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
, GetSystemMetrics(SM_CXVSCROLL
) + 1,
1060 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1062 else if (0 != (lpCreate
->style
& SBS_SIZEBOXBOTTOMRIGHTALIGN
))
1064 MoveWindow(Wnd
, lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1065 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1066 GetSystemMetrics(SM_CXVSCROLL
) + 1,
1067 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1070 else if (0 != (lpCreate
->style
& SBS_VERT
))
1072 if (0 != (lpCreate
->style
& SBS_LEFTALIGN
))
1074 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1075 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1077 else if (0 != (lpCreate
->style
& SBS_RIGHTALIGN
))
1080 lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1082 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1087 if (0 != (lpCreate
->style
& SBS_TOPALIGN
))
1089 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1090 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1092 else if (0 != (lpCreate
->style
& SBS_BOTTOMALIGN
))
1096 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1097 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1102 /* USER32 INTERNAL FUNCTIONS **************************************************/
1104 /***********************************************************************
1105 * ScrollTrackScrollBar
1107 * Track a mouse button press on a scroll-bar.
1108 * pt is in screen-coordinates for non-client scroll bars.
1111 ScrollTrackScrollBar(HWND Wnd
, INT SBType
, POINT Pt
)
1114 UINT XOffset
= 0, YOffset
= 0;
1116 if (SBType
!= SB_CTL
)
1117 { // Used with CMD mouse tracking.
1118 PWND pwnd
= ValidateHwnd(Wnd
);
1120 XOffset
= pwnd
->rcClient
.left
- pwnd
->rcWindow
.left
;
1121 YOffset
= pwnd
->rcClient
.top
- pwnd
->rcWindow
.top
;
1123 // WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL );
1124 ScreenToClient(Wnd
, &Pt
);
1125 // Pt.x -= rect.left;
1126 // Pt.y -= rect.top;
1131 IntScrollHandleScrollEvent(Wnd
, SBType
, WM_LBUTTONDOWN
, Pt
);
1135 if (!GetMessageW(&Msg
, 0, 0, 0)) break;
1136 if (CallMsgFilterW(&Msg
, MSGF_SCROLLBAR
)) continue;
1137 if ( Msg
.message
== WM_LBUTTONUP
||
1138 Msg
.message
== WM_MOUSEMOVE
||
1139 (Msg
.message
== WM_SYSTIMER
&& Msg
.wParam
== SCROLL_TIMER
))
1141 Pt
.x
= LOWORD(Msg
.lParam
) + XOffset
;
1142 Pt
.y
= HIWORD(Msg
.lParam
) + YOffset
;
1143 IntScrollHandleScrollEvent(Wnd
, SBType
, Msg
.message
, Pt
);
1147 TranslateMessage(&Msg
);
1148 DispatchMessageW(&Msg
);
1155 } while (Msg
.message
!= WM_LBUTTONUP
&& GetCapture() == Wnd
);
1159 static DWORD FASTCALL
1160 IntSetScrollInfo(HWND Wnd
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1162 DWORD Ret
= NtUserSetScrollInfo(Wnd
, SB_CTL
, Info
, bRedraw
);
1163 if (Ret
) IntNotifyWinEvent(EVENT_OBJECT_VALUECHANGE
, Wnd
, OBJID_CLIENT
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1168 /***********************************************************************
1172 ScrollBarWndProc_common(WNDPROC DefWindowProc
, HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL unicode
)
1174 #ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
1177 SCROLLINFO ScrollInfo
;
1179 pWnd
= ValidateHwnd(Wnd
);
1184 ERR("ScrollBar CTL size %d\n",(sizeof(SBWND
)-sizeof(WND
)));
1185 if ( pWnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
1187 ERR("Wrong Extra bytes for Scrollbar!\n");
1191 if (Msg
!= WM_CREATE
)
1193 return DefWindowProc(Wnd
, Msg
, wParam
, lParam
);
1195 NtUserSetWindowFNID(Wnd
, FNID_SCROLLBAR
);
1199 if (pWnd
->fnid
!= FNID_SCROLLBAR
)
1201 ERR("Wrong window class for Scrollbar!\n");
1208 if (! IsWindow(Wnd
))
1213 // Must be a scroll bar control!
1214 pSBWnd
= (PSBWND
)pWnd
;
1219 IntScrollCreateScrollBar(Wnd
, (LPCREATESTRUCTW
) lParam
);
1224 return SendMessageW( Wnd
, SBM_ENABLE_ARROWS
, wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
, 0);
1227 case WM_LBUTTONDBLCLK
:
1228 case WM_LBUTTONDOWN
:
1232 Pt
.x
= (short)LOWORD(lParam
);
1233 Pt
.y
= (short)HIWORD(lParam
);
1234 ScrollTrackScrollBar(Wnd
, SB_CTL
, Pt
);
1244 Pt
.x
= (short)LOWORD(lParam
);
1245 Pt
.y
= (short)HIWORD(lParam
);
1246 IntScrollHandleScrollEvent(Wnd
, SB_CTL
, Msg
, Pt
);
1251 IntScrollHandleKbdEvent(Wnd
, wParam
, lParam
);
1260 /* Create a caret when a ScrollBar get focus */
1262 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1264 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1265 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1268 CreateCaret(Wnd
, (HBITMAP
) 1, ThumbSize
- 2, Rect
.bottom
- Rect
.top
- 2);
1269 SetCaretPos(ThumbPos
+ 1, Rect
.top
+ 1);
1273 CreateCaret(Wnd
, (HBITMAP
) 1, Rect
.right
- Rect
.left
- 2, ThumbSize
- 2);
1274 SetCaretPos(Rect
.top
+ 1, ThumbPos
+ 1);
1283 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1285 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1286 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1289 Rect
.left
= ThumbPos
+ 1;
1290 Rect
.right
= Rect
.left
+ ThumbSize
;
1294 Rect
.top
= ThumbPos
+ 1;
1295 Rect
.bottom
= Rect
.top
+ ThumbSize
;
1298 InvalidateRect(Wnd
, &Rect
, FALSE
);
1307 return DLGC_WANTARROWS
; /* Windows returns this value */
1314 Dc
= (0 != wParam
? (HDC
) wParam
: BeginPaint(Wnd
, &Ps
));
1316 if (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1318 IntScrollDrawSizeGrip(Wnd
, Dc
);
1320 else if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEBOX
))
1323 GetClientRect(Wnd
, &Rect
);
1324 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
1328 IntDrawScrollBar(Wnd
, Dc
, SB_CTL
/*, TRUE, TRUE*/);
1339 return pSBWnd
->SBCalc
.pos
;
1342 *(LPINT
)wParam
= pSBWnd
->SBCalc
.posMin
;
1343 *(LPINT
)lParam
= pSBWnd
->SBCalc
.posMax
;
1344 // This message does not return a value.
1347 case SBM_ENABLE_ARROWS
:
1348 return EnableScrollBar( Wnd
, SB_CTL
, wParam
);
1352 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1353 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1354 ScrollInfo
.nPos
= wParam
;
1355 return IntSetScrollInfo(Wnd
, &ScrollInfo
, lParam
);
1358 case SBM_SETRANGEREDRAW
:
1361 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1362 ScrollInfo
.fMask
= SIF_RANGE
|SIF_PREVIOUSPOS
;
1363 ScrollInfo
.nMin
= wParam
;
1364 ScrollInfo
.nMax
= lParam
;
1365 return IntSetScrollInfo(Wnd
, &ScrollInfo
, Msg
== SBM_SETRANGEREDRAW
? TRUE
: FALSE
);
1368 case SBM_SETSCROLLINFO
:
1369 return IntSetScrollInfo(Wnd
, (LPCSCROLLINFO
)lParam
, wParam
);
1371 case SBM_GETSCROLLINFO
:
1373 PSBDATA pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
1374 DWORD ret
= NtUserSBGetParms(Wnd
, SB_CTL
, pSBData
, (SCROLLINFO
*) lParam
);
1377 ERR("SBM_GETSCROLLINFO No ScrollInfo\n");
1381 case SBM_GETSCROLLBARINFO
:
1382 ((PSCROLLBARINFO
)lParam
)->cbSize
= sizeof(SCROLLBARINFO
);
1383 return NtUserGetScrollBarInfo(Wnd
, OBJID_CLIENT
, (PSCROLLBARINFO
)lParam
);
1392 WARN("unknown Win32 msg %04x wp=%08lx lp=%08lx\n",
1393 Msg
, wParam
, lParam
);
1399 WARN("unknown msg %04x wp=%04lx lp=%08lx\n", Msg
, wParam
, lParam
);
1402 return DefWindowProcW( Wnd
, Msg
, wParam
, lParam
);
1404 return DefWindowProcA( Wnd
, Msg
, wParam
, lParam
);
1411 ScrollBarWndProcW(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1413 return ScrollBarWndProc_common(DefWindowProcW
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
1417 ScrollBarWndProcA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1419 return ScrollBarWndProc_common(DefWindowProcA
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
1423 /* PUBLIC FUNCTIONS ***********************************************************/
1428 BOOL WINAPI
EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
1430 BOOL Hook
, Ret
= FALSE
;
1434 Hook
= BeginIfHookedUserApiHook();
1436 /* Bypass SEH and go direct. */
1439 Ret
= NtUserEnableScrollBar(hwnd
, nBar
, flags
);
1440 if (!Ret
) return Ret
;
1441 SCROLL_RefreshScrollBar( hwnd
, nBar
, TRUE
, TRUE
);
1446 Ret
= guah
.EnableScrollBar(hwnd
, nBar
, flags
);
1448 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1459 RealGetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1464 if (SB_CTL
== SBType
)
1466 return SendMessageW(Wnd
, SBM_GETSCROLLINFO
, 0, (LPARAM
) Info
);
1469 pWnd
= ValidateHwnd(Wnd
);
1470 if (!pWnd
) return FALSE
;
1472 if (SBType
< SB_HORZ
|| SBType
> SB_VERT
)
1474 SetLastError(ERROR_INVALID_PARAMETER
);
1479 SetLastError(ERROR_NO_SCROLLBARS
);
1482 pSBData
= IntGetSBData(pWnd
, SBType
);
1483 return NtUserSBGetParms(Wnd
, SBType
, pSBData
, Info
);
1490 GetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1492 BOOL Hook
, Ret
= FALSE
;
1496 Hook
= BeginIfHookedUserApiHook();
1498 /* Bypass SEH and go direct. */
1499 if (!Hook
) return RealGetScrollInfo(Wnd
, SBType
, Info
);
1503 Ret
= guah
.GetScrollInfo(Wnd
, SBType
, Info
);
1505 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1519 GetScrollPos(HWND Wnd
, INT Bar
)
1524 TRACE("Wnd=%p Bar=%d\n", Wnd
, Bar
);
1526 /* Refer SB_CTL requests to the window */
1529 return SendMessageW(Wnd
, SBM_GETPOS
, (WPARAM
) 0, (LPARAM
) 0);
1531 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1533 pwnd
= ValidateHwnd(Wnd
);
1534 if (!pwnd
) return 0;
1538 pSBData
= IntGetSBData(pwnd
, Bar
);
1539 return pSBData
->pos
;
1542 SetLastError(ERROR_NO_SCROLLBARS
);
1543 ERR("GetScrollPos No Scroll Info\n");
1546 SetLastError(ERROR_INVALID_PARAMETER
);
1554 GetScrollRange(HWND Wnd
, int Bar
, LPINT MinPos
, LPINT MaxPos
)
1559 TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd
, Bar
, MinPos
, MaxPos
);
1561 /* Refer SB_CTL requests to the window */
1564 return SendMessageW(Wnd
, SBM_GETRANGE
, (WPARAM
) MinPos
, (LPARAM
) MaxPos
);
1566 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1568 pwnd
= ValidateHwnd(Wnd
);
1569 if (!pwnd
) return FALSE
;
1573 pSBData
= IntGetSBData(pwnd
, Bar
);
1574 *MinPos
= pSBData
->posMin
;
1575 *MaxPos
= pSBData
->posMax
;
1579 SetLastError(ERROR_NO_SCROLLBARS
);
1585 SetLastError(ERROR_INVALID_PARAMETER
);
1590 RealSetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1592 if (SB_CTL
== SBType
)
1594 return SendMessageW(Wnd
, SBM_SETSCROLLINFO
, (WPARAM
) bRedraw
, (LPARAM
) Info
);
1598 return NtUserSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1606 SetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1613 Hook
= BeginIfHookedUserApiHook();
1615 /* Bypass SEH and go direct. */
1616 if (!Hook
) return RealSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1620 Ret
= guah
.SetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1622 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1637 SetScrollPos(HWND hWnd
, INT nBar
, INT nPos
, BOOL bRedraw
)
1639 SCROLLINFO ScrollInfo
;
1641 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1642 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1643 ScrollInfo
.nPos
= nPos
;
1645 return RealSetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
);
1652 SetScrollRange(HWND hWnd
, INT nBar
, INT nMinPos
, INT nMaxPos
, BOOL bRedraw
)
1655 SCROLLINFO ScrollInfo
;
1657 pWnd
= ValidateHwnd(hWnd
);
1658 if ( !pWnd
) return FALSE
;
1660 if ((nMaxPos
- nMinPos
) > MAXLONG
)
1662 SetLastError(ERROR_INVALID_SCROLLBAR_RANGE
);
1666 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1667 ScrollInfo
.fMask
= SIF_RANGE
;
1668 ScrollInfo
.nMin
= nMinPos
;
1669 ScrollInfo
.nMax
= nMaxPos
;
1670 SetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
); // do not bypass themes.