comctl32: Added header message sequence test cases.
[wine] / dlls / comctl32 / tests / progress.c
1 /* Unit tests for the progress bar control.
2  *
3  * Copyright 2005 Michael Kaufmann
4  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <assert.h>
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27 #include "commctrl.h" 
28
29 #include "wine/test.h"
30
31
32 static HWND hProgressParentWnd, hProgressWnd;
33 static const char progressTestClass[] = "ProgressBarTestClass";
34
35
36 static LRESULT CALLBACK ProgressTestWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
37 {
38     switch(msg) {
39
40     case WM_DESTROY:
41         PostQuitMessage(0);
42         break;
43   
44     default:
45         return DefWindowProcA(hWnd, msg, wParam, lParam);
46     }
47     
48     return 0L;
49 }
50
51 static WNDPROC progress_wndproc;
52 static BOOL erased;
53 static RECT last_paint_rect;
54
55 static LRESULT CALLBACK ProgressSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
56 {
57     if (msg == WM_PAINT)
58     {
59         GetUpdateRect(hWnd, &last_paint_rect, FALSE);
60     }
61     else if (msg == WM_ERASEBKGND)
62     {
63         erased = TRUE;
64     }
65     return CallWindowProc(progress_wndproc, hWnd, msg, wParam, lParam);
66 }
67
68
69 static void update_window(HWND hWnd)
70 {
71     UpdateWindow(hWnd);
72     ok(!GetUpdateRect(hWnd, NULL, FALSE), "GetUpdateRect must return zero after UpdateWindow\n");    
73 }
74
75
76 static void init(void)
77 {
78     WNDCLASSA wc;
79     INITCOMMONCONTROLSEX icex;
80     RECT rect;
81     
82     icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
83     icex.dwICC   = ICC_PROGRESS_CLASS;
84     InitCommonControlsEx(&icex);
85   
86     wc.style = CS_HREDRAW | CS_VREDRAW;
87     wc.cbClsExtra = 0;
88     wc.cbWndExtra = 0;
89     wc.hInstance = GetModuleHandleA(NULL);
90     wc.hIcon = NULL;
91     wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_ARROW));
92     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
93     wc.lpszMenuName = NULL;
94     wc.lpszClassName = progressTestClass;
95     wc.lpfnWndProc = ProgressTestWndProc;
96     RegisterClassA(&wc);
97     
98     rect.left = 0;
99     rect.top = 0;
100     rect.right = 400;
101     rect.bottom = 20;
102     assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE));
103     
104     hProgressParentWnd = CreateWindowExA(0, progressTestClass, "Progress Bar Test", WS_OVERLAPPEDWINDOW,
105       CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, GetModuleHandleA(NULL), 0);
106     assert(hProgressParentWnd != NULL);
107
108     GetClientRect(hProgressParentWnd, &rect);
109     hProgressWnd = CreateWindowEx(0, PROGRESS_CLASS, "", WS_CHILD | WS_VISIBLE,
110       0, 0, rect.right, rect.bottom, hProgressParentWnd, NULL, GetModuleHandleA(NULL), 0);
111     assert(hProgressWnd != NULL);
112     progress_wndproc = (WNDPROC)SetWindowLongPtr(hProgressWnd, GWLP_WNDPROC, (LPARAM)ProgressSubclassProc);
113     
114     ShowWindow(hProgressParentWnd, SW_SHOWNORMAL);
115     ok(GetUpdateRect(hProgressParentWnd, NULL, FALSE), "GetUpdateRect: There should be a region that needs to be updated\n");
116     update_window(hProgressParentWnd);    
117 }
118
119
120 static void cleanup(void)
121 {
122     MSG msg;
123     
124     PostMessageA(hProgressParentWnd, WM_CLOSE, 0, 0);
125     while (GetMessageA(&msg,0,0,0)) {
126         TranslateMessage(&msg);
127         DispatchMessageA(&msg);
128     }
129     
130     UnregisterClassA(progressTestClass, GetModuleHandleA(NULL));
131 }
132
133
134 /*
135  * Tests if a progress bar repaints itself immediately when it receives
136  * some specific messages.
137  */
138 static void test_redraw(void)
139 {
140     RECT client_rect;
141
142     SendMessageA(hProgressWnd, PBM_SETRANGE, 0, MAKELPARAM(0, 100));
143     SendMessageA(hProgressWnd, PBM_SETPOS, 10, 0);
144     SendMessageA(hProgressWnd, PBM_SETSTEP, 20, 0);
145     update_window(hProgressWnd);
146
147     /* PBM_SETPOS */
148     ok(SendMessageA(hProgressWnd, PBM_SETPOS, 50, 0) == 10, "PBM_SETPOS must return the previous position\n");
149     ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
150     
151     /* PBM_DELTAPOS */
152     ok(SendMessageA(hProgressWnd, PBM_DELTAPOS, 15, 0) == 50, "PBM_DELTAPOS must return the previous position\n");
153     ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_DELTAPOS: The progress bar should be redrawn immediately\n");
154     
155     /* PBM_SETPOS */
156     ok(SendMessageA(hProgressWnd, PBM_SETPOS, 80, 0) == 65, "PBM_SETPOS must return the previous position\n");
157     ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_SETPOS: The progress bar should be redrawn immediately\n");
158     
159     /* PBM_STEPIT */
160     ok(SendMessageA(hProgressWnd, PBM_STEPIT, 0, 0) == 80, "PBM_STEPIT must return the previous position\n");
161     ok(!GetUpdateRect(hProgressWnd, NULL, FALSE), "PBM_STEPIT: The progress bar should be redrawn immediately\n");
162     ok((UINT)SendMessageA(hProgressWnd, PBM_GETPOS, 0, 0) == 100, "PBM_GETPOS returned a wrong position\n");
163     
164     /* PBM_SETRANGE and PBM_SETRANGE32:
165     Usually the progress bar doesn't repaint itself immediately. If the
166     position is not in the new range, it does.
167     Don't test this, it may change in future Windows versions. */
168
169     SendMessage(hProgressWnd, PBM_SETPOS, 0, 0);
170     update_window(hProgressWnd);
171
172     /* increase to 10 - no background erase required */
173     erased = FALSE;
174     SetRectEmpty(&last_paint_rect);
175     SendMessage(hProgressWnd, PBM_SETPOS, 10, 0);
176     GetClientRect(hProgressWnd, &client_rect);
177     ok(EqualRect(&last_paint_rect, &client_rect),
178        "last_paint_rect was { %d, %d, %d, %d } instead of { %d, %d, %d, %d }\n",
179        last_paint_rect.left, last_paint_rect.top, last_paint_rect.right, last_paint_rect.bottom,
180        client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
181     update_window(hProgressWnd);
182     ok(!erased, "Progress bar shouldn't have erased the background\n");
183
184     /* decrease to 0 - background erase will be required */
185     erased = FALSE;
186     SetRectEmpty(&last_paint_rect);
187     SendMessage(hProgressWnd, PBM_SETPOS, 0, 0);
188     GetClientRect(hProgressWnd, &client_rect);
189     ok(EqualRect(&last_paint_rect, &client_rect),
190        "last_paint_rect was { %d, %d, %d, %d } instead of { %d, %d, %d, %d }\n",
191        last_paint_rect.left, last_paint_rect.top, last_paint_rect.right, last_paint_rect.bottom,
192        client_rect.left, client_rect.top, client_rect.right, client_rect.bottom);
193     update_window(hProgressWnd);
194     ok(erased, "Progress bar should have erased the background\n");
195 }
196
197
198 START_TEST(progress)
199 {
200     init();
201     
202     test_redraw();
203     
204     cleanup();
205 }