mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / comctl32 / tests / progress.c
blob91ea6eec2a93e12c23efb8a7a4bc17713aabaf5f
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
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wingdi.h"
25 #include "winuser.h"
26 #include "commctrl.h"
28 #include "wine/test.h"
30 #include "v6util.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)
45 MSG msg;
46 int diff = 100;
47 DWORD time = GetTickCount() + diff;
49 while (diff > 0)
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)
59 switch(msg) {
61 case WM_DESTROY:
62 PostQuitMessage(0);
63 break;
65 default:
66 return DefWindowProcA(hWnd, msg, wParam, lParam);
69 return 0L;
72 static WNDPROC progress_wndproc;
73 static BOOL erased;
74 static RECT last_paint_rect;
76 static LRESULT CALLBACK progress_subclass_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
78 if (msg == WM_PAINT)
80 GetUpdateRect(hWnd, &last_paint_rect, FALSE);
82 else if (msg == WM_ERASEBKGND)
84 erased = TRUE;
86 return CallWindowProcA(progress_wndproc, hWnd, msg, wParam, lParam);
90 static void update_window(HWND hWnd)
92 UpdateWindow(hWnd);
93 ok(!GetUpdateRect(hWnd, NULL, FALSE), "GetUpdateRect must return zero after UpdateWindow\n");
97 static void init(void)
99 WNDCLASSA wc;
100 RECT rect;
101 BOOL ret;
103 wc.style = CS_HREDRAW | CS_VREDRAW;
104 wc.cbClsExtra = 0;
105 wc.cbWndExtra = 0;
106 wc.hInstance = GetModuleHandleA(NULL);
107 wc.hIcon = 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;
113 RegisterClassA(&wc);
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)
127 MSG msg;
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;
146 HWND hProgressWnd;
147 LRESULT ret;
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");
157 flush_events();
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);
165 /* PBM_SETPOS */
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");
169 /* PBM_DELTAPOS */
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");
173 /* PBM_SETPOS */
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");
177 /* PBM_STEPIT */
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);
181 if (ret == 0)
182 win_skip("PBM_GETPOS needs comctl32 > 4.70\n");
183 else
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 */
195 erased = FALSE;
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 */
205 erased = FALSE;
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)
219 HWND progress;
220 COLORREF clr;
222 progress = create_progress(PBS_SMOOTH);
224 clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, 0);
225 ok(clr == CLR_DEFAULT, "got %x\n", clr);
227 clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, RGB(0, 255, 0));
228 ok(clr == 0, "got %x\n", clr);
230 clr = SendMessageA(progress, PBM_SETBARCOLOR, 0, CLR_DEFAULT);
231 ok(clr == RGB(0, 255, 0), "got %x\n", clr);
233 clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, 0);
234 ok(clr == CLR_DEFAULT, "got %x\n", clr);
236 clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, RGB(255, 0, 0));
237 ok(clr == 0, "got %x\n", clr);
239 clr = SendMessageA(progress, PBM_SETBKCOLOR, 0, CLR_DEFAULT);
240 ok(clr == RGB(255, 0, 0), "got %x\n", clr);
242 DestroyWindow(progress);
245 static void test_PBM_STEPIT(void)
247 struct stepit_test
249 int min;
250 int max;
251 int step;
252 } stepit_tests[] =
254 { 3, 15, 5 },
255 { 3, 15, -5 },
256 { 3, 15, 50 },
257 { -15, 15, 5 },
258 { -3, -2, -5 },
259 { 0, 0, 1 },
260 { 5, 5, 1 },
261 { 0, 0, -1 },
262 { 5, 5, -1 },
263 { 10, 5, 2 },
265 HWND progress;
266 int i, j;
268 for (i = 0; i < ARRAY_SIZE(stepit_tests); i++)
270 struct stepit_test *test = &stepit_tests[i];
271 PBRANGE range;
272 LRESULT ret;
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);
288 int current;
290 pos += test->step;
291 if (test->min != test->max)
293 if (pos > test->max)
294 pos = (pos - test->min) % (test->max - test->min) + test->min;
295 if (pos < test->min)
296 pos = (pos - test->min) % (test->max - test->min) + test->max;
298 else
299 pos = test->min;
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);
317 #undef X
320 START_TEST(progress)
322 INITCOMMONCONTROLSEX iccex;
323 ULONG_PTR ctx_cookie;
324 HANDLE hCtx;
326 init_functions();
328 iccex.dwSize = sizeof(iccex);
329 iccex.dwICC = ICC_PROGRESS_CLASS;
330 pInitCommonControlsEx(&iccex);
332 init();
334 test_redraw();
335 test_setcolors();
336 test_PBM_STEPIT();
338 if (!load_v6_module(&ctx_cookie, &hCtx))
339 return;
341 test_setcolors();
342 test_PBM_STEPIT();
344 unload_v6_module(ctx_cookie, hCtx);
346 cleanup();