[CRT] Massively improve performance of rand_s
[reactos.git] / modules / rostests / winetests / user32 / scroll.c
1 /*
2 * Unit tests for scrollbar
3 *
4 * Copyright 2008 Lyutin Anatoly (Etersoft)
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <windows.h>
25
26 #include "wine/test.h"
27
28 static HWND hScroll;
29 static BOOL bThemeActive = FALSE;
30
31 static LRESULT CALLBACK MyWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
32 {
33 switch(msg)
34 {
35
36 case WM_CREATE:
37 {
38 hScroll = CreateWindowA( "SCROLLBAR", "", WS_CHILD | WS_VISIBLE, 0, 0, 120, 100, hWnd, (HMENU)100, GetModuleHandleA(0), 0 );
39
40 return 0;
41 }
42 case WM_DESTROY:
43 PostQuitMessage(0);
44 break;
45 case WM_HSCROLL:
46 case WM_VSCROLL:
47 /* stop tracking */
48 ReleaseCapture();
49 return 0;
50 default:
51 return DefWindowProcA(hWnd, msg, wParam, lParam);
52 }
53 return 0;
54 }
55
56 static HWND create_main_test_wnd(void)
57 {
58 HWND hMainWnd;
59
60 hScroll = NULL;
61 hMainWnd = CreateWindowExA( 0, "MyTestWnd", "Scroll",
62 WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,
63 CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 );
64 ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
65 ok(hScroll != NULL, "got NULL scroll bar handle\n");
66
67 return hMainWnd;
68 }
69
70 static void scrollbar_test_track(void)
71 {
72 HWND mainwnd;
73
74 mainwnd = create_main_test_wnd();
75
76 /* test that scrollbar tracking is terminated when
77 * the control loses mouse capture */
78 SendMessageA( hScroll, WM_LBUTTONDOWN, 0, MAKELPARAM( 1, 1));
79 /* a normal return from SendMessage */
80 /* not normal for instances such as closing the window */
81 ok( IsWindow( hScroll), "Scrollbar has gone!\n");
82
83 DestroyWindow(hScroll);
84 DestroyWindow(mainwnd);
85 }
86
87 static void test_EnableScrollBar(void)
88 {
89 HWND mainwnd;
90 BOOL ret;
91
92 mainwnd = create_main_test_wnd();
93
94 ret = EnableScrollBar( hScroll, SB_CTL, ESB_DISABLE_BOTH );
95 ok( ret, "The scrollbar should be disabled.\n" );
96 ok( !IsWindowEnabled( hScroll ), "The scrollbar window should be disabled.\n" );
97
98 ret = EnableScrollBar( hScroll, SB_CTL, ESB_ENABLE_BOTH );
99 ok( ret, "The scrollbar should be enabled.\n" );
100 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
101
102 /* test buttons separately */
103 ret = EnableScrollBar( hScroll, SB_CTL, ESB_DISABLE_LTUP );
104 ok( ret, "The scrollbar LTUP button should be disabled.\n" );
105 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
106 ret = EnableScrollBar( hScroll, SB_CTL, ESB_ENABLE_BOTH );
107 ok( ret, "The scrollbar should be enabled.\n" );
108 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
109
110 ret = EnableScrollBar( hScroll, SB_CTL, ESB_DISABLE_RTDN );
111 ok( ret, "The scrollbar RTDN button should be disabled.\n" );
112 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
113 ret = EnableScrollBar( hScroll, SB_CTL, ESB_ENABLE_BOTH );
114 ok( ret, "The scrollbar should be enabled.\n" );
115 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be enabled.\n" );
116
117 SetLastError( 0xdeadbeef );
118 ret = EnableScrollBar( mainwnd, SB_CTL, ESB_ENABLE_BOTH );
119 ok( !ret, "EnableScrollBar should fail.\n" );
120 todo_wine
121 ok( GetLastError() == ERROR_INVALID_PARAMETER
122 || broken(GetLastError() == 0xdeadbeef), /* winxp */
123 "GetLastError() = %u\n", GetLastError() );
124
125 /* disable window, try to re-enable */
126 ret = EnableWindow( hScroll, FALSE );
127 ok( !ret, "got %d\n", ret );
128 ok( !IsWindowEnabled( hScroll ), "The scrollbar window should be disabled.\n" );
129
130 ret = EnableScrollBar( hScroll, SB_CTL, ESB_ENABLE_BOTH );
131 ok( ret, "got %d\n", ret );
132 ok( IsWindowEnabled( hScroll ), "The scrollbar window should be disabled.\n" );
133
134 DestroyWindow(hScroll);
135 DestroyWindow(mainwnd);
136 }
137
138 static void test_SetScrollPos(void)
139 {
140 HWND mainwnd;
141 int ret;
142
143 mainwnd = create_main_test_wnd();
144
145 EnableWindow( hScroll, FALSE );
146 ok( !IsWindowEnabled( hScroll ), "The scroll should be disabled.\n" );
147
148 ret = SetScrollPos( hScroll, SB_CTL, 30, TRUE);
149 ok( !ret, "The position should not be set.\n" );
150
151 ret = GetScrollPos( hScroll, SB_CTL);
152 ok( !ret, "The position should be equal to zero\n");
153
154 ret = SetScrollRange( hScroll, SB_CTL, 0, 100, TRUE );
155 ok( ret, "The range should be set.\n" );
156
157 ret = SetScrollPos( hScroll, SB_CTL, 30, TRUE);
158 ok( !ret , "The position should not be set.\n" );
159
160 ret = GetScrollPos( hScroll, SB_CTL);
161 ok( ret == 30, "The position should be set!!!\n");
162
163 EnableWindow( hScroll, TRUE );
164 ok( IsWindowEnabled( hScroll ), "The scroll should be enabled.\n" );
165
166 ret = SetScrollPos( hScroll, SB_CTL, 30, TRUE);
167 ok( ret == 30, "The position should be set.\n" );
168
169 ret = GetScrollPos( hScroll, SB_CTL);
170 ok( ret == 30, "The position should not be equal to zero\n");
171
172 ret = SetScrollRange( hScroll, SB_CTL, 0, 100, TRUE );
173 ok( ret, "The range should be set.\n" );
174
175 ret = SetScrollPos( hScroll, SB_CTL, 30, TRUE);
176 ok( ret == 30, "The position should be set.\n" );
177
178 ret = GetScrollPos( hScroll, SB_CTL);
179 ok( ret == 30, "The position should not be equal to zero\n");
180
181 SetLastError( 0xdeadbeef );
182 ret = SetScrollPos( mainwnd, SB_CTL, 30, TRUE );
183 ok( !ret, "The position should not be set.\n" );
184 ok( GetLastError() == 0xdeadbeef, "GetLastError() = %u\n", GetLastError() );
185
186 SetLastError( 0xdeadbeef );
187 ret = GetScrollPos( mainwnd, SB_CTL );
188 ok( !ret, "The position should be equal to zero\n");
189 ok( GetLastError() == 0xdeadbeef, "GetLastError() = %u\n", GetLastError() );
190
191 DestroyWindow(hScroll);
192 DestroyWindow(mainwnd);
193 }
194
195 static void test_ShowScrollBar(void)
196 {
197 HWND mainwnd;
198 BOOL ret;
199
200 mainwnd = create_main_test_wnd();
201
202 ret = ShowScrollBar( hScroll, SB_CTL, FALSE );
203 ok( ret, "The ShowScrollBar() should not failed.\n" );
204 ok( !IsWindowVisible( hScroll ), "The scrollbar window should not be visible\n" );
205
206 ret = ShowScrollBar( hScroll, SB_CTL, TRUE );
207 ok( ret, "The ShowScrollBar() should not failed.\n" );
208 ok( !IsWindowVisible( hScroll ), "The scrollbar window should be visible\n" );
209
210 ret = ShowScrollBar( NULL, SB_CTL, TRUE );
211 ok( !ret, "The ShowScrollBar() should failed.\n" );
212
213 ret = ShowScrollBar( mainwnd, SB_CTL, TRUE );
214 ok( ret, "The ShowScrollBar() should not fail.\n" );
215
216 DestroyWindow(hScroll);
217 DestroyWindow(mainwnd);
218 }
219
220 static void test_GetScrollBarInfo(void)
221 {
222 HWND hMainWnd;
223 BOOL ret;
224 SCROLLBARINFO sbi;
225 RECT rect;
226 BOOL (WINAPI *pGetScrollBarInfo)(HWND, LONG, LPSCROLLBARINFO);
227
228 pGetScrollBarInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetScrollBarInfo");
229 if (!pGetScrollBarInfo)
230 {
231 win_skip("GetScrollBarInfo is not available\n");
232 return;
233 }
234
235 hMainWnd = create_main_test_wnd();
236
237 /* Test GetScrollBarInfo to make sure it returns rcScrollBar in screen
238 * coordinates. */
239 sbi.cbSize = sizeof(sbi);
240 ret = pGetScrollBarInfo( hScroll, OBJID_CLIENT, &sbi);
241 ok( ret, "The GetScrollBarInfo() call should not fail.\n" );
242 GetWindowRect( hScroll, &rect );
243 ok( ret, "The GetWindowRect() call should not fail.\n" );
244 ok( !(sbi.rgstate[0] & (STATE_SYSTEM_INVISIBLE|STATE_SYSTEM_OFFSCREEN)),
245 "unexpected rgstate(0x%x)\n", sbi.rgstate[0]);
246 ok(EqualRect(&rect, &sbi.rcScrollBar), "WindowRect %s != rcScrollBar %s\n",
247 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&sbi.rcScrollBar));
248
249 /* Test windows horizontal and vertical scrollbar to make sure rcScrollBar
250 * is still returned in screen coordinates by moving the window, and
251 * making sure that it shifts the rcScrollBar value. */
252 ShowWindow( hMainWnd, SW_SHOW );
253 sbi.cbSize = sizeof(sbi);
254 ret = pGetScrollBarInfo( hMainWnd, OBJID_HSCROLL, &sbi);
255 ok( ret, "The GetScrollBarInfo() call should not fail.\n" );
256 GetWindowRect( hMainWnd, &rect );
257 ok( ret, "The GetWindowRect() call should not fail.\n" );
258 MoveWindow( hMainWnd, rect.left+5, rect.top+5,
259 rect.right-rect.left, rect.bottom-rect.top, TRUE );
260 rect = sbi.rcScrollBar;
261 OffsetRect(&rect, 5, 5);
262 ret = pGetScrollBarInfo( hMainWnd, OBJID_HSCROLL, &sbi);
263 ok( ret, "The GetScrollBarInfo() call should not fail.\n" );
264 ok(EqualRect(&rect, &sbi.rcScrollBar), "PreviousRect %s != CurrentRect %s\n",
265 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&sbi.rcScrollBar));
266
267 sbi.cbSize = sizeof(sbi);
268 ret = pGetScrollBarInfo( hMainWnd, OBJID_VSCROLL, &sbi);
269 ok( ret, "The GetScrollBarInfo() call should not fail.\n" );
270 GetWindowRect( hMainWnd, &rect );
271 ok( ret, "The GetWindowRect() call should not fail.\n" );
272 MoveWindow( hMainWnd, rect.left+5, rect.top+5,
273 rect.right-rect.left, rect.bottom-rect.top, TRUE );
274 rect = sbi.rcScrollBar;
275 OffsetRect(&rect, 5, 5);
276 ret = pGetScrollBarInfo( hMainWnd, OBJID_VSCROLL, &sbi);
277 ok( ret, "The GetScrollBarInfo() call should not fail.\n" );
278 ok(EqualRect(&rect, &sbi.rcScrollBar), "PreviousRect %s != CurrentRect %s\n",
279 wine_dbgstr_rect(&rect), wine_dbgstr_rect(&sbi.rcScrollBar));
280
281 DestroyWindow(hScroll);
282 DestroyWindow(hMainWnd);
283 }
284
285 /* some tests designed to show that Horizontal and Vertical
286 * window scroll bar info are not created independently */
287 static void scrollbar_test_default( DWORD style)
288 {
289 INT min, max, ret;
290 DWORD winstyle;
291 HWND hwnd;
292 SCROLLINFO si = { sizeof( SCROLLINFO), SIF_TRACKPOS };
293
294 hwnd = CreateWindowExA( 0, "static", "", WS_POPUP | style,
295 0, 0, 10, 10, 0, 0, 0, NULL);
296 assert( hwnd != 0);
297
298 ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
299 ok( ret ||
300 broken( !ret) /* Win 9x/ME */ , "GetScrollRange failed.\n");
301 /* range is 0,0 if there are no H or V scroll bars. 0,100 otherwise */
302 if( !( style & ( WS_VSCROLL | WS_HSCROLL)))
303 ok( min == 0 && max == 0,
304 "Scroll bar range is %d,%d. Expected 0,0. Style %08x\n", min, max, style);
305 else
306 ok(( min == 0 && max == 100) ||
307 broken( min == 0 && max == 0), /* Win 9x/ME */
308 "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style);
309 ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
310 ok( ret ||
311 broken( !ret) /* Win 9x/ME */ , "GetScrollRange failed.\n");
312 /* range is 0,0 if there are no H or V scroll bars. 0,100 otherwise */
313 if( !( style & ( WS_VSCROLL | WS_HSCROLL)))
314 ok( min == 0 && max == 0,
315 "Scroll bar range is %d,%d. Expected 0,0. Style %08x\n", min, max, style);
316 else
317 ok(( min == 0 && max == 100) ||
318 broken( min == 0 && max == 0), /* Win 9x/ME */
319 "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style);
320 /* test GetScrollInfo, vist for vertical SB */
321 ret = GetScrollInfo( hwnd, SB_VERT, &si);
322 /* should fail if no H or V scroll bar styles are present. Succeed otherwise */
323 if( !( style & ( WS_VSCROLL | WS_HSCROLL)))
324 ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style);
325 else
326 ok( ret ||
327 broken( !ret), /* Win 9x/ME */
328 "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
329 /* Same for Horizontal SB */
330 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
331 /* should fail if no H or V scroll bar styles are present. Succeed otherwise */
332 if( !( style & ( WS_VSCROLL | WS_HSCROLL)))
333 ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style);
334 else
335 ok( ret ||
336 broken( !ret), /* Win 9x/ME */
337 "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
338 /* now set the Vertical Scroll range to something that could be the default value it
339 * already has */;
340 ret = SetScrollRange( hwnd, SB_VERT, 0, 100, FALSE);
341 ok( ret, "SetScrollRange failed.\n");
342 /* and request the Horizontal range */
343 ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
344 ok( ret, "GetScrollRange failed.\n");
345 /* now the range should be 0,100 in ALL cases */
346 ok( min == 0 && max == 100,
347 "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style);
348 /* See what is different now for GetScrollRange */
349 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
350 /* should succeed in ALL cases */
351 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
352 ret = GetScrollInfo( hwnd, SB_VERT, &si);
353 /* should succeed in ALL cases */
354 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
355 /* report the windows style */
356 winstyle = GetWindowLongA( hwnd, GWL_STYLE );
357 /* WS_VSCROLL added to the window style */
358 if( !(style & WS_VSCROLL))
359 {
360 if (bThemeActive || style != WS_HSCROLL)
361 todo_wine
362 ok( (winstyle & (WS_HSCROLL|WS_VSCROLL)) == ( style | WS_VSCROLL),
363 "unexpected style change %08x/%08x\n", winstyle, style);
364 else
365 ok( (winstyle & (WS_HSCROLL|WS_VSCROLL)) == style,
366 "unexpected style change %08x/%08x\n", winstyle, style);
367 }
368 /* do the test again with H and V reversed.
369 * Start with a clean window */
370 DestroyWindow( hwnd);
371 hwnd = CreateWindowExA( 0, "static", "", WS_POPUP | style,
372 0, 0, 10, 10, 0, 0, 0, NULL);
373 assert( hwnd != 0);
374 /* Set Horizontal Scroll range to something that could be the default value it
375 * already has */;
376 ret = SetScrollRange( hwnd, SB_HORZ, 0, 100, FALSE);
377 ok( ret, "SetScrollRange failed.\n");
378 /* and request the Vertical range */
379 ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
380 ok( ret, "GetScrollRange failed.\n");
381 /* now the range should be 0,100 in ALL cases */
382 ok( min == 0 && max == 100,
383 "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style);
384 /* See what is different now for GetScrollRange */
385 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
386 /* should succeed in ALL cases */
387 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
388 ret = GetScrollInfo( hwnd, SB_VERT, &si);
389 /* should succeed in ALL cases */
390 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
391 /* report the windows style */
392 winstyle = GetWindowLongA( hwnd, GWL_STYLE );
393 /* WS_HSCROLL added to the window style */
394 if( !(style & WS_HSCROLL))
395 {
396 if (bThemeActive || style != WS_VSCROLL)
397 todo_wine
398 ok( (winstyle & (WS_HSCROLL|WS_VSCROLL)) == ( style | WS_HSCROLL),
399 "unexpected style change %08x/%08x\n", winstyle, style);
400 else
401 ok( (winstyle & (WS_HSCROLL|WS_VSCROLL)) == style,
402 "unexpected style change %08x/%08x\n", winstyle, style);
403 }
404 /* Slightly change the test to use SetScrollInfo
405 * Start with a clean window */
406 DestroyWindow( hwnd);
407 hwnd = CreateWindowExA( 0, "static", "", WS_POPUP | style,
408 0, 0, 10, 10, 0, 0, 0, NULL);
409 assert( hwnd != 0);
410 /* set Horizontal position with SetScrollInfo */
411 si.nPos = 0;
412 si.nMin = 11;
413 si.nMax = 22;
414 si.fMask |= SIF_RANGE;
415 ret = SetScrollInfo( hwnd, SB_HORZ, &si, FALSE);
416 ok( ret, "SetScrollInfo failed. Style is %08x\n", style);
417 /* and request the Vertical range */
418 ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
419 ok( ret, "GetScrollRange failed.\n");
420 /* now the range should be 0,100 in ALL cases */
421 ok( min == 0 && max == 100,
422 "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style);
423 /* See what is different now for GetScrollRange */
424 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
425 /* should succeed in ALL cases */
426 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
427 ret = GetScrollInfo( hwnd, SB_VERT, &si);
428 /* should succeed in ALL cases */
429 ok( ret, "GetScrollInfo failed unexpectedly. Style is %08x\n", style);
430 /* also test if the window scroll bars are enabled */
431 ret = EnableScrollBar( hwnd, SB_VERT, ESB_ENABLE_BOTH);
432 ok( !ret, "Vertical window scroll bar was not enabled\n");
433 ret = EnableScrollBar( hwnd, SB_HORZ, ESB_ENABLE_BOTH);
434 ok( !ret, "Horizontal window scroll bar was not enabled\n");
435 DestroyWindow( hwnd);
436 /* finally, check if adding a WS_[HV]SCROLL style of a window makes the scroll info
437 * available */
438 if( style & (WS_HSCROLL | WS_VSCROLL)) return;/* only test if not yet set */
439 /* Start with a clean window */
440 DestroyWindow( hwnd);
441 hwnd = CreateWindowExA( 0, "static", "", WS_POPUP ,
442 0, 0, 10, 10, 0, 0, 0, NULL);
443 assert( hwnd != 0);
444 ret = GetScrollInfo( hwnd, SB_VERT, &si);
445 /* should fail */
446 ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style);
447 /* add scroll styles */
448 winstyle = GetWindowLongA( hwnd, GWL_STYLE );
449 SetWindowLongW( hwnd, GWL_STYLE, winstyle | WS_VSCROLL | WS_HSCROLL);
450 ret = GetScrollInfo( hwnd, SB_VERT, &si);
451 /* should still fail */
452 ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style);
453 /* clean up */
454 DestroyWindow( hwnd);
455 }
456
457 static LRESULT CALLBACK scroll_init_proc(HWND hwnd, UINT msg,
458 WPARAM wparam, LPARAM lparam)
459 {
460 SCROLLINFO horz, vert;
461 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
462 BOOL h_ret, v_ret;
463
464 switch(msg)
465 {
466 case WM_NCCREATE:
467 return cs->lpCreateParams ? DefWindowProcA(hwnd, msg, wparam, lparam) :
468 TRUE;
469
470 case WM_CREATE:
471 horz.cbSize = sizeof horz;
472 horz.fMask = SIF_ALL;
473 horz.nMin = 0xdeadbeaf;
474 horz.nMax = 0xbaadc0de;
475 vert = horz;
476 h_ret = GetScrollInfo(hwnd, SB_HORZ, &horz);
477 v_ret = GetScrollInfo(hwnd, SB_VERT, &vert);
478
479 if(cs->lpCreateParams)
480 {
481 /* WM_NCCREATE was passed to DefWindowProc */
482 if(cs->style & (WS_VSCROLL | WS_HSCROLL))
483 {
484 ok(h_ret && v_ret, "GetScrollInfo() should return NON-zero "
485 "but got h_ret=%d v_ret=%d\n", h_ret, v_ret);
486 ok(vert.nMin == 0 && vert.nMax == 100,
487 "unexpected init values(SB_VERT): min=%d max=%d\n",
488 vert.nMin, vert.nMax);
489 ok(horz.nMin == 0 && horz.nMax == 100,
490 "unexpected init values(SB_HORZ): min=%d max=%d\n",
491 horz.nMin, horz.nMax);
492 }
493 else
494 {
495 ok(!h_ret && !v_ret, "GetScrollInfo() should return zeru, "
496 "but got h_ret=%d v_ret=%d\n", h_ret, v_ret);
497 ok(vert.nMin == 0xdeadbeaf && vert.nMax == 0xbaadc0de,
498 "unexpected initialization(SB_VERT): min=%d max=%d\n",
499 vert.nMin, vert.nMax);
500 ok(horz.nMin == 0xdeadbeaf && horz.nMax == 0xbaadc0de,
501 "unexpected initialization(SB_HORZ): min=%d max=%d\n",
502 horz.nMin, horz.nMax);
503 }
504 }
505 else
506 {
507 ok(!h_ret && !v_ret, "GetScrollInfo() should return zeru, "
508 "but got h_ret=%d v_ret=%d\n", h_ret, v_ret);
509 ok(horz.nMin == 0xdeadbeaf && horz.nMax == 0xbaadc0de &&
510 vert.nMin == 0xdeadbeaf && vert.nMax == 0xbaadc0de,
511 "unexpected initialization\n");
512 }
513 return FALSE; /* abort creation */
514
515 default:
516 /* need for WM_GETMINMAXINFO, which precedes WM_NCCREATE */
517 return 0;
518 }
519 }
520
521 static void scrollbar_test_init(void)
522 {
523 WNDCLASSEXA wc;
524 CHAR cls_name[] = "scroll_test_class";
525 LONG style[] = {WS_VSCROLL, WS_HSCROLL, WS_VSCROLL | WS_HSCROLL, 0};
526 int i;
527
528 memset( &wc, 0, sizeof wc );
529 wc.cbSize = sizeof wc;
530 wc.style = CS_VREDRAW | CS_HREDRAW;
531 wc.hInstance = GetModuleHandleA(0);
532 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
533 wc.hbrBackground = GetStockObject(WHITE_BRUSH);
534 wc.lpszClassName = cls_name;
535 wc.lpfnWndProc = scroll_init_proc;
536 RegisterClassExA(&wc);
537
538 for(i = 0; i < ARRAY_SIZE(style); i++)
539 {
540 /* need not to destroy these windows due creation abort */
541 CreateWindowExA(0, cls_name, NULL, style[i],
542 100, 100, 100, 100, NULL, NULL, wc.hInstance, (LPVOID)TRUE);
543 CreateWindowExA(0, cls_name, NULL, style[i],
544 100, 100, 100, 100, NULL, NULL, wc.hInstance, (LPVOID)FALSE);
545 }
546 UnregisterClassA(cls_name, wc.hInstance);
547 }
548
549 static void test_SetScrollInfo(void)
550 {
551 SCROLLINFO si;
552 HWND mainwnd;
553 BOOL ret;
554
555 mainwnd = create_main_test_wnd();
556
557 ret = IsWindowEnabled(hScroll);
558 ok(ret, "scroll bar disabled\n");
559
560 EnableScrollBar(hScroll, SB_CTL, ESB_DISABLE_BOTH);
561
562 ret = IsWindowEnabled(hScroll);
563 ok(!ret, "scroll bar enabled\n");
564
565 memset(&si, 0, sizeof(si));
566 si.cbSize = sizeof(si);
567 si.fMask = 0xf;
568 ret = GetScrollInfo(hScroll, SB_CTL, &si);
569 ok(ret, "got %d\n", ret);
570
571 /* SetScrollInfo */
572 memset(&si, 0, sizeof(si));
573 si.cbSize = sizeof(si);
574 ret = IsWindowEnabled(hScroll);
575 ok(!ret, "scroll bar enabled\n");
576 si.fMask = SIF_POS|SIF_RANGE|SIF_PAGE|SIF_DISABLENOSCROLL;
577 si.nMax = 100;
578 si.nMin = 10;
579 si.nPos = 0;
580 si.nPage = 100;
581 SetScrollInfo(hScroll, SB_CTL, &si, TRUE);
582 ret = IsWindowEnabled(hScroll);
583 ok(!ret, "scroll bar enabled\n");
584
585 si.fMask = 0xf;
586 ret = GetScrollInfo(hScroll, SB_CTL, &si);
587 ok(ret, "got %d\n", ret);
588
589 EnableScrollBar(hScroll, SB_CTL, ESB_ENABLE_BOTH);
590 ok(IsWindowEnabled(hScroll), "expected enabled scrollbar\n");
591
592 si.fMask = SIF_POS|SIF_RANGE|SIF_PAGE|SIF_DISABLENOSCROLL;
593 si.nMax = 10;
594 si.nMin = 100;
595 si.nPos = 0;
596 si.nPage = 100;
597 SetScrollInfo(hScroll, SB_CTL, &si, TRUE);
598 ret = IsWindowEnabled(hScroll);
599 ok(ret, "scroll bar disabled\n");
600
601 DestroyWindow(hScroll);
602 DestroyWindow(mainwnd);
603 }
604
605 static WNDPROC scrollbar_wndproc;
606
607 static SCROLLINFO set_scrollinfo;
608
609 static LRESULT CALLBACK subclass_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
610 {
611 if (msg == WM_CREATE && ((CREATESTRUCTA*)lparam)->lpCreateParams)
612 return DefWindowProcA(hwnd, msg, wparam, lparam);
613
614 if (msg == SBM_SETSCROLLINFO)
615 set_scrollinfo = *(SCROLLINFO*)lparam;
616
617 return CallWindowProcA(scrollbar_wndproc, hwnd, msg, wparam, lparam);
618 }
619
620 static void test_subclass(void)
621 {
622 SCROLLBARINFO scroll_info;
623 WNDCLASSEXA class_info;
624 WNDCLASSA wc;
625 LRESULT res;
626 HWND hwnd;
627 BOOL r;
628
629 r = GetClassInfoExA(GetModuleHandleA(NULL), "SCROLLBAR", &class_info);
630 ok(r, "GetClassInfoEx failed: %u\n", GetLastError());
631 scrollbar_wndproc = class_info.lpfnWndProc;
632
633 memset(&wc, 0, sizeof(wc));
634 wc.cbWndExtra = class_info.cbWndExtra + 3; /* more space than needed works */
635 wc.hInstance = GetModuleHandleA(NULL);
636 wc.lpszClassName = "MyTestSubclass";
637 wc.lpfnWndProc = subclass_proc;
638 r = RegisterClassA(&wc);
639 ok(r, "RegisterClass failed: %u\n", GetLastError());
640
641 hwnd = CreateWindowExA( 0, "MyTestSubclass", "Scroll", WS_OVERLAPPEDWINDOW,
642 CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 );
643 ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
644
645 r = SetScrollRange(hwnd, SB_CTL, 0, 100, TRUE);
646 ok(r, "SetScrollRange failed: %u\n", GetLastError());
647
648 res = SetScrollPos(hwnd, SB_CTL, 2, FALSE);
649 ok(!res, "SetScrollPos returned %lu\n", res);
650
651 memset(&set_scrollinfo, 0xcc, sizeof(set_scrollinfo));
652 res = SetScrollPos(hwnd, SB_CTL, 1, FALSE);
653 ok(res == 2, "SetScrollPos returned %lu\n", res);
654 ok(set_scrollinfo.cbSize == sizeof(SCROLLINFO), "cbSize = %u\n", set_scrollinfo.cbSize);
655 todo_wine
656 ok(set_scrollinfo.fMask == (0x1000 | SIF_POS), "fMask = %x\n", set_scrollinfo.fMask);
657 ok(set_scrollinfo.nPos == 1, "nPos = %x\n", set_scrollinfo.nPos);
658
659 memset(&scroll_info, 0xcc, sizeof(scroll_info));
660 scroll_info.cbSize = sizeof(scroll_info);
661 res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
662 ok(res == 1, "SBM_GETSCROLLBARINFO returned %lu\n", res);
663
664 DestroyWindow(hwnd);
665
666 /* if we skip calling wndproc for WM_CREATE, window is not considered a scrollbar */
667 hwnd = CreateWindowExA( 0, "MyTestSubclass", "Scroll", WS_OVERLAPPEDWINDOW,
668 CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), (void *)1 );
669 ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
670
671 memset(&scroll_info, 0xcc, sizeof(scroll_info));
672 scroll_info.cbSize = sizeof(scroll_info);
673 res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
674 ok(!res, "SBM_GETSCROLLBARINFO returned %lu\n", res);
675
676 DestroyWindow(hwnd);
677
678 /* not enough space in extra data */
679 wc.cbWndExtra = class_info.cbWndExtra - 1;
680 wc.lpszClassName = "MyTestSubclass2";
681 r = RegisterClassA(&wc);
682 ok(r, "RegisterClass failed: %u\n", GetLastError());
683
684 hwnd = CreateWindowExA( 0, "MyTestSubclass2", "Scroll", WS_OVERLAPPEDWINDOW,
685 CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0 );
686 ok(hwnd != NULL, "Failed to create window: %u\n", GetLastError());
687
688 memset(&scroll_info, 0xcc, sizeof(scroll_info));
689 scroll_info.cbSize = sizeof(scroll_info);
690 res = SendMessageA(hwnd, SBM_GETSCROLLBARINFO, 0, (LPARAM)&scroll_info);
691 ok(!res, "SBM_GETSCROLLBARINFO returned %lu\n", res);
692
693 memset(&set_scrollinfo, 0xcc, sizeof(set_scrollinfo));
694 res = SetScrollPos(hwnd, SB_CTL, 1, FALSE);
695 ok(res == 0, "SetScrollPos returned %lu\n", res);
696 ok(set_scrollinfo.cbSize == sizeof(SCROLLINFO), "cbSize = %u\n", set_scrollinfo.cbSize);
697 todo_wine
698 ok(set_scrollinfo.fMask == (0x1000 | SIF_POS), "fMask = %x\n", set_scrollinfo.fMask);
699 ok(set_scrollinfo.nPos == 1, "nPos = %x\n", set_scrollinfo.nPos);
700
701 DestroyWindow(hwnd);
702 }
703
704 START_TEST ( scroll )
705 {
706 WNDCLASSA wc;
707 HMODULE hUxtheme;
708 BOOL (WINAPI * pIsThemeActive)(VOID);
709
710 wc.style = CS_HREDRAW | CS_VREDRAW;
711 wc.cbClsExtra = 0;
712 wc.cbWndExtra = 0;
713 wc.hInstance = GetModuleHandleA(NULL);
714 wc.hIcon = NULL;
715 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_IBEAM);
716 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
717 wc.lpszMenuName = NULL;
718 wc.lpszClassName = "MyTestWnd";
719 wc.lpfnWndProc = MyWndProc;
720 RegisterClassA(&wc);
721
722 test_EnableScrollBar();
723 test_SetScrollPos();
724 test_ShowScrollBar();
725 test_GetScrollBarInfo();
726 scrollbar_test_track();
727 test_SetScrollInfo();
728 test_subclass();
729
730 /* Some test results vary depending of theming being active or not */
731 hUxtheme = LoadLibraryA("uxtheme.dll");
732 if (hUxtheme)
733 {
734 pIsThemeActive = (void*)GetProcAddress(hUxtheme, "IsThemeActive");
735 if (pIsThemeActive)
736 bThemeActive = pIsThemeActive();
737 FreeLibrary(hUxtheme);
738 }
739
740 scrollbar_test_default( 0);
741 scrollbar_test_default( WS_HSCROLL);
742 scrollbar_test_default( WS_VSCROLL);
743 scrollbar_test_default( WS_HSCROLL | WS_VSCROLL);
744
745 scrollbar_test_init();
746 }