4 * Copyright 1993 Martin Ayotte
5 * Copyright 1994, 1996 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "user_private.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(scroll
);
29 /* Overlap between arrows and thumb */
30 #define SCROLL_ARROW_THUMB_OVERLAP 0
33 /***********************************************************************
36 * Draw the scroll bar arrows.
38 static void SCROLL_DrawArrows( HDC hdc
, UINT flags
,
39 RECT
*rect
, INT arrowSize
, BOOL vertical
,
40 BOOL top_pressed
, BOOL bottom_pressed
)
46 r
.bottom
= r
.top
+ arrowSize
;
48 r
.right
= r
.left
+ arrowSize
;
50 DrawFrameControl( hdc
, &r
, DFC_SCROLL
,
51 (vertical
? DFCS_SCROLLUP
: DFCS_SCROLLLEFT
)
52 | (top_pressed
? (DFCS_PUSHED
| DFCS_FLAT
) : 0 )
53 | (flags
& ESB_DISABLE_LTUP
? DFCS_INACTIVE
: 0 ) );
57 r
.top
= r
.bottom
-arrowSize
;
59 r
.left
= r
.right
-arrowSize
;
61 DrawFrameControl( hdc
, &r
, DFC_SCROLL
,
62 (vertical
? DFCS_SCROLLDOWN
: DFCS_SCROLLRIGHT
)
63 | (bottom_pressed
? (DFCS_PUSHED
| DFCS_FLAT
) : 0 )
64 | (flags
& ESB_DISABLE_RTDN
? DFCS_INACTIVE
: 0) );
67 /***********************************************************************
70 * Draw the scroll bar interior (everything except the arrows).
72 static void SCROLL_DrawInterior( HWND hwnd
, HDC hdc
, INT nBar
,
73 RECT
*rect
, INT arrowSize
,
74 INT thumbSize
, INT thumbPos
, BOOL vertical
,
75 BOOL top_selected
, BOOL bottom_selected
)
79 HBRUSH hSaveBrush
,hBrush
;
83 hBrush
= (HBRUSH
)SendMessageW( GetParent(hwnd
), WM_CTLCOLORSCROLLBAR
,
84 (WPARAM
)hdc
,(LPARAM
)hwnd
);
88 COLORREF bk
= GetSysColor( COLOR_3DHILIGHT
);
89 SetTextColor( hdc
, GetSysColor( COLOR_3DFACE
));
90 SetBkColor( hdc
, bk
);
92 /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
93 * we better use 0x55aa bitmap brush to make scrollbar's background
94 * look different from the window background.
96 if (bk
== GetSysColor( COLOR_WINDOW
))
97 hBrush
= SYSCOLOR_Get55AABrush();
100 hBrush
= GetSysColorBrush( COLOR_SCROLLBAR
);
101 UnrealizeObject( hBrush
);
105 hSavePen
= SelectObject( hdc
, SYSCOLOR_GetPen(COLOR_WINDOWFRAME
) );
106 hSaveBrush
= SelectObject( hdc
, hBrush
);
108 /* Calculate the scroll rectangle */
113 r
.top
+= arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
;
114 r
.bottom
-= (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
);
118 r
.left
+= arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
;
119 r
.right
-= (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
);
122 /* Draw the scroll bar frame */
124 /* Draw the scroll rectangles and thumb */
126 if (!thumbPos
) /* No thumb to draw */
128 PatBlt( hdc
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
, PATCOPY
);
130 /* cleanup and return */
131 SelectObject( hdc
, hSavePen
);
132 SelectObject( hdc
, hSaveBrush
);
138 PatBlt( hdc
, r
.left
, r
.top
, r
.right
- r
.left
,
139 thumbPos
- (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
),
140 top_selected
? 0x0f0000 : PATCOPY
);
141 r
.top
+= thumbPos
- (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
);
142 PatBlt( hdc
, r
.left
, r
.top
+ thumbSize
, r
.right
- r
.left
,
143 r
.bottom
- r
.top
- thumbSize
,
144 bottom_selected
? 0x0f0000 : PATCOPY
);
145 r
.bottom
= r
.top
+ thumbSize
;
147 else /* horizontal */
149 PatBlt( hdc
, r
.left
, r
.top
,
150 thumbPos
- (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
),
151 r
.bottom
- r
.top
, top_selected
? 0x0f0000 : PATCOPY
);
152 r
.left
+= thumbPos
- (arrowSize
- SCROLL_ARROW_THUMB_OVERLAP
);
153 PatBlt( hdc
, r
.left
+ thumbSize
, r
.top
, r
.right
- r
.left
- thumbSize
,
154 r
.bottom
- r
.top
, bottom_selected
? 0x0f0000 : PATCOPY
);
155 r
.right
= r
.left
+ thumbSize
;
160 SelectObject( hdc
, GetSysColorBrush(COLOR_BTNFACE
) );
161 Rectangle( hdc
, r
.left
+1, r
.top
+1, r
.right
-1, r
.bottom
-1 );
162 DrawEdge( hdc
, &r
, EDGE_RAISED
, BF_RECT
);
165 SelectObject( hdc
, hSavePen
);
166 SelectObject( hdc
, hSaveBrush
);
169 void WINAPI
USER_ScrollBarDraw( HWND hwnd
, HDC hdc
, INT nBar
, enum SCROLL_HITTEST hit_test
,
170 const struct SCROLL_TRACKING_INFO
*tracking_info
, BOOL arrows
,
171 BOOL interior
, RECT
*rect
, UINT enable_flags
, INT arrowSize
,
172 INT thumbPos
, INT thumbSize
, BOOL vertical
)
176 DWORD style
= GetWindowLongW( hwnd
, GWL_STYLE
);
178 if (style
& SBS_SIZEGRIP
)
182 FillRect( hdc
, &rc
, GetSysColorBrush( COLOR_BTNFACE
) );
183 rc
.left
= max( rc
.left
, rc
.right
- GetSystemMetrics( SM_CXVSCROLL
) - 1 );
184 rc
.top
= max( rc
.top
, rc
.bottom
- GetSystemMetrics( SM_CYHSCROLL
) - 1 );
185 DrawFrameControl( hdc
, &rc
, DFC_SCROLL
, DFCS_SCROLLSIZEGRIP
);
189 if (style
& SBS_SIZEBOX
)
191 FillRect( hdc
, rect
, GetSysColorBrush( COLOR_BTNFACE
) );
196 /* Draw the arrows */
197 if (arrows
&& arrowSize
)
199 if (vertical
== tracking_info
->vertical
&& GetCapture() == hwnd
)
200 SCROLL_DrawArrows( hdc
, enable_flags
, rect
, arrowSize
, vertical
,
201 hit_test
== tracking_info
->hit_test
&& hit_test
== SCROLL_TOP_ARROW
,
202 hit_test
== tracking_info
->hit_test
&& hit_test
== SCROLL_BOTTOM_ARROW
);
204 SCROLL_DrawArrows( hdc
, enable_flags
, rect
, arrowSize
, vertical
, FALSE
, FALSE
);
209 if (vertical
== tracking_info
->vertical
&& GetCapture() == hwnd
)
211 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, rect
, arrowSize
, thumbSize
, thumbPos
, vertical
,
212 hit_test
== tracking_info
->hit_test
&& hit_test
== SCROLL_TOP_RECT
,
213 hit_test
== tracking_info
->hit_test
&& hit_test
== SCROLL_BOTTOM_RECT
);
217 SCROLL_DrawInterior( hwnd
, hdc
, nBar
, rect
, arrowSize
, thumbSize
, thumbPos
,
218 vertical
, FALSE
, FALSE
);
222 /* if scroll bar has focus, reposition the caret */
223 if(hwnd
==GetFocus() && (nBar
==SB_CTL
))
227 SetCaretPos(thumbPos
+ 1, rect
->top
+ 1);
231 SetCaretPos(rect
->top
+ 1, thumbPos
+ 1);
236 LRESULT WINAPI
USER_ScrollBarProc( HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
, BOOL unicode
)
243 case WM_LBUTTONDBLCLK
:
247 case WM_NCMOUSELEAVE
:
257 case SBM_SETRANGEREDRAW
:
259 case SBM_GETSCROLLINFO
:
260 case SBM_GETSCROLLBARINFO
:
261 case SBM_SETSCROLLINFO
:
266 case SBM_ENABLE_ARROWS
:
274 return NtUserMessageCall( hwnd
, message
, wParam
, lParam
, 0, NtUserScrollBarWndProc
, !unicode
);
277 if (message
>= WM_USER
)
278 WARN("unknown msg %04x wp=%04Ix lp=%08Ix\n",
279 message
, wParam
, lParam
);
281 return DefWindowProcW( hwnd
, message
, wParam
, lParam
);
283 return DefWindowProcA( hwnd
, message
, wParam
, lParam
);
288 /***********************************************************************
289 * ScrollBarWndProc_common
291 LRESULT
ScrollBarWndProc_common( HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
, BOOL unicode
)
293 return user_api
->pScrollBarWndProc( hwnd
, msg
, wParam
, lParam
, unicode
);
297 /*************************************************************************
298 * GetScrollInfo (USER32.@)
300 * GetScrollInfo can be used to retrieve the position, upper bound,
301 * lower bound, and page size of a scrollbar control.
304 * hwnd [I] Handle of window with scrollbar(s)
305 * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
306 * info [IO] fMask specifies which values to retrieve
309 * TRUE if SCROLLINFO is filled
310 * ( if nBar is SB_CTL, GetScrollInfo returns TRUE even if nothing
313 BOOL WINAPI DECLSPEC_HOTPATCH
GetScrollInfo(HWND hwnd
, INT nBar
, LPSCROLLINFO info
)
315 TRACE("hwnd=%p nBar=%d info=%p\n", hwnd
, nBar
, info
);
317 /* Refer SB_CTL requests to the window */
320 SendMessageW(hwnd
, SBM_GETSCROLLINFO
, 0, (LPARAM
)info
);
323 return NtUserGetScrollInfo( hwnd
, nBar
, info
);
327 /*************************************************************************
328 * SetScrollPos (USER32.@)
330 * Sets the current position of the scroll thumb.
333 * hwnd [I] Handle of window with scrollbar(s)
334 * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
336 * bRedraw [I] Should scrollbar be redrawn afterwards?
339 * Success: Scrollbar position
343 * Note the ambiguity when 0 is returned. Use GetLastError
344 * to make sure there was an error (and to know which one).
346 int WINAPI DECLSPEC_HOTPATCH
SetScrollPos( HWND hwnd
, int bar
, int pos
, BOOL redraw
)
350 info
.cbSize
= sizeof(info
);
352 info
.fMask
= SIF_POS
| SIF_RETURNPREV
;
353 return NtUserSetScrollInfo( hwnd
, bar
, &info
, redraw
);
357 /*************************************************************************
358 * GetScrollPos (USER32.@)
360 * Gets the current position of the scroll thumb.
363 * hwnd [I] Handle of window with scrollbar(s)
364 * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
367 * Success: Current position
371 * There is ambiguity when 0 is returned. Use GetLastError
372 * to make sure there was an error (and to know which one).
374 int WINAPI DECLSPEC_HOTPATCH
GetScrollPos( HWND hwnd
, int bar
)
378 TRACE( "hwnd=%p bar=%d\n", hwnd
, bar
);
380 /* Refer SB_CTL requests to the window */
382 return SendMessageW( hwnd
, SBM_GETPOS
, 0, 0 );
384 info
.cbSize
= sizeof(info
);
385 info
.fMask
= SIF_POS
;
386 return GetScrollInfo( hwnd
, bar
, &info
) ? info
.nPos
: 0;
390 /*************************************************************************
391 * SetScrollRange (USER32.@)
392 * The SetScrollRange function sets the minimum and maximum scroll box positions
393 * If nMinPos and nMaxPos is the same value, the scroll bar will hide
395 * Sets the range of the scroll bar.
398 * hwnd [I] Handle of window with scrollbar(s)
399 * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
400 * minVal [I] New minimum value
401 * maxVal [I] New Maximum value
402 * bRedraw [I] Should scrollbar be redrawn afterwards?
408 BOOL WINAPI DECLSPEC_HOTPATCH
SetScrollRange(HWND hwnd
, INT nBar
, INT minVal
, INT maxVal
, BOOL bRedraw
)
412 TRACE("hwnd=%p nBar=%d min=%d max=%d, bRedraw=%d\n", hwnd
, nBar
, minVal
, maxVal
, bRedraw
);
414 info
.cbSize
= sizeof(info
);
415 info
.fMask
= SIF_RANGE
;
418 NtUserSetScrollInfo( hwnd
, nBar
, &info
, bRedraw
);
423 /*************************************************************************
424 * GetScrollRange (USER32.@)
426 * Gets the range of the scroll bar.
429 * hwnd [I] Handle of window with scrollbar(s)
430 * nBar [I] One of SB_HORZ, SB_VERT, or SB_CTL
431 * lpMin [O] Where to store minimum value
432 * lpMax [O] Where to store maximum value
435 * TRUE if values is filled
437 BOOL WINAPI DECLSPEC_HOTPATCH
GetScrollRange( HWND hwnd
, int bar
, int *min
, int *max
)
441 TRACE( "hwnd=%p nBar=%d lpMin=%p lpMax=%p\n", hwnd
, bar
, min
, max
);
443 /* Refer SB_CTL requests to the window */
446 SendMessageW( hwnd
, SBM_GETRANGE
, (WPARAM
)min
, (LPARAM
)max
);
450 info
.cbSize
= sizeof(info
);
451 info
.fMask
= SIF_RANGE
;
452 info
.nMin
= info
.nMax
= 0;
453 GetScrollInfo( hwnd
, bar
, &info
);
454 if (min
) *min
= info
.nMin
;
455 if (max
) *max
= info
.nMax
;