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 /* Hit test code of the last button-down event */
67 static DWORD ScrollTrackHitTest
= SCROLL_NOWHERE
;
68 static BOOL ScrollTrackVertical
;
70 /* Is the moving thumb being displayed? */
71 static BOOL ScrollMovingThumb
= FALSE
;
73 HBRUSH
DefWndControlColor(HDC hDC
, UINT ctlType
);
75 UINT_PTR WINAPI
SetSystemTimer(HWND
,UINT_PTR
,UINT
,TIMERPROC
);
76 BOOL WINAPI
KillSystemTimer(HWND
,UINT_PTR
);
78 /*********************************************************************
79 * scrollbar class descriptor
81 const struct builtin_class_descr SCROLL_builtin_class
=
83 L
"ScrollBar", /* name */
84 CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
| CS_PARENTDC
, /* style */
85 ScrollBarWndProcA
, /* procA */
86 ScrollBarWndProcW
, /* procW */
87 sizeof(SBWND
)-sizeof(WND
), /* extra */
88 IDC_ARROW
, /* cursor */
92 /* PRIVATE FUNCTIONS **********************************************************/
95 IntGetSBData(PWND pwnd
, INT Bar
)
100 pSBInfo
= DesktopPtrToUser(pwnd
->pSBInfo
);
104 return &pSBInfo
->Horz
;
106 return &pSBInfo
->Vert
;
108 if ( pwnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
110 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
113 pSBWnd
= (PSBWND
)pwnd
;
114 return (PSBDATA
)&pSBWnd
->SBCalc
;
116 ERR("IntGetSBData Bad Bar!\n");
122 IntDrawScrollInterior(HWND hWnd
, HDC hDC
, INT nBar
, BOOL Vertical
,
123 PSCROLLBARINFO ScrollBarInfo
)
125 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
126 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
128 HBRUSH hSaveBrush
, hBrush
;
129 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
131 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
133 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
134 BottomSelected
= TRUE
;
137 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
138 * The window-owned scrollbars need to call DefWndControlColor
139 * to correctly setup default scrollbar colors
143 hBrush
= GetControlBrush( hWnd
, hDC
, WM_CTLCOLORSCROLLBAR
);
145 hBrush
= GetSysColorBrush(COLOR_SCROLLBAR
);
149 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
152 hSaveBrush
= SelectObject(hDC
, hBrush
);
154 /* Calculate the scroll rectangle */
157 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
158 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
159 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
160 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
164 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
165 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
166 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
167 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
170 /* Draw the scroll rectangles and thumb */
171 if (!ScrollBarInfo
->xyThumbBottom
)
173 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
174 Rect
.bottom
- Rect
.top
, PATCOPY
);
176 /* Cleanup and return */
177 SelectObject(hDC
, hSaveBrush
);
181 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
183 if (ScrollBarInfo
->dxyLineButton
)
189 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
190 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
191 Rect
.top
+= ThumbTop
;
192 PatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
193 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
194 Rect
.bottom
= Rect
.top
+ ThumbSize
;
200 PatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
201 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
209 PatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
210 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
211 Rect
.left
+= ThumbTop
;
212 PatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
213 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
214 BottomSelected
? BLACKNESS
: PATCOPY
);
215 Rect
.right
= Rect
.left
+ ThumbSize
;
221 PatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
222 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
230 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
233 SelectObject(hDC
, hSaveBrush
);
237 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
240 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
242 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
245 ScrollDirFlagLT
= DFCS_SCROLLUP
;
246 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
247 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
248 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
252 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
253 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
254 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
255 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
258 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
260 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
262 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
264 ScrollDirFlagLT
|= DFCS_INACTIVE
;
266 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
268 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
270 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
272 ScrollDirFlagRB
|= DFCS_INACTIVE
;
275 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
276 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
280 IntScrollDrawMovingThumb(HDC Dc
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
282 INT Pos
= ScrollTrackingPos
;
287 MaxSize
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->rcScrollBar
.top
;
289 MaxSize
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->rcScrollBar
.left
;
291 MaxSize
-= ScrollBarInfo
->dxyLineButton
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
293 if (Pos
< ScrollBarInfo
->dxyLineButton
)
294 Pos
= ScrollBarInfo
->dxyLineButton
;
295 else if (MaxSize
< Pos
)
298 OldTop
= ScrollBarInfo
->xyThumbTop
;
299 ScrollBarInfo
->xyThumbBottom
= Pos
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
300 ScrollBarInfo
->xyThumbTop
= Pos
;
301 IntDrawScrollInterior(ScrollTrackingWin
, Dc
, ScrollTrackingBar
, Vertical
, ScrollBarInfo
);
302 ScrollBarInfo
->xyThumbBottom
= OldTop
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
303 ScrollBarInfo
->xyThumbTop
= OldTop
;
305 ScrollMovingThumb
= !ScrollMovingThumb
;
309 IntScrollGetObjectId(INT SBType
)
311 if (SBType
== SB_VERT
)
312 return OBJID_VSCROLL
;
313 if (SBType
== SB_HORZ
)
314 return OBJID_HSCROLL
;
319 IntGetScrollBarInfo(HWND Wnd
, INT Bar
, PSCROLLBARINFO ScrollBarInfo
)
321 ScrollBarInfo
->cbSize
= sizeof(SCROLLBARINFO
);
323 return NtUserGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), ScrollBarInfo
);
327 IntDrawScrollBar(HWND Wnd
, HDC DC
, INT Bar
)
335 * Get scroll bar info.
348 Vertical
= (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) != 0;
354 if (!IntGetScrollBarInfo(Wnd
, Bar
, &Info
))
359 if (IsRectEmpty(&Info
.rcScrollBar
))
364 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
369 if (Info
.dxyLineButton
)
371 IntDrawScrollArrows(DC
, &Info
, Vertical
);
377 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
380 * If scroll bar has focus, reposition the caret.
382 if (Wnd
== GetFocus() && SB_CTL
== Bar
)
386 SetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
390 SetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
396 IntScrollPtInRectEx(LPRECT Rect
, POINT Pt
, BOOL Vertical
)
398 RECT TempRect
= *Rect
;
401 /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
402 * still be considered in the scrollbar. */
405 scrollbarWidth
= Rect
->right
- Rect
->left
;
406 TempRect
.left
-= scrollbarWidth
*8;
407 TempRect
.right
+= scrollbarWidth
*8;
408 TempRect
.top
-= scrollbarWidth
*2;
409 TempRect
.bottom
+= scrollbarWidth
*2;
413 scrollbarWidth
= Rect
->bottom
- Rect
->top
;
414 TempRect
.left
-= scrollbarWidth
*2;
415 TempRect
.right
+= scrollbarWidth
*2;
416 TempRect
.top
-= scrollbarWidth
*8;
417 TempRect
.bottom
+= scrollbarWidth
*8;
420 return PtInRect(&TempRect
, Pt
);
423 static DWORD FASTCALL
424 IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
, POINT Pt
, BOOL Dragging
)
426 INT ArrowSize
, ThumbSize
, ThumbPos
;
428 if ((Dragging
&& ! IntScrollPtInRectEx(&ScrollBarInfo
->rcScrollBar
, Pt
, Vertical
)) ||
429 ! PtInRect(&ScrollBarInfo
->rcScrollBar
, Pt
)) return SCROLL_NOWHERE
;
431 ThumbPos
= ScrollBarInfo
->xyThumbTop
;
432 ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ThumbPos
;
433 ArrowSize
= ScrollBarInfo
->dxyLineButton
;
437 if (Pt
.y
< ScrollBarInfo
->rcScrollBar
.top
+ ArrowSize
) return SCROLL_TOP_ARROW
;
438 if (Pt
.y
>= ScrollBarInfo
->rcScrollBar
.bottom
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
439 if (!ThumbPos
) return SCROLL_TOP_RECT
;
440 Pt
.y
-= ScrollBarInfo
->rcScrollBar
.top
;
441 if (Pt
.y
< ThumbPos
) return SCROLL_TOP_RECT
;
442 if (Pt
.y
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
446 if (Pt
.x
< ScrollBarInfo
->rcScrollBar
.left
+ ArrowSize
) return SCROLL_TOP_ARROW
;
447 if (Pt
.x
>= ScrollBarInfo
->rcScrollBar
.right
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
448 if (!ThumbPos
) return SCROLL_TOP_RECT
;
449 Pt
.x
-= ScrollBarInfo
->rcScrollBar
.left
;
450 if (Pt
.x
< ThumbPos
) return SCROLL_TOP_RECT
;
451 if (Pt
.x
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
458 /***********************************************************************
459 * IntScrollGetScrollBarRect
461 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
462 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
463 * 'arrowSize' returns the width or height of an arrow (depending on
464 * the orientation of the scrollbar), 'thumbSize' returns the size of
465 * the thumb, and 'thumbPos' returns the position of the thumb
466 * relative to the left or to the top.
467 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
470 IntScrollGetScrollBarRect(HWND Wnd
, INT Bar
, RECT
*Rect
,
471 INT
*ArrowSize
, INT
*ThumbSize
,
481 pWnd
= ValidateHwnd( Wnd
);
482 if (!pWnd
) return FALSE
;
483 pSBInfo
= DesktopPtrToUser(pWnd
->pSBInfo
);
485 *Rect
= pWnd
->rcClient
;
486 OffsetRect( Rect
, -pWnd
->rcWindow
.left
, -pWnd
->rcWindow
.top
);
487 if (pWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
488 mirror_rect( &pWnd
->rcWindow
, Rect
);
493 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
494 Rect
->top
= Rect
->bottom
;
495 Rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
496 if (pWnd
->style
& WS_BORDER
)
501 else if (pWnd
->style
& WS_VSCROLL
)
506 pSBData
= &pSBInfo
->Horz
;
510 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
511 if (pWnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
)
513 Rect
->right
= Rect
->left
;
514 Rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
518 Rect
->left
= Rect
->right
;
519 Rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
521 if (pWnd
->style
& WS_BORDER
)
526 else if (pWnd
->style
& WS_HSCROLL
)
531 pSBData
= &pSBInfo
->Vert
;
535 GetClientRect( Wnd
, Rect
);
536 Vertical
= (pWnd
->style
& SBS_VERT
);
537 pSBWnd
= (PSBWND
)pWnd
;
538 pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
545 if (Vertical
) Pixels
= Rect
->bottom
- Rect
->top
;
546 else Pixels
= Rect
->right
- Rect
->left
;
548 if (Pixels
<= 2 * GetSystemMetrics(SM_CXVSCROLL
) + SCROLL_MIN_RECT
)
550 if (SCROLL_MIN_RECT
< Pixels
)
551 *ArrowSize
= (Pixels
- SCROLL_MIN_RECT
) / 2;
554 *ThumbPos
= *ThumbSize
= 0;
558 *ArrowSize
= GetSystemMetrics(SM_CXVSCROLL
);
559 Pixels
-= (2 * (GetSystemMetrics(SM_CXVSCROLL
) - SCROLL_ARROW_THUMB_OVERLAP
));
562 *ThumbSize
= MulDiv(Pixels
, pSBData
->page
, (pSBData
->posMax
- pSBData
->posMin
+ 1));
563 if (*ThumbSize
< SCROLL_MIN_THUMB
) *ThumbSize
= SCROLL_MIN_THUMB
;
565 else *ThumbSize
= GetSystemMetrics(SM_CXVSCROLL
);
567 if (((Pixels
-= *ThumbSize
) < 0) ||
568 (( pSBInfo
->WSBflags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
))
570 /* Rectangle too small or scrollbar disabled -> no thumb */
571 *ThumbPos
= *ThumbSize
= 0;
575 INT Max
= pSBData
->posMax
- max(pSBData
->page
- 1, 0);
576 if (pSBData
->posMin
>= Max
)
577 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
;
579 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
580 + MulDiv(Pixels
, (pSBData
->pos
- pSBData
->posMin
),(Max
- pSBData
->posMin
));
586 /***********************************************************************
587 * IntScrollGetThumbVal
589 * Compute the current scroll position based on the thumb position in pixels
590 * from the top of the scroll-bar.
593 IntScrollGetThumbVal(HWND Wnd
, INT SBType
, PSCROLLBARINFO ScrollBarInfo
,
594 BOOL Vertical
, INT Pos
)
598 INT Pixels
= Vertical
? ScrollBarInfo
->rcScrollBar
.bottom
599 - ScrollBarInfo
->rcScrollBar
.top
600 : ScrollBarInfo
->rcScrollBar
.right
601 - ScrollBarInfo
->rcScrollBar
.left
;
603 pWnd
= ValidateHwnd( Wnd
);
604 if (!pWnd
) return FALSE
;
606 pSBData
= IntGetSBData(pWnd
, SBType
);
608 if ((Pixels
-= 2 * ScrollBarInfo
->dxyLineButton
) <= 0)
610 return pSBData
->posMin
;
613 if ((Pixels
-= (ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
)) <= 0)
615 return pSBData
->posMin
;
618 Pos
= Pos
- ScrollBarInfo
->dxyLineButton
;
623 if (Pos
> Pixels
) Pos
= Pixels
;
626 Pos
*= pSBData
->posMax
- pSBData
->posMin
;
628 Pos
*= pSBData
->posMax
- pSBData
->posMin
- pSBData
->page
+ 1;
630 return pSBData
->posMin
+ ((Pos
+ Pixels
/ 2) / Pixels
);
633 /***********************************************************************
636 static POINT
IntScrollClipPos(PRECT lpRect
, POINT pt
)
638 if( pt
.x
< lpRect
->left
)
641 if( pt
.x
> lpRect
->right
)
642 pt
.x
= lpRect
->right
;
644 if( pt
.y
< lpRect
->top
)
647 if( pt
.y
> lpRect
->bottom
)
648 pt
.y
= lpRect
->bottom
;
653 /***********************************************************************
654 * IntScrollDrawSizeGrip
656 * Draw the size grip.
659 IntScrollDrawSizeGrip(HWND Wnd
, HDC Dc
)
663 GetClientRect(Wnd
, &Rect
);
664 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
665 Rect
.left
= max(Rect
.left
, Rect
.right
- GetSystemMetrics(SM_CXVSCROLL
) - 1);
666 Rect
.top
= max(Rect
.top
, Rect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) - 1);
667 DrawFrameControl(Dc
, &Rect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
670 /***********************************************************************
671 * SCROLL_RefreshScrollBar
673 * Repaint the scroll bar interior after a SetScrollRange() or
674 * SetScrollPos() call.
676 static void SCROLL_RefreshScrollBar( HWND hwnd
, INT nBar
,
677 BOOL arrows
, BOOL interior
)
679 HDC hdc
= GetDCEx( hwnd
, 0,
680 DCX_CACHE
| ((nBar
== SB_CTL
) ? 0 : DCX_WINDOW
) );
683 IntDrawScrollBar( hwnd
, hdc
, nBar
);//, arrows, interior );
684 ReleaseDC( hwnd
, hdc
);
688 /***********************************************************************
689 * IntScrollHandleKbdEvent
691 * Handle a keyboard event (only for SB_CTL scrollbars with focus).
694 IntScrollHandleKbdEvent(
695 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
696 WPARAM wParam
/* [in] Variable input including enable state */,
697 LPARAM lParam
/* [in] Variable input including input point */)
699 TRACE("Wnd=%p wParam=%ld lParam=%ld\n", Wnd
, wParam
, lParam
);
701 /* hide caret on first KEYDOWN to prevent flicker */
702 if (0 == (lParam
& PFD_DOUBLEBUFFER_DONTCARE
))
714 wParam
= SB_PAGEDOWN
;
730 wParam
= SB_LINEDOWN
;
737 SendMessageW(GetParent(Wnd
),
738 (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) ?
739 WM_VSCROLL
: WM_HSCROLL
), wParam
, (LPARAM
) Wnd
);
742 /***********************************************************************
743 * IntScrollHandleScrollEvent
745 * Handle a mouse or timer event for the scrollbar.
746 * 'Pt' is the location of the mouse event in drawing coordinates
749 IntScrollHandleScrollEvent(HWND Wnd
, INT SBType
, UINT Msg
, POINT Pt
)
751 static POINT PrevPt
; /* Previous mouse position for timer events */
752 static UINT TrackThumbPos
; /* Thumb position when tracking started. */
753 static INT LastClickPos
; /* Position in the scroll-bar of the last
754 button-down event. */
755 static INT LastMousePos
; /* Position in the scroll-bar of the last
759 HWND WndOwner
, WndCtl
;
762 SCROLLBARINFO ScrollBarInfo
;
763 SETSCROLLBARINFO NewInfo
;
765 if (! IntGetScrollBarInfo(Wnd
, SBType
, &ScrollBarInfo
))
769 if ((ScrollTrackHitTest
== SCROLL_NOWHERE
) && (Msg
!= WM_LBUTTONDOWN
))
771 //// ReactOS : Justin Case something goes wrong.
772 if (Wnd
== GetCapture())
780 NewInfo
.nTrackPos
= ScrollTrackingVal
;
781 NewInfo
.reserved
= ScrollBarInfo
.reserved
;
782 memcpy(NewInfo
.rgstate
, ScrollBarInfo
.rgstate
, (CCHILDREN_SCROLLBAR
+ 1) * sizeof(DWORD
));
784 if (SBType
== SB_CTL
&& (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
788 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
789 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
792 ScrollTrackHitTest
= HitTest
= SCROLL_THUMB
;
795 GetClientRect(GetParent(GetParent(Wnd
)), &ScrollBarInfo
.rcScrollBar
);
800 ScrollTrackHitTest
= HitTest
= SCROLL_NOWHERE
;
801 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
810 Dc
= GetDCEx(Wnd
, 0, DCX_CACHE
| ((SB_CTL
== SBType
) ? 0 : DCX_WINDOW
));
811 if (SB_VERT
== SBType
)
815 else if (SB_HORZ
== SBType
)
821 Vertical
= (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
));
823 WndOwner
= (SB_CTL
== SBType
) ? GetParent(Wnd
) : Wnd
;
824 WndCtl
= (SB_CTL
== SBType
) ? Wnd
: NULL
;
828 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
829 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
830 ScrollTrackVertical
= Vertical
;
831 ScrollTrackHitTest
= HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
832 LastClickPos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
833 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
834 LastMousePos
= LastClickPos
;
835 TrackThumbPos
= ScrollBarInfo
.xyThumbTop
;
837 if (SBType
== SB_CTL
&& (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_TABSTOP
)) SetFocus(Wnd
);
839 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] |= STATE_SYSTEM_PRESSED
;
840 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
841 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
845 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, TRUE
);
850 HitTest
= SCROLL_NOWHERE
;
852 /* if scrollbar has focus, show back caret */
853 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
854 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] &= ~STATE_SYSTEM_PRESSED
;
855 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
856 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
858 IntDrawScrollArrows(Dc
, &ScrollBarInfo
, Vertical
);
864 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
868 return; /* Should never happen */
871 TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
872 Wnd
, SBType
, SPY_GetMsgName(Msg
,Wnd
), Pt
.x
, Pt
.y
, HitTest
);
874 switch (ScrollTrackHitTest
)
876 case SCROLL_NOWHERE
: /* No tracking in progress */
879 case SCROLL_TOP_ARROW
:
880 if (HitTest
== ScrollTrackHitTest
)
882 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
884 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
885 SB_LINEUP
, (LPARAM
) WndCtl
);
887 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
888 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
893 KillSystemTimer(Wnd
, SCROLL_TIMER
);
897 case SCROLL_TOP_RECT
:
898 if (HitTest
== ScrollTrackHitTest
)
900 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
902 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
903 SB_PAGEUP
, (LPARAM
) WndCtl
);
905 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
906 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
911 KillSystemTimer(Wnd
, SCROLL_TIMER
);
916 if (Msg
== WM_LBUTTONDOWN
)
918 ScrollTrackingWin
= Wnd
;
919 ScrollTrackingBar
= SBType
;
920 ScrollTrackingPos
= TrackThumbPos
+ LastMousePos
- LastClickPos
;
921 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
922 Vertical
, ScrollTrackingPos
);
923 NewInfo
.nTrackPos
= ScrollTrackingVal
;
924 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
925 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
927 else if (Msg
== WM_LBUTTONUP
)
929 ScrollTrackingWin
= 0;
930 ScrollTrackingVal
= 0;
931 IntDrawScrollInterior(Wnd
, Dc
, SBType
, Vertical
, &ScrollBarInfo
);
933 else /* WM_MOUSEMOVE */
937 if (! IntScrollPtInRectEx(&ScrollBarInfo
.rcScrollBar
, Pt
, Vertical
))
943 Pt
= IntScrollClipPos(&ScrollBarInfo
.rcScrollBar
, Pt
);
944 Pos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
945 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
947 if (Pos
!= LastMousePos
|| ! ScrollMovingThumb
)
950 ScrollTrackingPos
= TrackThumbPos
+ Pos
- LastClickPos
;
951 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
952 Vertical
, ScrollTrackingPos
);
953 NewInfo
.nTrackPos
= ScrollTrackingVal
;
954 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
955 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
956 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
957 MAKEWPARAM(SB_THUMBTRACK
, ScrollTrackingVal
),
963 case SCROLL_BOTTOM_RECT
:
964 if (HitTest
== ScrollTrackHitTest
)
966 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
968 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
969 SB_PAGEDOWN
, (LPARAM
) WndCtl
);
971 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
972 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
977 KillSystemTimer(Wnd
, SCROLL_TIMER
);
981 case SCROLL_BOTTOM_ARROW
:
982 if (HitTest
== ScrollTrackHitTest
)
984 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
986 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
987 SB_LINEDOWN
, (LPARAM
) WndCtl
);
989 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
990 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
993 else KillSystemTimer(Wnd
, SCROLL_TIMER
);
997 if (Msg
== WM_LBUTTONDOWN
)
999 if (SCROLL_THUMB
== HitTest
)
1001 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1002 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1003 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1004 MAKEWPARAM(SB_THUMBTRACK
, Val
), (LPARAM
) WndCtl
);
1008 if (Msg
== WM_LBUTTONUP
)
1010 HitTest
= ScrollTrackHitTest
;
1011 ScrollTrackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
1013 if (SCROLL_THUMB
== HitTest
)
1015 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1016 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1017 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1018 MAKEWPARAM(SB_THUMBPOSITION
, Val
), (LPARAM
) WndCtl
);
1020 /* SB_ENDSCROLL doesn't report thumb position */
1021 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1022 SB_ENDSCROLL
, (LPARAM
) WndCtl
);
1024 /* Terminate tracking */
1025 ScrollTrackingWin
= 0;
1032 /***********************************************************************
1033 * IntScrollCreateScrollBar
1035 * Create a scroll bar
1037 static void IntScrollCreateScrollBar(
1038 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
1039 LPCREATESTRUCTW lpCreate
/* [in] The style and place of the scroll bar */)
1043 Info
.cbSize
= sizeof(SCROLLINFO
);
1044 Info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
1050 NtUserSetScrollInfo(Wnd
, SB_CTL
, &Info
, FALSE
);
1052 TRACE("hwnd=%p lpCreate=%p\n", Wnd
, lpCreate
);
1055 if (lpCreate
->style
& WS_DISABLED
)
1057 // info->flags = ESB_DISABLE_BOTH;
1058 //NtUserEnableScrollBar(Wnd,SB_CTL,(wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH));
1059 NtUserMessageCall( Wnd
, WM_ENABLE
, FALSE
, 0, 0, FNID_SCROLLBAR
, FALSE
);
1060 ERR("Created WS_DISABLED scrollbar\n");
1063 if (0 != (lpCreate
->style
& (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
1065 if (0 != (lpCreate
->style
& SBS_SIZEBOXTOPLEFTALIGN
))
1067 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
, GetSystemMetrics(SM_CXVSCROLL
) + 1,
1068 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1070 else if (0 != (lpCreate
->style
& SBS_SIZEBOXBOTTOMRIGHTALIGN
))
1072 MoveWindow(Wnd
, lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1073 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1074 GetSystemMetrics(SM_CXVSCROLL
) + 1,
1075 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1078 else if (0 != (lpCreate
->style
& SBS_VERT
))
1080 if (0 != (lpCreate
->style
& SBS_LEFTALIGN
))
1082 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1083 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1085 else if (0 != (lpCreate
->style
& SBS_RIGHTALIGN
))
1088 lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1090 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1095 if (0 != (lpCreate
->style
& SBS_TOPALIGN
))
1097 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1098 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1100 else if (0 != (lpCreate
->style
& SBS_BOTTOMALIGN
))
1104 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1105 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1110 /* USER32 INTERNAL FUNCTIONS **************************************************/
1112 /***********************************************************************
1113 * ScrollTrackScrollBar
1115 * Track a mouse button press on a scroll-bar.
1116 * pt is in screen-coordinates for non-client scroll bars.
1119 ScrollTrackScrollBar(HWND Wnd
, INT SBType
, POINT Pt
)
1122 UINT XOffset
= 0, YOffset
= 0;
1124 if (SBType
!= SB_CTL
)
1125 { // Used with CMD mouse tracking.
1126 PWND pwnd
= ValidateHwnd(Wnd
);
1128 XOffset
= pwnd
->rcClient
.left
- pwnd
->rcWindow
.left
;
1129 YOffset
= pwnd
->rcClient
.top
- pwnd
->rcWindow
.top
;
1131 // WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL );
1132 ScreenToClient(Wnd
, &Pt
);
1133 // Pt.x -= rect.left;
1134 // Pt.y -= rect.top;
1139 IntScrollHandleScrollEvent(Wnd
, SBType
, WM_LBUTTONDOWN
, Pt
);
1143 if (!GetMessageW(&Msg
, 0, 0, 0)) break;
1144 if (CallMsgFilterW(&Msg
, MSGF_SCROLLBAR
)) continue;
1145 if ( Msg
.message
== WM_LBUTTONUP
||
1146 Msg
.message
== WM_MOUSEMOVE
||
1147 (Msg
.message
== WM_SYSTIMER
&& Msg
.wParam
== SCROLL_TIMER
))
1149 Pt
.x
= LOWORD(Msg
.lParam
) + XOffset
;
1150 Pt
.y
= HIWORD(Msg
.lParam
) + YOffset
;
1151 IntScrollHandleScrollEvent(Wnd
, SBType
, Msg
.message
, Pt
);
1155 TranslateMessage(&Msg
);
1156 DispatchMessageW(&Msg
);
1163 } while (Msg
.message
!= WM_LBUTTONUP
&& GetCapture() == Wnd
);
1167 static DWORD FASTCALL
1168 IntSetScrollInfo(HWND Wnd
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1170 DWORD Ret
= NtUserSetScrollInfo(Wnd
, SB_CTL
, Info
, bRedraw
);
1171 if (Ret
) IntNotifyWinEvent(EVENT_OBJECT_VALUECHANGE
, Wnd
, OBJID_CLIENT
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1176 /***********************************************************************
1180 ScrollBarWndProc_common(WNDPROC DefWindowProc
, HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL unicode
)
1182 #ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
1185 SCROLLINFO ScrollInfo
;
1187 pWnd
= ValidateHwnd(Wnd
);
1192 ERR("ScrollBar CTL size %d\n",(sizeof(SBWND
)-sizeof(WND
)));
1193 if ( pWnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
1195 ERR("Wrong Extra bytes for Scrollbar!\n");
1199 if (Msg
!= WM_CREATE
)
1201 return DefWindowProc(Wnd
, Msg
, wParam
, lParam
);
1203 NtUserSetWindowFNID(Wnd
, FNID_SCROLLBAR
);
1207 if (pWnd
->fnid
!= FNID_SCROLLBAR
)
1209 ERR("Wrong window class for Scrollbar!\n");
1216 if (! IsWindow(Wnd
))
1221 // Must be a scroll bar control!
1222 pSBWnd
= (PSBWND
)pWnd
;
1227 IntScrollCreateScrollBar(Wnd
, (LPCREATESTRUCTW
) lParam
);
1232 return SendMessageW( Wnd
, SBM_ENABLE_ARROWS
, wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
, 0);
1235 case WM_LBUTTONDBLCLK
:
1236 case WM_LBUTTONDOWN
:
1237 if (GetWindowLongW( Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1239 SendMessageW( GetParent(Wnd
), WM_SYSCOMMAND
,
1240 SC_SIZE
+ ((GetWindowLongW( Wnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
) ?
1241 WMSZ_BOTTOMLEFT
: WMSZ_BOTTOMRIGHT
), lParam
);
1246 Pt
.x
= (short)LOWORD(lParam
);
1247 Pt
.y
= (short)HIWORD(lParam
);
1248 ScrollTrackScrollBar(Wnd
, SB_CTL
, Pt
);
1257 Pt
.x
= (short)LOWORD(lParam
);
1258 Pt
.y
= (short)HIWORD(lParam
);
1259 IntScrollHandleScrollEvent(Wnd
, SB_CTL
, Msg
, Pt
);
1264 IntScrollHandleKbdEvent(Wnd
, wParam
, lParam
);
1273 /* Create a caret when a ScrollBar get focus */
1275 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1277 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1278 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1281 CreateCaret(Wnd
, (HBITMAP
) 1, ThumbSize
- 2, Rect
.bottom
- Rect
.top
- 2);
1282 SetCaretPos(ThumbPos
+ 1, Rect
.top
+ 1);
1286 CreateCaret(Wnd
, (HBITMAP
) 1, Rect
.right
- Rect
.left
- 2, ThumbSize
- 2);
1287 SetCaretPos(Rect
.top
+ 1, ThumbPos
+ 1);
1296 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1298 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1299 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1302 Rect
.left
= ThumbPos
+ 1;
1303 Rect
.right
= Rect
.left
+ ThumbSize
;
1307 Rect
.top
= ThumbPos
+ 1;
1308 Rect
.bottom
= Rect
.top
+ ThumbSize
;
1311 InvalidateRect(Wnd
, &Rect
, FALSE
);
1320 return DLGC_WANTARROWS
; /* Windows returns this value */
1327 Dc
= (0 != wParam
? (HDC
) wParam
: BeginPaint(Wnd
, &Ps
));
1329 if (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1331 IntScrollDrawSizeGrip(Wnd
, Dc
);
1333 else if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEBOX
))
1336 GetClientRect(Wnd
, &Rect
);
1337 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
1341 IntDrawScrollBar(Wnd
, Dc
, SB_CTL
/*, TRUE, TRUE*/);
1352 return pSBWnd
->SBCalc
.pos
;
1355 *(LPINT
)wParam
= pSBWnd
->SBCalc
.posMin
;
1356 *(LPINT
)lParam
= pSBWnd
->SBCalc
.posMax
;
1357 // This message does not return a value.
1360 case SBM_ENABLE_ARROWS
:
1361 return EnableScrollBar( Wnd
, SB_CTL
, wParam
);
1365 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1366 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1367 ScrollInfo
.nPos
= wParam
;
1368 return IntSetScrollInfo(Wnd
, &ScrollInfo
, lParam
);
1371 case SBM_SETRANGEREDRAW
:
1374 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1375 ScrollInfo
.fMask
= SIF_RANGE
|SIF_PREVIOUSPOS
;
1376 ScrollInfo
.nMin
= wParam
;
1377 ScrollInfo
.nMax
= lParam
;
1378 return IntSetScrollInfo(Wnd
, &ScrollInfo
, Msg
== SBM_SETRANGEREDRAW
? TRUE
: FALSE
);
1381 case SBM_SETSCROLLINFO
:
1382 return IntSetScrollInfo(Wnd
, (LPCSCROLLINFO
)lParam
, wParam
);
1384 case SBM_GETSCROLLINFO
:
1386 PSBDATA pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
1387 DWORD ret
= NtUserSBGetParms(Wnd
, SB_CTL
, pSBData
, (SCROLLINFO
*) lParam
);
1390 ERR("SBM_GETSCROLLINFO No ScrollInfo\n");
1394 case SBM_GETSCROLLBARINFO
:
1395 ((PSCROLLBARINFO
)lParam
)->cbSize
= sizeof(SCROLLBARINFO
);
1396 return NtUserGetScrollBarInfo(Wnd
, OBJID_CLIENT
, (PSCROLLBARINFO
)lParam
);
1405 WARN("unknown Win32 msg %04x wp=%08lx lp=%08lx\n",
1406 Msg
, wParam
, lParam
);
1412 WARN("unknown msg %04x wp=%04lx lp=%08lx\n", Msg
, wParam
, lParam
);
1415 return DefWindowProcW( Wnd
, Msg
, wParam
, lParam
);
1417 return DefWindowProcA( Wnd
, Msg
, wParam
, lParam
);
1424 ScrollBarWndProcW(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1426 return ScrollBarWndProc_common(DefWindowProcW
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
1430 ScrollBarWndProcA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1432 return ScrollBarWndProc_common(DefWindowProcA
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
1436 /* PUBLIC FUNCTIONS ***********************************************************/
1444 EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
1446 BOOL Hook
, Ret
= FALSE
;
1450 Hook
= BeginIfHookedUserApiHook();
1452 /* Bypass SEH and go direct. */
1455 Ret
= NtUserEnableScrollBar(hwnd
, nBar
, flags
);
1456 if (!Ret
) return Ret
;
1457 SCROLL_RefreshScrollBar( hwnd
, nBar
, TRUE
, TRUE
);
1462 Ret
= guah
.EnableScrollBar(hwnd
, nBar
, flags
);
1464 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1475 RealGetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1480 if (SB_CTL
== SBType
)
1482 return SendMessageW(Wnd
, SBM_GETSCROLLINFO
, 0, (LPARAM
) Info
);
1485 pWnd
= ValidateHwnd(Wnd
);
1486 if (!pWnd
) return FALSE
;
1488 if (SBType
< SB_HORZ
|| SBType
> SB_VERT
)
1490 SetLastError(ERROR_INVALID_PARAMETER
);
1495 SetLastError(ERROR_NO_SCROLLBARS
);
1498 pSBData
= IntGetSBData(pWnd
, SBType
);
1499 return NtUserSBGetParms(Wnd
, SBType
, pSBData
, Info
);
1508 GetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1510 BOOL Hook
, Ret
= FALSE
;
1514 Hook
= BeginIfHookedUserApiHook();
1516 /* Bypass SEH and go direct. */
1517 if (!Hook
) return RealGetScrollInfo(Wnd
, SBType
, Info
);
1521 Ret
= guah
.GetScrollInfo(Wnd
, SBType
, Info
);
1523 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1539 GetScrollPos(HWND Wnd
, INT Bar
)
1544 TRACE("Wnd=%p Bar=%d\n", Wnd
, Bar
);
1546 /* Refer SB_CTL requests to the window */
1549 return SendMessageW(Wnd
, SBM_GETPOS
, (WPARAM
) 0, (LPARAM
) 0);
1551 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1553 pwnd
= ValidateHwnd(Wnd
);
1554 if (!pwnd
) return 0;
1558 pSBData
= IntGetSBData(pwnd
, Bar
);
1559 return pSBData
->pos
;
1562 SetLastError(ERROR_NO_SCROLLBARS
);
1563 TRACE("GetScrollPos No Scroll Info\n");
1566 SetLastError(ERROR_INVALID_PARAMETER
);
1576 GetScrollRange(HWND Wnd
, int Bar
, LPINT MinPos
, LPINT MaxPos
)
1581 TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd
, Bar
, MinPos
, MaxPos
);
1583 /* Refer SB_CTL requests to the window */
1586 return SendMessageW(Wnd
, SBM_GETRANGE
, (WPARAM
) MinPos
, (LPARAM
) MaxPos
);
1588 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1590 pwnd
= ValidateHwnd(Wnd
);
1591 if (!pwnd
) return FALSE
;
1595 pSBData
= IntGetSBData(pwnd
, Bar
);
1596 *MinPos
= pSBData
->posMin
;
1597 *MaxPos
= pSBData
->posMax
;
1601 SetLastError(ERROR_NO_SCROLLBARS
);
1607 SetLastError(ERROR_INVALID_PARAMETER
);
1612 RealSetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1614 if (SB_CTL
== SBType
)
1616 return SendMessageW(Wnd
, SBM_SETSCROLLINFO
, (WPARAM
) bRedraw
, (LPARAM
) Info
);
1620 return NtUserSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1630 SetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1637 Hook
= BeginIfHookedUserApiHook();
1639 /* Bypass SEH and go direct. */
1640 if (!Hook
) return RealSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1644 Ret
= guah
.SetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1663 SetScrollPos(HWND hWnd
, INT nBar
, INT nPos
, BOOL bRedraw
)
1665 SCROLLINFO ScrollInfo
;
1667 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1668 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1669 ScrollInfo
.nPos
= nPos
;
1671 return RealSetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
);
1680 SetScrollRange(HWND hWnd
, INT nBar
, INT nMinPos
, INT nMaxPos
, BOOL bRedraw
)
1683 SCROLLINFO ScrollInfo
;
1685 pWnd
= ValidateHwnd(hWnd
);
1686 if ( !pWnd
) return FALSE
;
1688 if ((nMaxPos
- nMinPos
) > MAXLONG
)
1690 SetLastError(ERROR_INVALID_SCROLLBAR_RANGE
);
1694 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1695 ScrollInfo
.fMask
= SIF_RANGE
;
1696 ScrollInfo
.nMin
= nMinPos
;
1697 ScrollInfo
.nMax
= nMaxPos
;
1698 SetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
); // do not bypass themes.