Scrollbar improvements
[reactos.git] / reactos / subsys / win32k / ntuser / scrollbar.c
1 /* $Id: scrollbar.c,v 1.4 2003/01/24 22:42:15 jfilby Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Scrollbars
6 * FILE: subsys/win32k/ntuser/scrollbar.c
7 * PROGRAMER: Jason Filby (jasonfilby@yahoo.com)
8 * REVISION HISTORY:
9 * 16-11-2002 Jason Filby Created
10 */
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <win32k/win32k.h>
15 #include <include/object.h>
16 #include <include/window.h>
17 #include <include/class.h>
18 #include <include/error.h>
19 #include <include/winsta.h>
20 #include <include/winpos.h>
21 #include <include/rect.h>
22
23 //#define NDEBUG
24 #include <debug.h>
25
26 #define SCROLL_MIN_RECT 4 /* Minimum size of the rectangle between the arrows */
27 #define SCROLL_ARROW_THUMB_OVERLAP 0 /* Overlap between arrows and thumb */
28
29 /* FUNCTIONS *****************************************************************/
30
31 /* Ported from WINE20020904 */
32 /* Compute the scroll bar rectangle, in drawing coordinates (i.e. client coords for SB_CTL, window coords for SB_VERT and
33 * SB_HORZ). 'arrowSize' returns the width or height of an arrow (depending on * the orientation of the scrollbar),
34 * 'thumbSize' returns the size of the thumb, and 'thumbPos' returns the position of the thumb relative to the left or to
35 * the top. Return TRUE if the scrollbar is vertical, FALSE if horizontal.
36 */
37 static BOOL
38 SCROLL_GetScrollBarRect (PWINDOW_OBJECT Window, INT nBar, PRECT lprect)
39 {
40 SCROLLBARINFO info;
41 INT pixels, thumbSize, arrowSize;
42 BOOL vertical;
43 RECT ClientRect = Window->ClientRect;
44 RECT WindowRect = Window->WindowRect;
45 ULONG Style;
46
47 switch (nBar)
48 {
49 case SB_HORZ:
50 lprect->left = ClientRect.left - WindowRect.left;
51 lprect->top = ClientRect.bottom - WindowRect.top;
52 lprect->right = ClientRect.right - WindowRect.left;
53 lprect->bottom = lprect->top + NtUserGetSystemMetrics (SM_CYHSCROLL);
54 if (Window->Style & WS_BORDER)
55 {
56 lprect->left--;
57 lprect->right++;
58 }
59 else if (Window->Style & WS_VSCROLL)
60 lprect->right++;
61 vertical = FALSE;
62 break;
63
64 case SB_VERT:
65 lprect->left = ClientRect.right - WindowRect.left;
66 lprect->top = ClientRect.top - WindowRect.top;
67 lprect->right = lprect->left + NtUserGetSystemMetrics (SM_CXVSCROLL);
68 lprect->bottom = ClientRect.bottom - WindowRect.top;
69 if (Window->Style & WS_BORDER)
70 {
71 lprect->top--;
72 lprect->bottom++;
73 }
74 else if (Window->Style & WS_HSCROLL)
75 lprect->bottom++;
76 vertical = TRUE;
77 break;
78
79 case SB_CTL:
80 W32kGetClientRect (Window, lprect);
81 vertical = ((Window->Style & SBS_VERT) != 0);
82 break;
83
84 default:
85 W32kReleaseWindowObject(Window);
86 return FALSE;
87 }
88
89 if (vertical)
90 pixels = lprect->bottom - lprect->top;
91 else
92 pixels = lprect->right - lprect->left;
93
94 info.cbSize = sizeof(SCROLLBARINFO);
95 SCROLL_GetScrollBarInfo (Window, nBar, &info);
96
97 if (pixels <= 2 * NtUserGetSystemMetrics (SM_CXVSCROLL) + SCROLL_MIN_RECT)
98 {
99 info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
100 }
101 else
102 {
103 arrowSize = NtUserGetSystemMetrics (SM_CXVSCROLL);
104 pixels -= (2 * (NtUserGetSystemMetrics (SM_CXVSCROLL) - SCROLL_ARROW_THUMB_OVERLAP));
105
106 /* Temporary initialization - to be removed once proper code is in */
107 info.dxyLineButton = info.xyThumbTop = info.xyThumbBottom = 0;
108
109 /* if (info->Page)
110 {
111 thumbSize = MulDiv(pixels,info->Page,(info->MaxVal-info->MinVal+1));
112 if (*thumbSize < SCROLL_MIN_THUMB) *thumbSize = SCROLL_MIN_THUMB;
113 }
114 else *thumbSize = NtUserGetSystemMetrics(SM_CXVSCROLL); */
115 /*
116 if (((pixels -= *thumbSize ) < 0) ||
117 ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH))
118 { */
119 /* Rectangle too small or scrollbar disabled -> no thumb */
120 /* *thumbPos = *thumbSize = 0;
121 }
122 else
123 { */
124 /* INT max = info->MaxVal - max( info->Page-1, 0 );
125 if (info->MinVal >= max)
126 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP;
127 else
128 *thumbPos = *arrowSize - SCROLL_ARROW_THUMB_OVERLAP
129 + MulDiv(pixels, (info->CurVal-info->MinVal),(max - info->MinVal));
130 } */
131 }
132
133 return vertical;
134 }
135
136 DWORD SCROLL_CreateScrollBar(PWINDOW_OBJECT Window, LONG idObject)
137 {
138 PSCROLLBARINFO psbi;
139 LRESULT Result;
140 INT i;
141
142 Result = WinPosGetNonClientSize(Window->Self,
143 &Window->WindowRect,
144 &Window->ClientRect);
145
146 psbi = ExAllocatePool(NonPagedPool, sizeof(SCROLLBARINFO));
147
148 for (i=0; i<CCHILDREN_SCROLLBAR+1; i++)
149 psbi->rgstate[i] = 0;
150
151 switch(idObject)
152 {
153 case SB_HORZ:
154 Window->pHScroll = psbi;
155 break;
156 case SB_VERT:
157 Window->pVScroll = psbi;
158 break;
159 case SB_CTL:
160 Window->wExtra = psbi;
161 break;
162 default:
163 return FALSE;
164 }
165
166 SCROLL_GetScrollBarRect (Window, idObject, &(psbi->rcScrollBar));
167
168 return 0;
169 }
170
171 DWORD SCROLL_GetScrollBarInfo(PWINDOW_OBJECT Window, LONG idObject, PSCROLLBARINFO psbi)
172 {
173 switch(idObject)
174 {
175 case SB_HORZ:
176 memcpy(psbi, Window->pHScroll, psbi->cbSize);
177 break;
178 case SB_VERT:
179 memcpy(psbi, Window->pVScroll, psbi->cbSize);
180 break;
181 case SB_CTL:
182 memcpy(psbi, Window->wExtra, psbi->cbSize);
183 break;
184 default:
185 W32kReleaseWindowObject(Window);
186 return FALSE;
187 }
188
189 return TRUE;
190 }
191
192 DWORD
193 STDCALL
194 NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi)
195 {
196 PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
197
198 if (!Window) return FALSE;
199
200 SCROLL_GetScrollBarInfo(Window, idObject, psbi);
201
202 W32kReleaseWindowObject(Window);
203
204 return TRUE;
205 }
206
207 DWORD
208 STDCALL
209 NtUserEnableScrollBar(
210 DWORD Unknown0,
211 DWORD Unknown1,
212 DWORD Unknown2)
213 {
214 return 0;
215 }
216
217 DWORD
218 STDCALL
219 NtUserScrollDC(
220 DWORD Unknown0,
221 DWORD Unknown1,
222 DWORD Unknown2,
223 DWORD Unknown3,
224 DWORD Unknown4,
225 DWORD Unknown5,
226 DWORD Unknown6)
227
228 {
229 UNIMPLEMENTED
230
231 return 0;
232 }
233
234 DWORD
235 STDCALL
236 NtUserSetScrollInfo(
237 DWORD Unknown0,
238 DWORD Unknown1,
239 DWORD Unknown2,
240 DWORD Unknown3)
241 {
242 UNIMPLEMENTED
243
244 return 0;
245 }
246
247 /* Ported from WINE20020904 (SCROLL_ShowScrollBar) */
248 DWORD
249 STDCALL
250 NtUserShowScrollBar(HWND hWnd, int wBar, DWORD bShow)
251 {
252 BOOL fShowV = (wBar == SB_VERT) ? 0 : bShow;
253 BOOL fShowH = (wBar == SB_HORZ) ? 0 : bShow;
254 PWINDOW_OBJECT Window = W32kGetWindowObject(hWnd);
255
256 switch (wBar)
257 {
258 case SB_CTL:
259 NtUserShowWindow (hWnd, fShowH ? SW_SHOW : SW_HIDE);
260 return TRUE;
261
262 case SB_BOTH:
263 case SB_HORZ:
264 if (fShowH)
265 {
266 fShowH = !(Window->Style & WS_HSCROLL);
267 Window->Style |= WS_HSCROLL;
268 }
269 else /* hide it */
270 {
271 fShowH = (Window->Style & WS_HSCROLL);
272 Window->Style &= ~WS_HSCROLL;
273 }
274 if (wBar == SB_HORZ)
275 {
276 fShowV = FALSE;
277 break;
278 }
279 /* fall through */
280
281 case SB_VERT:
282 if (fShowV)
283 {
284 fShowV = !(Window->Style & WS_VSCROLL);
285 Window->Style |= WS_VSCROLL;
286 }
287 else /* hide it */
288 {
289 fShowV = (Window->Style & WS_VSCROLL);
290 Window->Style &= ~WS_VSCROLL;
291 }
292 if (wBar == SB_VERT)
293 fShowH = FALSE;
294 break;
295
296 default:
297 return FALSE; /* Nothing to do! */
298 }
299
300 if (fShowH || fShowV) /* frame has been changed, let the window redraw itself */
301 {
302 NtUserSetWindowPos (hWnd, 0, 0, 0, 0, 0,
303 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED);
304 return TRUE;
305 }
306 return FALSE; /* no frame changes */
307 }
308
309 /* EOF */