1 /* Unit tests for the progress bar control.
3 * Copyright 2005 Michael Kaufmann
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include "wine/test.h"
32 static HWND hProgressParentWnd
;
33 static const char progressTestClass
[] = "ProgressBarTestClass";
34 static BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
36 static HWND
create_progress(DWORD style
)
38 return CreateWindowExA(0, PROGRESS_CLASSA
, "", WS_VISIBLE
| style
,
39 0, 0, 100, 20, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
42 /* try to make sure pending X events have been processed before continuing */
43 static void flush_events(void)
47 DWORD time
= GetTickCount() + diff
;
51 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min(10,diff
), QS_ALLINPUT
) == WAIT_TIMEOUT
) break;
52 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
53 diff
= time
- GetTickCount();
57 static LRESULT CALLBACK
progress_test_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
66 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
72 static WNDPROC progress_wndproc
;
74 static RECT last_paint_rect
;
76 static LRESULT CALLBACK
progress_subclass_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
80 GetUpdateRect(hWnd
, &last_paint_rect
, FALSE
);
82 else if (msg
== WM_ERASEBKGND
)
86 return CallWindowProcA(progress_wndproc
, hWnd
, msg
, wParam
, lParam
);
90 static void update_window(HWND hWnd
)
93 ok(!GetUpdateRect(hWnd
, NULL
, FALSE
), "GetUpdateRect must return zero after UpdateWindow\n");
97 static void init(void)
103 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
106 wc
.hInstance
= GetModuleHandleA(NULL
);
108 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
109 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
110 wc
.lpszMenuName
= NULL
;
111 wc
.lpszClassName
= progressTestClass
;
112 wc
.lpfnWndProc
= progress_test_wnd_proc
;
115 SetRect(&rect
, 0, 0, 400, 20);
116 ret
= AdjustWindowRect(&rect
, WS_OVERLAPPEDWINDOW
, FALSE
);
117 ok(ret
, "got %d\n", ret
);
119 hProgressParentWnd
= CreateWindowExA(0, progressTestClass
, "Progress Bar Test", WS_OVERLAPPEDWINDOW
,
120 CW_USEDEFAULT
, CW_USEDEFAULT
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
121 ok(hProgressParentWnd
!= NULL
, "failed to create parent wnd\n");
125 static void cleanup(void)
129 PostMessageA(hProgressParentWnd
, WM_CLOSE
, 0, 0);
130 while (GetMessageA(&msg
,0,0,0)) {
131 TranslateMessage(&msg
);
132 DispatchMessageA(&msg
);
135 UnregisterClassA(progressTestClass
, GetModuleHandleA(NULL
));
140 * Tests if a progress bar repaints itself immediately when it receives
141 * some specific messages.
143 static void test_redraw(void)
145 RECT client_rect
, rect
;
149 GetClientRect(hProgressParentWnd
, &rect
);
150 hProgressWnd
= CreateWindowExA(0, PROGRESS_CLASSA
, "", WS_CHILD
| WS_VISIBLE
,
151 0, 0, rect
.right
, rect
.bottom
, hProgressParentWnd
, NULL
, GetModuleHandleA(NULL
), 0);
152 ok(hProgressWnd
!= NULL
, "Failed to create progress bar.\n");
153 progress_wndproc
= (WNDPROC
)SetWindowLongPtrA(hProgressWnd
, GWLP_WNDPROC
, (LPARAM
)progress_subclass_proc
);
155 ShowWindow(hProgressParentWnd
, SW_SHOWNORMAL
);
156 ok(GetUpdateRect(hProgressParentWnd
, NULL
, FALSE
), "GetUpdateRect: There should be a region that needs to be updated\n");
158 update_window(hProgressParentWnd
);
160 SendMessageA(hProgressWnd
, PBM_SETRANGE
, 0, MAKELPARAM(0, 100));
161 SendMessageA(hProgressWnd
, PBM_SETPOS
, 10, 0);
162 SendMessageA(hProgressWnd
, PBM_SETSTEP
, 20, 0);
163 update_window(hProgressWnd
);
166 ok(SendMessageA(hProgressWnd
, PBM_SETPOS
, 50, 0) == 10, "PBM_SETPOS must return the previous position\n");
167 ok(!GetUpdateRect(hProgressWnd
, NULL
, FALSE
), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
170 ok(SendMessageA(hProgressWnd
, PBM_DELTAPOS
, 15, 0) == 50, "PBM_DELTAPOS must return the previous position\n");
171 ok(!GetUpdateRect(hProgressWnd
, NULL
, FALSE
), "PBM_DELTAPOS: The progress bar should be redrawn immediately\n");
174 ok(SendMessageA(hProgressWnd
, PBM_SETPOS
, 80, 0) == 65, "PBM_SETPOS must return the previous position\n");
175 ok(!GetUpdateRect(hProgressWnd
, NULL
, FALSE
), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
178 ok(SendMessageA(hProgressWnd
, PBM_STEPIT
, 0, 0) == 80, "PBM_STEPIT must return the previous position\n");
179 ok(!GetUpdateRect(hProgressWnd
, NULL
, FALSE
), "PBM_STEPIT: The progress bar should be redrawn immediately\n");
180 ret
= SendMessageA(hProgressWnd
, PBM_GETPOS
, 0, 0);
182 win_skip("PBM_GETPOS needs comctl32 > 4.70\n");
184 ok(ret
== 100, "PBM_GETPOS returned a wrong position : %d\n", (UINT
)ret
);
186 /* PBM_SETRANGE and PBM_SETRANGE32:
187 Usually the progress bar doesn't repaint itself immediately. If the
188 position is not in the new range, it does.
189 Don't test this, it may change in future Windows versions. */
191 SendMessageA(hProgressWnd
, PBM_SETPOS
, 0, 0);
192 update_window(hProgressWnd
);
194 /* increase to 10 - no background erase required */
196 SetRectEmpty(&last_paint_rect
);
197 SendMessageA(hProgressWnd
, PBM_SETPOS
, 10, 0);
198 GetClientRect(hProgressWnd
, &client_rect
);
199 ok(EqualRect(&last_paint_rect
, &client_rect
), "last_paint_rect was %s instead of %s\n",
200 wine_dbgstr_rect(&last_paint_rect
), wine_dbgstr_rect(&client_rect
));
201 update_window(hProgressWnd
);
202 ok(!erased
, "Progress bar shouldn't have erased the background\n");
204 /* decrease to 0 - background erase will be required */
206 SetRectEmpty(&last_paint_rect
);
207 SendMessageA(hProgressWnd
, PBM_SETPOS
, 0, 0);
208 GetClientRect(hProgressWnd
, &client_rect
);
209 ok(EqualRect(&last_paint_rect
, &client_rect
), "last_paint_rect was %s instead of %s\n",
210 wine_dbgstr_rect(&last_paint_rect
), wine_dbgstr_rect(&client_rect
));
211 update_window(hProgressWnd
);
212 ok(erased
, "Progress bar should have erased the background\n");
214 DestroyWindow(hProgressWnd
);
217 static void test_setcolors(void)
222 progress
= create_progress(PBS_SMOOTH
);
224 clr
= SendMessageA(progress
, PBM_SETBARCOLOR
, 0, 0);
225 ok(clr
== CLR_DEFAULT
, "got %lx\n", clr
);
227 clr
= SendMessageA(progress
, PBM_SETBARCOLOR
, 0, RGB(0, 255, 0));
228 ok(clr
== 0, "got %lx\n", clr
);
230 clr
= SendMessageA(progress
, PBM_SETBARCOLOR
, 0, CLR_DEFAULT
);
231 ok(clr
== RGB(0, 255, 0), "got %lx\n", clr
);
233 clr
= SendMessageA(progress
, PBM_SETBKCOLOR
, 0, 0);
234 ok(clr
== CLR_DEFAULT
, "got %lx\n", clr
);
236 clr
= SendMessageA(progress
, PBM_SETBKCOLOR
, 0, RGB(255, 0, 0));
237 ok(clr
== 0, "got %lx\n", clr
);
239 clr
= SendMessageA(progress
, PBM_SETBKCOLOR
, 0, CLR_DEFAULT
);
240 ok(clr
== RGB(255, 0, 0), "got %lx\n", clr
);
242 DestroyWindow(progress
);
245 static void test_PBM_STEPIT(void)
268 for (i
= 0; i
< ARRAY_SIZE(stepit_tests
); i
++)
270 struct stepit_test
*test
= &stepit_tests
[i
];
274 progress
= create_progress(0);
276 ret
= SendMessageA(progress
, PBM_SETRANGE32
, test
->min
, test
->max
);
277 ok(ret
!= 0, "Unexpected return value.\n");
279 SendMessageA(progress
, PBM_GETRANGE
, 0, (LPARAM
)&range
);
280 ok(range
.iLow
== test
->min
&& range
.iHigh
== test
->max
, "Unexpected range.\n");
282 SendMessageA(progress
, PBM_SETPOS
, test
->min
, 0);
283 SendMessageA(progress
, PBM_SETSTEP
, test
->step
, 0);
285 for (j
= 0; j
< test
->max
; j
++)
287 int pos
= SendMessageA(progress
, PBM_GETPOS
, 0, 0);
291 if (test
->min
!= test
->max
)
294 pos
= (pos
- test
->min
) % (test
->max
- test
->min
) + test
->min
;
296 pos
= (pos
- test
->min
) % (test
->max
- test
->min
) + test
->max
;
301 SendMessageA(progress
, PBM_STEPIT
, 0, 0);
303 current
= SendMessageA(progress
, PBM_GETPOS
, 0, 0);
304 ok(current
== pos
, "%u: unexpected position %d, expected %d.\n", i
, current
, pos
);
307 DestroyWindow(progress
);
311 static void init_functions(void)
313 HMODULE hComCtl32
= LoadLibraryA("comctl32.dll");
315 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
316 X(InitCommonControlsEx
);
322 INITCOMMONCONTROLSEX iccex
;
323 ULONG_PTR ctx_cookie
;
328 iccex
.dwSize
= sizeof(iccex
);
329 iccex
.dwICC
= ICC_PROGRESS_CLASS
;
330 pInitCommonControlsEx(&iccex
);
338 if (!load_v6_module(&ctx_cookie
, &hCtx
))
344 unload_v6_module(ctx_cookie
, hCtx
);