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
31 WINE_DEFAULT_DEBUG_CHANNEL(scrollbar
);
33 /* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
34 #define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
35 #define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
36 #define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
37 #define SCROLL_THUMB 0x03 /* Thumb rectangle */
38 #define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
39 #define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
41 #define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
42 holding the button down */
43 #define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
45 #define SCROLL_TIMER 0 /* Scroll timer id */
47 /* Minimum size of the rectangle between the arrows */
48 #define SCROLL_MIN_RECT 4
50 /* Minimum size of the thumb in pixels */
51 #define SCROLL_MIN_THUMB 6
53 /* Overlap between arrows and thumb */
54 #define SCROLL_ARROW_THUMB_OVERLAP 0
56 /* Thumb-tracking info */
57 static HWND ScrollTrackingWin
= 0;
58 static INT ScrollTrackingBar
= 0;
59 static INT ScrollTrackingPos
= 0;
60 static INT ScrollTrackingVal
= 0;
61 /* Hit test code of the last button-down event */
62 static DWORD ScrollTrackHitTest
= SCROLL_NOWHERE
;
63 static BOOL ScrollTrackVertical
;
65 /* Is the moving thumb being displayed? */
66 static BOOL ScrollMovingThumb
= FALSE
;
68 HBRUSH
DefWndControlColor(HDC hDC
, UINT ctlType
);
70 UINT_PTR WINAPI
SetSystemTimer(HWND
,UINT_PTR
,UINT
,TIMERPROC
);
71 BOOL WINAPI
KillSystemTimer(HWND
,UINT_PTR
);
73 /*********************************************************************
74 * scrollbar class descriptor
76 const struct builtin_class_descr SCROLL_builtin_class
=
78 L
"ScrollBar", /* name */
79 CS_DBLCLKS
| CS_VREDRAW
| CS_HREDRAW
| CS_PARENTDC
, /* style */
80 ScrollBarWndProcA
, /* procA */
81 ScrollBarWndProcW
, /* procW */
82 sizeof(SBWND
)-sizeof(WND
), /* extra */
83 IDC_ARROW
, /* cursor */
87 /* PRIVATE FUNCTIONS **********************************************************/
90 IntGetSBData(PWND pwnd
, INT Bar
)
95 pSBInfo
= DesktopPtrToUser(pwnd
->pSBInfo
);
99 return &pSBInfo
->Horz
;
101 return &pSBInfo
->Vert
;
103 if ( pwnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
105 ERR("IntGetSBData Wrong Extra bytes for CTL Scrollbar!\n");
108 pSBWnd
= (PSBWND
)pwnd
;
109 return (PSBDATA
)&pSBWnd
->SBCalc
;
111 ERR("IntGetSBData Bad Bar!\n");
117 IntDrawScrollInterior(HWND hWnd
, HDC hDC
, INT nBar
, BOOL Vertical
,
118 PSCROLLBARINFO ScrollBarInfo
)
120 INT ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
121 INT ThumbTop
= ScrollBarInfo
->xyThumbTop
;
123 HBRUSH hSaveBrush
, hBrush
;
124 BOOL TopSelected
= FALSE
, BottomSelected
= FALSE
;
126 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_RECT
] & STATE_SYSTEM_PRESSED
)
128 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_RECT
] & STATE_SYSTEM_PRESSED
)
129 BottomSelected
= TRUE
;
132 * Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
133 * The window-owned scrollbars need to call DefWndControlColor
134 * to correctly setup default scrollbar colors
138 hBrush
= GetControlBrush( hWnd
, hDC
, WM_CTLCOLORSCROLLBAR
);
140 hBrush
= GetSysColorBrush(COLOR_SCROLLBAR
);
144 hBrush
= DefWndControlColor(hDC
, CTLCOLOR_SCROLLBAR
);
147 hSaveBrush
= SelectObject(hDC
, hBrush
);
149 /* Calculate the scroll rectangle */
152 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
+ ScrollBarInfo
->dxyLineButton
;
153 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->dxyLineButton
;
154 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
;
155 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
;
159 Rect
.top
= ScrollBarInfo
->rcScrollBar
.top
;
160 Rect
.bottom
= ScrollBarInfo
->rcScrollBar
.bottom
;
161 Rect
.left
= ScrollBarInfo
->rcScrollBar
.left
+ ScrollBarInfo
->dxyLineButton
;
162 Rect
.right
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->dxyLineButton
;
165 /* Draw the scroll rectangles and thumb */
166 if (!ScrollBarInfo
->xyThumbBottom
)
168 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
169 Rect
.bottom
- Rect
.top
, PATCOPY
);
171 /* Cleanup and return */
172 SelectObject(hDC
, hSaveBrush
);
176 ThumbTop
-= ScrollBarInfo
->dxyLineButton
;
178 if (ScrollBarInfo
->dxyLineButton
)
184 PatBlt(hDC
, Rect
.left
, Rect
.top
, Rect
.right
- Rect
.left
,
185 ThumbTop
, TopSelected
? BLACKNESS
: PATCOPY
);
186 Rect
.top
+= ThumbTop
;
187 PatBlt(hDC
, Rect
.left
, Rect
.top
+ ThumbSize
, Rect
.right
- Rect
.left
,
188 Rect
.bottom
- Rect
.top
- ThumbSize
, BottomSelected
? BLACKNESS
: PATCOPY
);
189 Rect
.bottom
= Rect
.top
+ ThumbSize
;
195 PatBlt(hDC
, Rect
.left
, ScrollBarInfo
->dxyLineButton
,
196 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
204 PatBlt(hDC
, Rect
.left
, Rect
.top
, ThumbTop
,
205 Rect
.bottom
- Rect
.top
, TopSelected
? BLACKNESS
: PATCOPY
);
206 Rect
.left
+= ThumbTop
;
207 PatBlt(hDC
, Rect
.left
+ ThumbSize
, Rect
.top
,
208 Rect
.right
- Rect
.left
- ThumbSize
, Rect
.bottom
- Rect
.top
,
209 BottomSelected
? BLACKNESS
: PATCOPY
);
210 Rect
.right
= Rect
.left
+ ThumbSize
;
216 PatBlt(hDC
, ScrollBarInfo
->dxyLineButton
, Rect
.top
,
217 Rect
.right
- Rect
.left
, Rect
.bottom
- Rect
.top
, PATCOPY
);
225 DrawEdge(hDC
, &Rect
, EDGE_RAISED
, BF_RECT
| BF_MIDDLE
);
228 SelectObject(hDC
, hSaveBrush
);
232 IntDrawScrollArrows(HDC hDC
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
235 INT ScrollDirFlagLT
, ScrollDirFlagRB
;
237 RectLT
= RectRB
= ScrollBarInfo
->rcScrollBar
;
240 ScrollDirFlagLT
= DFCS_SCROLLUP
;
241 ScrollDirFlagRB
= DFCS_SCROLLDOWN
;
242 RectLT
.bottom
= RectLT
.top
+ ScrollBarInfo
->dxyLineButton
;
243 RectRB
.top
= RectRB
.bottom
- ScrollBarInfo
->dxyLineButton
;
247 ScrollDirFlagLT
= DFCS_SCROLLLEFT
;
248 ScrollDirFlagRB
= DFCS_SCROLLRIGHT
;
249 RectLT
.right
= RectLT
.left
+ ScrollBarInfo
->dxyLineButton
;
250 RectRB
.left
= RectRB
.right
- ScrollBarInfo
->dxyLineButton
;
253 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_PRESSED
)
255 ScrollDirFlagLT
|= DFCS_PUSHED
| DFCS_FLAT
;
257 if (ScrollBarInfo
->rgstate
[SCROLL_TOP_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
259 ScrollDirFlagLT
|= DFCS_INACTIVE
;
261 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_PRESSED
)
263 ScrollDirFlagRB
|= DFCS_PUSHED
| DFCS_FLAT
;
265 if (ScrollBarInfo
->rgstate
[SCROLL_BOTTOM_ARROW
] & STATE_SYSTEM_UNAVAILABLE
)
267 ScrollDirFlagRB
|= DFCS_INACTIVE
;
270 DrawFrameControl(hDC
, &RectLT
, DFC_SCROLL
, ScrollDirFlagLT
);
271 DrawFrameControl(hDC
, &RectRB
, DFC_SCROLL
, ScrollDirFlagRB
);
275 IntScrollDrawMovingThumb(HDC Dc
, PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
)
277 INT Pos
= ScrollTrackingPos
;
282 MaxSize
= ScrollBarInfo
->rcScrollBar
.bottom
- ScrollBarInfo
->rcScrollBar
.top
;
284 MaxSize
= ScrollBarInfo
->rcScrollBar
.right
- ScrollBarInfo
->rcScrollBar
.left
;
286 MaxSize
-= ScrollBarInfo
->dxyLineButton
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
288 if (Pos
< ScrollBarInfo
->dxyLineButton
)
289 Pos
= ScrollBarInfo
->dxyLineButton
;
290 else if (MaxSize
< Pos
)
293 OldTop
= ScrollBarInfo
->xyThumbTop
;
294 ScrollBarInfo
->xyThumbBottom
= Pos
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
295 ScrollBarInfo
->xyThumbTop
= Pos
;
296 IntDrawScrollInterior(ScrollTrackingWin
, Dc
, ScrollTrackingBar
, Vertical
, ScrollBarInfo
);
297 ScrollBarInfo
->xyThumbBottom
= OldTop
+ ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
;
298 ScrollBarInfo
->xyThumbTop
= OldTop
;
300 ScrollMovingThumb
= !ScrollMovingThumb
;
304 IntScrollGetObjectId(INT SBType
)
306 if (SBType
== SB_VERT
)
307 return OBJID_VSCROLL
;
308 if (SBType
== SB_HORZ
)
309 return OBJID_HSCROLL
;
314 IntGetScrollBarInfo(HWND Wnd
, INT Bar
, PSCROLLBARINFO ScrollBarInfo
)
316 ScrollBarInfo
->cbSize
= sizeof(SCROLLBARINFO
);
318 return NtUserGetScrollBarInfo(Wnd
, IntScrollGetObjectId(Bar
), ScrollBarInfo
);
322 IntDrawScrollBar(HWND Wnd
, HDC DC
, INT Bar
)
330 * Get scroll bar info.
343 Vertical
= (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) != 0;
349 if (!IntGetScrollBarInfo(Wnd
, Bar
, &Info
))
354 if (IsRectEmpty(&Info
.rcScrollBar
))
359 //ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
364 if (Info
.dxyLineButton
)
366 IntDrawScrollArrows(DC
, &Info
, Vertical
);
372 IntDrawScrollInterior(Wnd
, DC
, Bar
, Vertical
, &Info
);
375 * If scroll bar has focus, reposition the caret.
377 if (Wnd
== GetFocus() && SB_CTL
== Bar
)
381 SetCaretPos(Info
.rcScrollBar
.top
+ 1, Info
.dxyLineButton
+ 1);
385 SetCaretPos(Info
.dxyLineButton
+ 1, Info
.rcScrollBar
.top
+ 1);
391 IntScrollPtInRectEx(LPRECT Rect
, POINT Pt
, BOOL Vertical
)
393 RECT TempRect
= *Rect
;
396 /* Pad hit rect to allow mouse to be dragged outside of scrollbar and
397 * still be considered in the scrollbar. */
400 scrollbarWidth
= Rect
->right
- Rect
->left
;
401 TempRect
.left
-= scrollbarWidth
*8;
402 TempRect
.right
+= scrollbarWidth
*8;
403 TempRect
.top
-= scrollbarWidth
*2;
404 TempRect
.bottom
+= scrollbarWidth
*2;
408 scrollbarWidth
= Rect
->bottom
- Rect
->top
;
409 TempRect
.left
-= scrollbarWidth
*2;
410 TempRect
.right
+= scrollbarWidth
*2;
411 TempRect
.top
-= scrollbarWidth
*8;
412 TempRect
.bottom
+= scrollbarWidth
*8;
415 return PtInRect(&TempRect
, Pt
);
418 static DWORD FASTCALL
419 IntScrollHitTest(PSCROLLBARINFO ScrollBarInfo
, BOOL Vertical
, POINT Pt
, BOOL Dragging
)
421 INT ArrowSize
, ThumbSize
, ThumbPos
;
423 if ((Dragging
&& ! IntScrollPtInRectEx(&ScrollBarInfo
->rcScrollBar
, Pt
, Vertical
)) ||
424 ! PtInRect(&ScrollBarInfo
->rcScrollBar
, Pt
)) return SCROLL_NOWHERE
;
426 ThumbPos
= ScrollBarInfo
->xyThumbTop
;
427 ThumbSize
= ScrollBarInfo
->xyThumbBottom
- ThumbPos
;
428 ArrowSize
= ScrollBarInfo
->dxyLineButton
;
432 if (Pt
.y
< ScrollBarInfo
->rcScrollBar
.top
+ ArrowSize
) return SCROLL_TOP_ARROW
;
433 if (Pt
.y
>= ScrollBarInfo
->rcScrollBar
.bottom
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
434 if (!ThumbPos
) return SCROLL_TOP_RECT
;
435 Pt
.y
-= ScrollBarInfo
->rcScrollBar
.top
;
436 if (Pt
.y
< ThumbPos
) return SCROLL_TOP_RECT
;
437 if (Pt
.y
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
441 if (Pt
.x
< ScrollBarInfo
->rcScrollBar
.left
+ ArrowSize
) return SCROLL_TOP_ARROW
;
442 if (Pt
.x
>= ScrollBarInfo
->rcScrollBar
.right
- ArrowSize
) return SCROLL_BOTTOM_ARROW
;
443 if (!ThumbPos
) return SCROLL_TOP_RECT
;
444 Pt
.x
-= ScrollBarInfo
->rcScrollBar
.left
;
445 if (Pt
.x
< ThumbPos
) return SCROLL_TOP_RECT
;
446 if (Pt
.x
>= ThumbPos
+ ThumbSize
) return SCROLL_BOTTOM_RECT
;
453 /***********************************************************************
454 * IntScrollGetScrollBarRect
456 * Compute the scroll bar rectangle, in drawing coordinates (i.e. client
457 * coords for SB_CTL, window coords for SB_VERT and SB_HORZ).
458 * 'arrowSize' returns the width or height of an arrow (depending on
459 * the orientation of the scrollbar), 'thumbSize' returns the size of
460 * the thumb, and 'thumbPos' returns the position of the thumb
461 * relative to the left or to the top.
462 * Return TRUE if the scrollbar is vertical, FALSE if horizontal.
465 IntScrollGetScrollBarRect(HWND Wnd
, INT Bar
, RECT
*Rect
,
466 INT
*ArrowSize
, INT
*ThumbSize
,
476 pWnd
= ValidateHwnd( Wnd
);
477 if (!pWnd
) return FALSE
;
478 pSBInfo
= DesktopPtrToUser(pWnd
->pSBInfo
);
480 *Rect
= pWnd
->rcClient
;
481 OffsetRect( Rect
, -pWnd
->rcWindow
.left
, -pWnd
->rcWindow
.top
);
482 if (pWnd
->ExStyle
& WS_EX_LAYOUTRTL
)
483 mirror_rect( &pWnd
->rcWindow
, Rect
);
488 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
489 Rect
->top
= Rect
->bottom
;
490 Rect
->bottom
+= GetSystemMetrics(SM_CYHSCROLL
);
491 if (pWnd
->style
& WS_BORDER
)
496 else if (pWnd
->style
& WS_VSCROLL
)
501 pSBData
= &pSBInfo
->Horz
;
505 // WIN_GetRectangles( Wnd, COORDS_WINDOW, NULL, Rect );
506 if (pWnd
->ExStyle
& WS_EX_LEFTSCROLLBAR
)
508 Rect
->right
= Rect
->left
;
509 Rect
->left
-= GetSystemMetrics(SM_CXVSCROLL
);
513 Rect
->left
= Rect
->right
;
514 Rect
->right
+= GetSystemMetrics(SM_CXVSCROLL
);
516 if (pWnd
->style
& WS_BORDER
)
521 else if (pWnd
->style
& WS_HSCROLL
)
526 pSBData
= &pSBInfo
->Vert
;
530 GetClientRect( Wnd
, Rect
);
531 Vertical
= (pWnd
->style
& SBS_VERT
);
532 pSBWnd
= (PSBWND
)pWnd
;
533 pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
540 if (Vertical
) Pixels
= Rect
->bottom
- Rect
->top
;
541 else Pixels
= Rect
->right
- Rect
->left
;
543 if (Pixels
<= 2 * GetSystemMetrics(SM_CXVSCROLL
) + SCROLL_MIN_RECT
)
545 if (SCROLL_MIN_RECT
< Pixels
)
546 *ArrowSize
= (Pixels
- SCROLL_MIN_RECT
) / 2;
549 *ThumbPos
= *ThumbSize
= 0;
553 *ArrowSize
= GetSystemMetrics(SM_CXVSCROLL
);
554 Pixels
-= (2 * (GetSystemMetrics(SM_CXVSCROLL
) - SCROLL_ARROW_THUMB_OVERLAP
));
557 *ThumbSize
= MulDiv(Pixels
, pSBData
->page
, (pSBData
->posMax
- pSBData
->posMin
+ 1));
558 if (*ThumbSize
< SCROLL_MIN_THUMB
) *ThumbSize
= SCROLL_MIN_THUMB
;
560 else *ThumbSize
= GetSystemMetrics(SM_CXVSCROLL
);
562 if (((Pixels
-= *ThumbSize
) < 0) ||
563 (( pSBInfo
->WSBflags
& ESB_DISABLE_BOTH
) == ESB_DISABLE_BOTH
))
565 /* Rectangle too small or scrollbar disabled -> no thumb */
566 *ThumbPos
= *ThumbSize
= 0;
570 INT Max
= pSBData
->posMax
- max(pSBData
->page
- 1, 0);
571 if (pSBData
->posMin
>= Max
)
572 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
;
574 *ThumbPos
= *ArrowSize
- SCROLL_ARROW_THUMB_OVERLAP
575 + MulDiv(Pixels
, (pSBData
->pos
- pSBData
->posMin
),(Max
- pSBData
->posMin
));
581 /***********************************************************************
582 * IntScrollGetThumbVal
584 * Compute the current scroll position based on the thumb position in pixels
585 * from the top of the scroll-bar.
588 IntScrollGetThumbVal(HWND Wnd
, INT SBType
, PSCROLLBARINFO ScrollBarInfo
,
589 BOOL Vertical
, INT Pos
)
593 INT Pixels
= Vertical
? ScrollBarInfo
->rcScrollBar
.bottom
594 - ScrollBarInfo
->rcScrollBar
.top
595 : ScrollBarInfo
->rcScrollBar
.right
596 - ScrollBarInfo
->rcScrollBar
.left
;
598 pWnd
= ValidateHwnd( Wnd
);
599 if (!pWnd
) return FALSE
;
601 pSBData
= IntGetSBData(pWnd
, SBType
);
603 if ((Pixels
-= 2 * ScrollBarInfo
->dxyLineButton
) <= 0)
605 return pSBData
->posMin
;
608 if ((Pixels
-= (ScrollBarInfo
->xyThumbBottom
- ScrollBarInfo
->xyThumbTop
)) <= 0)
610 return pSBData
->posMin
;
613 Pos
= Pos
- ScrollBarInfo
->dxyLineButton
;
618 if (Pos
> Pixels
) Pos
= Pixels
;
621 Pos
*= pSBData
->posMax
- pSBData
->posMin
;
623 Pos
*= pSBData
->posMax
- pSBData
->posMin
- pSBData
->page
+ 1;
625 return pSBData
->posMin
+ ((Pos
+ Pixels
/ 2) / Pixels
);
628 /***********************************************************************
631 static POINT
IntScrollClipPos(PRECT lpRect
, POINT pt
)
633 if( pt
.x
< lpRect
->left
)
636 if( pt
.x
> lpRect
->right
)
637 pt
.x
= lpRect
->right
;
639 if( pt
.y
< lpRect
->top
)
642 if( pt
.y
> lpRect
->bottom
)
643 pt
.y
= lpRect
->bottom
;
648 /***********************************************************************
649 * IntScrollDrawSizeGrip
651 * Draw the size grip.
654 IntScrollDrawSizeGrip(HWND Wnd
, HDC Dc
)
658 GetClientRect(Wnd
, &Rect
);
659 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
660 Rect
.left
= max(Rect
.left
, Rect
.right
- GetSystemMetrics(SM_CXVSCROLL
) - 1);
661 Rect
.top
= max(Rect
.top
, Rect
.bottom
- GetSystemMetrics(SM_CYHSCROLL
) - 1);
662 DrawFrameControl(Dc
, &Rect
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
665 /***********************************************************************
666 * SCROLL_RefreshScrollBar
668 * Repaint the scroll bar interior after a SetScrollRange() or
669 * SetScrollPos() call.
671 static void SCROLL_RefreshScrollBar( HWND hwnd
, INT nBar
,
672 BOOL arrows
, BOOL interior
)
674 HDC hdc
= GetDCEx( hwnd
, 0,
675 DCX_CACHE
| ((nBar
== SB_CTL
) ? 0 : DCX_WINDOW
) );
678 IntDrawScrollBar( hwnd
, hdc
, nBar
);//, arrows, interior );
679 ReleaseDC( hwnd
, hdc
);
683 /***********************************************************************
684 * IntScrollHandleKbdEvent
686 * Handle a keyboard event (only for SB_CTL scrollbars with focus).
689 IntScrollHandleKbdEvent(
690 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
691 WPARAM wParam
/* [in] Variable input including enable state */,
692 LPARAM lParam
/* [in] Variable input including input point */)
694 TRACE("Wnd=%p wParam=%ld lParam=%ld\n", Wnd
, wParam
, lParam
);
696 /* hide caret on first KEYDOWN to prevent flicker */
697 if (0 == (lParam
& PFD_DOUBLEBUFFER_DONTCARE
))
709 wParam
= SB_PAGEDOWN
;
725 wParam
= SB_LINEDOWN
;
732 SendMessageW(GetParent(Wnd
),
733 (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
) ?
734 WM_VSCROLL
: WM_HSCROLL
), wParam
, (LPARAM
) Wnd
);
737 /***********************************************************************
738 * IntScrollHandleScrollEvent
740 * Handle a mouse or timer event for the scrollbar.
741 * 'Pt' is the location of the mouse event in drawing coordinates
744 IntScrollHandleScrollEvent(HWND Wnd
, INT SBType
, UINT Msg
, POINT Pt
)
746 static POINT PrevPt
; /* Previous mouse position for timer events */
747 static UINT TrackThumbPos
; /* Thumb position when tracking started. */
748 static INT LastClickPos
; /* Position in the scroll-bar of the last
749 button-down event. */
750 static INT LastMousePos
; /* Position in the scroll-bar of the last
754 HWND WndOwner
, WndCtl
;
757 SCROLLBARINFO ScrollBarInfo
;
758 SETSCROLLBARINFO NewInfo
;
760 if (! IntGetScrollBarInfo(Wnd
, SBType
, &ScrollBarInfo
))
764 if ((ScrollTrackHitTest
== SCROLL_NOWHERE
) && (Msg
!= WM_LBUTTONDOWN
))
766 //// ReactOS : Justin Case something goes wrong.
767 if (Wnd
== GetCapture())
775 NewInfo
.nTrackPos
= ScrollTrackingVal
;
776 NewInfo
.reserved
= ScrollBarInfo
.reserved
;
777 memcpy(NewInfo
.rgstate
, ScrollBarInfo
.rgstate
, (CCHILDREN_SCROLLBAR
+ 1) * sizeof(DWORD
));
779 if (SBType
== SB_CTL
&& (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
783 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
784 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
787 ScrollTrackHitTest
= HitTest
= SCROLL_THUMB
;
790 GetClientRect(GetParent(GetParent(Wnd
)), &ScrollBarInfo
.rcScrollBar
);
795 ScrollTrackHitTest
= HitTest
= SCROLL_NOWHERE
;
796 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
805 Dc
= GetDCEx(Wnd
, 0, DCX_CACHE
| ((SB_CTL
== SBType
) ? 0 : DCX_WINDOW
));
806 if (SB_VERT
== SBType
)
810 else if (SB_HORZ
== SBType
)
816 Vertical
= (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_VERT
));
818 WndOwner
= (SB_CTL
== SBType
) ? GetParent(Wnd
) : Wnd
;
819 WndCtl
= (SB_CTL
== SBType
) ? Wnd
: NULL
;
823 case WM_LBUTTONDOWN
: /* Initialise mouse tracking */
824 HideCaret(Wnd
); /* hide caret while holding down LBUTTON */
825 ScrollTrackVertical
= Vertical
;
826 ScrollTrackHitTest
= HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
827 LastClickPos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
828 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
829 LastMousePos
= LastClickPos
;
830 TrackThumbPos
= ScrollBarInfo
.xyThumbTop
;
832 if (SBType
== SB_CTL
&& (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & WS_TABSTOP
)) SetFocus(Wnd
);
834 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] |= STATE_SYSTEM_PRESSED
;
835 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
836 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
840 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, TRUE
);
845 HitTest
= SCROLL_NOWHERE
;
847 /* if scrollbar has focus, show back caret */
848 if (Wnd
== GetFocus()) ShowCaret(Wnd
);
849 ScrollBarInfo
.rgstate
[ScrollTrackHitTest
] &= ~STATE_SYSTEM_PRESSED
;
850 NewInfo
.rgstate
[ScrollTrackHitTest
] = ScrollBarInfo
.rgstate
[ScrollTrackHitTest
];
851 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
853 IntDrawScrollInterior(Wnd
,Dc
,SBType
,Vertical
,&ScrollBarInfo
);
854 IntDrawScrollArrows(Dc
, &ScrollBarInfo
, Vertical
);
860 HitTest
= IntScrollHitTest(&ScrollBarInfo
, Vertical
, Pt
, FALSE
);
864 return; /* Should never happen */
867 TRACE("Event: hwnd=%p bar=%d msg=%s pt=%d,%d hit=%d\n",
868 Wnd
, SBType
, SPY_GetMsgName(Msg
,Wnd
), Pt
.x
, Pt
.y
, HitTest
);
870 switch (ScrollTrackHitTest
)
872 case SCROLL_NOWHERE
: /* No tracking in progress */
875 case SCROLL_TOP_ARROW
:
876 if (HitTest
== ScrollTrackHitTest
)
878 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
880 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
881 SB_LINEUP
, (LPARAM
) WndCtl
);
883 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
884 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
889 KillSystemTimer(Wnd
, SCROLL_TIMER
);
893 case SCROLL_TOP_RECT
:
894 if (HitTest
== ScrollTrackHitTest
)
896 if ((WM_LBUTTONDOWN
== Msg
) || (WM_SYSTIMER
== Msg
))
898 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
899 SB_PAGEUP
, (LPARAM
) WndCtl
);
901 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
902 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
907 KillSystemTimer(Wnd
, SCROLL_TIMER
);
912 if (Msg
== WM_LBUTTONDOWN
)
914 ScrollTrackingWin
= Wnd
;
915 ScrollTrackingBar
= SBType
;
916 ScrollTrackingPos
= TrackThumbPos
+ LastMousePos
- LastClickPos
;
917 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
918 Vertical
, ScrollTrackingPos
);
919 NewInfo
.nTrackPos
= ScrollTrackingVal
;
920 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
921 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
923 else if (Msg
== WM_LBUTTONUP
)
925 ScrollTrackingWin
= 0;
926 ScrollTrackingVal
= 0;
927 IntDrawScrollInterior(Wnd
, Dc
, SBType
, Vertical
, &ScrollBarInfo
);
929 else /* WM_MOUSEMOVE */
933 if (! IntScrollPtInRectEx(&ScrollBarInfo
.rcScrollBar
, Pt
, Vertical
))
939 Pt
= IntScrollClipPos(&ScrollBarInfo
.rcScrollBar
, Pt
);
940 Pos
= Vertical
? (Pt
.y
- ScrollBarInfo
.rcScrollBar
.top
)
941 : (Pt
.x
- ScrollBarInfo
.rcScrollBar
.left
);
943 if (Pos
!= LastMousePos
|| ! ScrollMovingThumb
)
946 ScrollTrackingPos
= TrackThumbPos
+ Pos
- LastClickPos
;
947 ScrollTrackingVal
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
,
948 Vertical
, ScrollTrackingPos
);
949 NewInfo
.nTrackPos
= ScrollTrackingVal
;
950 NtUserSetScrollBarInfo(Wnd
, IntScrollGetObjectId(SBType
), &NewInfo
);
951 IntScrollDrawMovingThumb(Dc
, &ScrollBarInfo
, Vertical
);
952 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
953 MAKEWPARAM(SB_THUMBTRACK
, ScrollTrackingVal
),
959 case SCROLL_BOTTOM_RECT
:
960 if (HitTest
== ScrollTrackHitTest
)
962 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
964 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
965 SB_PAGEDOWN
, (LPARAM
) WndCtl
);
967 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
968 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
973 KillSystemTimer(Wnd
, SCROLL_TIMER
);
977 case SCROLL_BOTTOM_ARROW
:
978 if (HitTest
== ScrollTrackHitTest
)
980 if ((Msg
== WM_LBUTTONDOWN
) || (Msg
== WM_SYSTIMER
))
982 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
983 SB_LINEDOWN
, (LPARAM
) WndCtl
);
985 SetSystemTimer(Wnd
, SCROLL_TIMER
, (WM_LBUTTONDOWN
== Msg
) ?
986 SCROLL_FIRST_DELAY
: SCROLL_REPEAT_DELAY
,
989 else KillSystemTimer(Wnd
, SCROLL_TIMER
);
993 if (Msg
== WM_LBUTTONDOWN
)
995 if (SCROLL_THUMB
== HitTest
)
997 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
998 TrackThumbPos
+ LastMousePos
- LastClickPos
);
999 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1000 MAKEWPARAM(SB_THUMBTRACK
, Val
), (LPARAM
) WndCtl
);
1004 if (Msg
== WM_LBUTTONUP
)
1006 HitTest
= ScrollTrackHitTest
;
1007 ScrollTrackHitTest
= SCROLL_NOWHERE
; /* Terminate tracking */
1009 if (SCROLL_THUMB
== HitTest
)
1011 UINT Val
= IntScrollGetThumbVal(Wnd
, SBType
, &ScrollBarInfo
, Vertical
,
1012 TrackThumbPos
+ LastMousePos
- LastClickPos
);
1013 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1014 MAKEWPARAM(SB_THUMBPOSITION
, Val
), (LPARAM
) WndCtl
);
1016 /* SB_ENDSCROLL doesn't report thumb position */
1017 SendMessageW(WndOwner
, Vertical
? WM_VSCROLL
: WM_HSCROLL
,
1018 SB_ENDSCROLL
, (LPARAM
) WndCtl
);
1020 /* Terminate tracking */
1021 ScrollTrackingWin
= 0;
1028 /***********************************************************************
1029 * IntScrollCreateScrollBar
1031 * Create a scroll bar
1033 static void IntScrollCreateScrollBar(
1034 HWND Wnd
/* [in] Handle of window with scrollbar(s) */,
1035 LPCREATESTRUCTW lpCreate
/* [in] The style and place of the scroll bar */)
1039 Info
.cbSize
= sizeof(SCROLLINFO
);
1040 Info
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
1046 NtUserSetScrollInfo(Wnd
, SB_CTL
, &Info
, FALSE
);
1048 TRACE("hwnd=%p lpCreate=%p\n", Wnd
, lpCreate
);
1051 if (lpCreate
->style
& WS_DISABLED
)
1053 // info->flags = ESB_DISABLE_BOTH;
1054 //NtUserEnableScrollBar(Wnd,SB_CTL,(wParam ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH));
1055 NtUserMessageCall( Wnd
, WM_ENABLE
, FALSE
, 0, 0, FNID_SCROLLBAR
, FALSE
);
1056 ERR("Created WS_DISABLED scrollbar\n");
1059 if (0 != (lpCreate
->style
& (SBS_SIZEGRIP
| SBS_SIZEBOX
)))
1061 if (0 != (lpCreate
->style
& SBS_SIZEBOXTOPLEFTALIGN
))
1063 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
, GetSystemMetrics(SM_CXVSCROLL
) + 1,
1064 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1066 else if (0 != (lpCreate
->style
& SBS_SIZEBOXBOTTOMRIGHTALIGN
))
1068 MoveWindow(Wnd
, lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1069 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1070 GetSystemMetrics(SM_CXVSCROLL
) + 1,
1071 GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1074 else if (0 != (lpCreate
->style
& SBS_VERT
))
1076 if (0 != (lpCreate
->style
& SBS_LEFTALIGN
))
1078 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1079 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1081 else if (0 != (lpCreate
->style
& SBS_RIGHTALIGN
))
1084 lpCreate
->x
+ lpCreate
->cx
- GetSystemMetrics(SM_CXVSCROLL
) - 1,
1086 GetSystemMetrics(SM_CXVSCROLL
) + 1, lpCreate
->cy
, FALSE
);
1091 if (0 != (lpCreate
->style
& SBS_TOPALIGN
))
1093 MoveWindow(Wnd
, lpCreate
->x
, lpCreate
->y
,
1094 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1096 else if (0 != (lpCreate
->style
& SBS_BOTTOMALIGN
))
1100 lpCreate
->y
+ lpCreate
->cy
- GetSystemMetrics(SM_CYHSCROLL
) - 1,
1101 lpCreate
->cx
, GetSystemMetrics(SM_CYHSCROLL
) + 1, FALSE
);
1106 /* USER32 INTERNAL FUNCTIONS **************************************************/
1108 /***********************************************************************
1109 * ScrollTrackScrollBar
1111 * Track a mouse button press on a scroll-bar.
1112 * pt is in screen-coordinates for non-client scroll bars.
1115 ScrollTrackScrollBar(HWND Wnd
, INT SBType
, POINT Pt
)
1118 UINT XOffset
= 0, YOffset
= 0;
1120 if (SBType
!= SB_CTL
)
1121 { // Used with CMD mouse tracking.
1122 PWND pwnd
= ValidateHwnd(Wnd
);
1124 XOffset
= pwnd
->rcClient
.left
- pwnd
->rcWindow
.left
;
1125 YOffset
= pwnd
->rcClient
.top
- pwnd
->rcWindow
.top
;
1127 // WIN_GetRectangles( Wnd, COORDS_CLIENT, &rect, NULL );
1128 ScreenToClient(Wnd
, &Pt
);
1129 // Pt.x -= rect.left;
1130 // Pt.y -= rect.top;
1135 IntScrollHandleScrollEvent(Wnd
, SBType
, WM_LBUTTONDOWN
, Pt
);
1139 if (!GetMessageW(&Msg
, 0, 0, 0)) break;
1140 if (CallMsgFilterW(&Msg
, MSGF_SCROLLBAR
)) continue;
1141 if ( Msg
.message
== WM_LBUTTONUP
||
1142 Msg
.message
== WM_MOUSEMOVE
||
1143 (Msg
.message
== WM_SYSTIMER
&& Msg
.wParam
== SCROLL_TIMER
))
1145 Pt
.x
= LOWORD(Msg
.lParam
) + XOffset
;
1146 Pt
.y
= HIWORD(Msg
.lParam
) + YOffset
;
1147 IntScrollHandleScrollEvent(Wnd
, SBType
, Msg
.message
, Pt
);
1151 TranslateMessage(&Msg
);
1152 DispatchMessageW(&Msg
);
1159 } while (Msg
.message
!= WM_LBUTTONUP
&& GetCapture() == Wnd
);
1163 static DWORD FASTCALL
1164 IntSetScrollInfo(HWND Wnd
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1166 DWORD Ret
= NtUserSetScrollInfo(Wnd
, SB_CTL
, Info
, bRedraw
);
1167 if (Ret
) IntNotifyWinEvent(EVENT_OBJECT_VALUECHANGE
, Wnd
, OBJID_CLIENT
, CHILDID_SELF
, WEF_SETBYWNDPTI
);
1172 /***********************************************************************
1176 ScrollBarWndProc_common(WNDPROC DefWindowProc
, HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, BOOL unicode
)
1178 #ifdef __REACTOS__ // Do this now, remove after Server side is fixed.
1181 SCROLLINFO ScrollInfo
;
1183 pWnd
= ValidateHwnd(Wnd
);
1188 TRACE("ScrollBar CTL size %d\n", (sizeof(SBWND
)-sizeof(WND
)));
1189 if ( pWnd
->cbwndExtra
!= (sizeof(SBWND
)-sizeof(WND
)) )
1191 ERR("Wrong Extra bytes for Scrollbar!\n");
1195 if (Msg
!= WM_CREATE
)
1197 return DefWindowProc(Wnd
, Msg
, wParam
, lParam
);
1199 NtUserSetWindowFNID(Wnd
, FNID_SCROLLBAR
);
1203 if (pWnd
->fnid
!= FNID_SCROLLBAR
)
1205 ERR("Wrong window class for Scrollbar!\n");
1212 if (! IsWindow(Wnd
))
1217 // Must be a scroll bar control!
1218 pSBWnd
= (PSBWND
)pWnd
;
1223 IntScrollCreateScrollBar(Wnd
, (LPCREATESTRUCTW
) lParam
);
1228 return SendMessageW( Wnd
, SBM_ENABLE_ARROWS
, wParam
? ESB_ENABLE_BOTH
: ESB_DISABLE_BOTH
, 0);
1231 case WM_LBUTTONDBLCLK
:
1232 case WM_LBUTTONDOWN
:
1233 if (GetWindowLongW( Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1235 SendMessageW( GetParent(Wnd
), WM_SYSCOMMAND
,
1236 SC_SIZE
+ ((GetWindowLongW( Wnd
, GWL_EXSTYLE
) & WS_EX_LAYOUTRTL
) ?
1237 WMSZ_BOTTOMLEFT
: WMSZ_BOTTOMRIGHT
), lParam
);
1242 Pt
.x
= (short)LOWORD(lParam
);
1243 Pt
.y
= (short)HIWORD(lParam
);
1244 ScrollTrackScrollBar(Wnd
, SB_CTL
, Pt
);
1253 Pt
.x
= (short)LOWORD(lParam
);
1254 Pt
.y
= (short)HIWORD(lParam
);
1255 IntScrollHandleScrollEvent(Wnd
, SB_CTL
, Msg
, Pt
);
1260 IntScrollHandleKbdEvent(Wnd
, wParam
, lParam
);
1269 /* Create a caret when a ScrollBar get focus */
1271 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1273 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1274 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1277 CreateCaret(Wnd
, (HBITMAP
) 1, ThumbSize
- 2, Rect
.bottom
- Rect
.top
- 2);
1278 SetCaretPos(ThumbPos
+ 1, Rect
.top
+ 1);
1282 CreateCaret(Wnd
, (HBITMAP
) 1, Rect
.right
- Rect
.left
- 2, ThumbSize
- 2);
1283 SetCaretPos(Rect
.top
+ 1, ThumbPos
+ 1);
1292 int ArrowSize
, ThumbSize
, ThumbPos
, Vertical
;
1294 Vertical
= IntScrollGetScrollBarRect(Wnd
, SB_CTL
, &Rect
,
1295 &ArrowSize
, &ThumbSize
, &ThumbPos
);
1298 Rect
.left
= ThumbPos
+ 1;
1299 Rect
.right
= Rect
.left
+ ThumbSize
;
1303 Rect
.top
= ThumbPos
+ 1;
1304 Rect
.bottom
= Rect
.top
+ ThumbSize
;
1307 InvalidateRect(Wnd
, &Rect
, FALSE
);
1316 return DLGC_WANTARROWS
; /* Windows returns this value */
1323 Dc
= (0 != wParam
? (HDC
) wParam
: BeginPaint(Wnd
, &Ps
));
1325 if (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEGRIP
)
1327 IntScrollDrawSizeGrip(Wnd
, Dc
);
1329 else if (0 != (GetWindowLongPtrW(Wnd
, GWL_STYLE
) & SBS_SIZEBOX
))
1332 GetClientRect(Wnd
, &Rect
);
1333 FillRect(Dc
, &Rect
, GetSysColorBrush(COLOR_SCROLLBAR
));
1337 IntDrawScrollBar(Wnd
, Dc
, SB_CTL
/*, TRUE, TRUE*/);
1348 return pSBWnd
->SBCalc
.pos
;
1351 *(LPINT
)wParam
= pSBWnd
->SBCalc
.posMin
;
1352 *(LPINT
)lParam
= pSBWnd
->SBCalc
.posMax
;
1353 // This message does not return a value.
1356 case SBM_ENABLE_ARROWS
:
1357 return EnableScrollBar( Wnd
, SB_CTL
, wParam
);
1361 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1362 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1363 ScrollInfo
.nPos
= wParam
;
1364 return IntSetScrollInfo(Wnd
, &ScrollInfo
, lParam
);
1367 case SBM_SETRANGEREDRAW
:
1370 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1371 ScrollInfo
.fMask
= SIF_RANGE
|SIF_PREVIOUSPOS
;
1372 ScrollInfo
.nMin
= wParam
;
1373 ScrollInfo
.nMax
= lParam
;
1374 return IntSetScrollInfo(Wnd
, &ScrollInfo
, Msg
== SBM_SETRANGEREDRAW
? TRUE
: FALSE
);
1377 case SBM_SETSCROLLINFO
:
1378 return IntSetScrollInfo(Wnd
, (LPCSCROLLINFO
)lParam
, wParam
);
1380 case SBM_GETSCROLLINFO
:
1382 PSBDATA pSBData
= (PSBDATA
)&pSBWnd
->SBCalc
;
1383 DWORD ret
= NtUserSBGetParms(Wnd
, SB_CTL
, pSBData
, (SCROLLINFO
*) lParam
);
1386 ERR("SBM_GETSCROLLINFO No ScrollInfo\n");
1390 case SBM_GETSCROLLBARINFO
:
1391 ((PSCROLLBARINFO
)lParam
)->cbSize
= sizeof(SCROLLBARINFO
);
1392 return NtUserGetScrollBarInfo(Wnd
, OBJID_CLIENT
, (PSCROLLBARINFO
)lParam
);
1401 WARN("unknown Win32 msg %04x wp=%08lx lp=%08lx\n",
1402 Msg
, wParam
, lParam
);
1408 WARN("unknown msg %04x wp=%04lx lp=%08lx\n", Msg
, wParam
, lParam
);
1411 return DefWindowProcW( Wnd
, Msg
, wParam
, lParam
);
1413 return DefWindowProcA( Wnd
, Msg
, wParam
, lParam
);
1420 ScrollBarWndProcW(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1422 return ScrollBarWndProc_common(DefWindowProcW
, Wnd
, Msg
, wParam
, lParam
, TRUE
);
1426 ScrollBarWndProcA(HWND Wnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
)
1428 return ScrollBarWndProc_common(DefWindowProcA
, Wnd
, Msg
, wParam
, lParam
, FALSE
);
1432 /* PUBLIC FUNCTIONS ***********************************************************/
1440 EnableScrollBar( HWND hwnd
, UINT nBar
, UINT flags
)
1442 BOOL Hook
, Ret
= FALSE
;
1446 Hook
= BeginIfHookedUserApiHook();
1448 /* Bypass SEH and go direct. */
1451 Ret
= NtUserEnableScrollBar(hwnd
, nBar
, flags
);
1452 if (!Ret
) return Ret
;
1453 SCROLL_RefreshScrollBar( hwnd
, nBar
, TRUE
, TRUE
);
1458 Ret
= guah
.EnableScrollBar(hwnd
, nBar
, flags
);
1460 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1462 ERR("Got exception in hooked EnableScrollBar!\n");
1472 RealGetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1477 if (SB_CTL
== SBType
)
1479 return SendMessageW(Wnd
, SBM_GETSCROLLINFO
, 0, (LPARAM
) Info
);
1482 pWnd
= ValidateHwnd(Wnd
);
1483 if (!pWnd
) return FALSE
;
1485 if (SBType
< SB_HORZ
|| SBType
> SB_VERT
)
1487 SetLastError(ERROR_INVALID_PARAMETER
);
1492 SetLastError(ERROR_NO_SCROLLBARS
);
1495 pSBData
= IntGetSBData(pWnd
, SBType
);
1496 return NtUserSBGetParms(Wnd
, SBType
, pSBData
, Info
);
1502 BOOL WINAPI
GetScrollBarInfo( _In_ HWND hwnd
, _In_ LONG idObject
, _Inout_ LPSCROLLBARINFO info
)
1505 PWND pWnd
= ValidateHwnd(hwnd
);
1506 TRACE("hwnd=%p idObject=%d info=%p\n", hwnd
, idObject
, info
);
1507 if (!pWnd
) return FALSE
;
1508 Ret
= NtUserGetScrollBarInfo(hwnd
, idObject
, info
); // This will be fixed once SB is server side.
1509 /* rcScrollBar needs to be in screen coordinates */
1510 OffsetRect( &(info
->rcScrollBar
), pWnd
->rcWindow
.left
, pWnd
->rcWindow
.top
);
1520 GetScrollInfo(HWND Wnd
, INT SBType
, LPSCROLLINFO Info
)
1522 BOOL Hook
, Ret
= FALSE
;
1526 Hook
= BeginIfHookedUserApiHook();
1528 /* Bypass SEH and go direct. */
1529 if (!Hook
) return RealGetScrollInfo(Wnd
, SBType
, Info
);
1533 Ret
= guah
.GetScrollInfo(Wnd
, SBType
, Info
);
1535 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1537 ERR("Got exception in hooked GetScrollInfo!\n");
1552 GetScrollPos(HWND Wnd
, INT Bar
)
1557 TRACE("Wnd=%p Bar=%d\n", Wnd
, Bar
);
1559 /* Refer SB_CTL requests to the window */
1562 return SendMessageW(Wnd
, SBM_GETPOS
, (WPARAM
) 0, (LPARAM
) 0);
1564 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1566 pwnd
= ValidateHwnd(Wnd
);
1567 if (!pwnd
) return 0;
1571 pSBData
= IntGetSBData(pwnd
, Bar
);
1572 return pSBData
->pos
;
1575 SetLastError(ERROR_NO_SCROLLBARS
);
1576 TRACE("GetScrollPos No Scroll Info\n");
1579 SetLastError(ERROR_INVALID_PARAMETER
);
1589 GetScrollRange(HWND Wnd
, int Bar
, LPINT MinPos
, LPINT MaxPos
)
1594 TRACE("Wnd=%x Bar=%d Min=%p Max=%p\n", Wnd
, Bar
, MinPos
, MaxPos
);
1596 /* Refer SB_CTL requests to the window */
1599 return SendMessageW(Wnd
, SBM_GETRANGE
, (WPARAM
) MinPos
, (LPARAM
) MaxPos
);
1601 else if (Bar
== SB_HORZ
|| Bar
== SB_VERT
)
1603 pwnd
= ValidateHwnd(Wnd
);
1604 if (!pwnd
) return FALSE
;
1608 pSBData
= IntGetSBData(pwnd
, Bar
);
1609 *MinPos
= pSBData
->posMin
;
1610 *MaxPos
= pSBData
->posMax
;
1614 SetLastError(ERROR_NO_SCROLLBARS
);
1620 SetLastError(ERROR_INVALID_PARAMETER
);
1625 RealSetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1627 if (SB_CTL
== SBType
)
1629 return SendMessageW(Wnd
, SBM_SETSCROLLINFO
, (WPARAM
) bRedraw
, (LPARAM
) Info
);
1633 return NtUserSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1643 SetScrollInfo(HWND Wnd
, int SBType
, LPCSCROLLINFO Info
, BOOL bRedraw
)
1650 Hook
= BeginIfHookedUserApiHook();
1652 /* Bypass SEH and go direct. */
1653 if (!Hook
) return RealSetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1657 Ret
= guah
.SetScrollInfo(Wnd
, SBType
, Info
, bRedraw
);
1659 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1661 ERR("Got exception in hooked SetScrollInfo!\n");
1677 SetScrollPos(HWND hWnd
, INT nBar
, INT nPos
, BOOL bRedraw
)
1679 SCROLLINFO ScrollInfo
;
1681 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1682 ScrollInfo
.fMask
= SIF_POS
|SIF_PREVIOUSPOS
;
1683 ScrollInfo
.nPos
= nPos
;
1685 return RealSetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
);
1694 SetScrollRange(HWND hWnd
, INT nBar
, INT nMinPos
, INT nMaxPos
, BOOL bRedraw
)
1697 SCROLLINFO ScrollInfo
;
1699 pWnd
= ValidateHwnd(hWnd
);
1700 if ( !pWnd
) return FALSE
;
1702 if (((LONGLONG
)nMaxPos
- nMinPos
) > MAXLONG
)
1704 SetLastError(ERROR_INVALID_SCROLLBAR_RANGE
);
1708 ScrollInfo
.cbSize
= sizeof(SCROLLINFO
);
1709 ScrollInfo
.fMask
= SIF_RANGE
;
1710 ScrollInfo
.nMin
= nMinPos
;
1711 ScrollInfo
.nMax
= nMaxPos
;
1712 SetScrollInfo(hWnd
, nBar
, &ScrollInfo
, bRedraw
); // do not bypass themes.