Release 0.9.39.
[wine/gsoc-2012-control.git] / dlls / comctl32 / tests / rebar.c
blobd715d33b4a252eb5ebed1d4dba64af8bf16641cd
1 /* Unit tests for rebar.
3 * Copyright 2007 Mikolaj Zalewski
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 <assert.h>
21 #include <stdarg.h>
23 #include <windows.h>
24 #include <commctrl.h>
25 #include <uxtheme.h>
27 #include "wine/test.h"
29 RECT height_change_notify_rect;
30 static HWND hMainWnd;
31 static HWND hRebar;
34 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
35 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
36 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
38 #define check_rect_no_top(name, val, exp) { \
39 ok((val.bottom - val.top == exp.bottom - exp.top) && \
40 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
41 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
44 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
46 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
48 static void rebuild_rebar(HWND *hRebar)
50 if (*hRebar)
51 DestroyWindow(*hRebar);
53 *hRebar = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
54 hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
55 SendMessageA(*hRebar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
58 static HWND build_toolbar(int nr, HWND hParent)
60 TBBUTTON btns[8];
61 HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
62 hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
63 int iBitmapId = 0;
64 int i;
66 ok(hToolbar != NULL, "Toolbar creation problem\n");
67 ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
68 ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
69 ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
71 for (i=0; i<5+nr; i++)
73 btns[i].iBitmap = i;
74 btns[i].idCommand = i;
75 btns[i].fsStyle = BTNS_BUTTON;
76 btns[i].fsState = TBSTATE_ENABLED;
77 btns[i].iString = 0;
80 switch (nr)
82 case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
83 case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
84 case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
86 ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGE failed\n");
87 ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
88 return hToolbar;
91 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
93 switch (msg)
95 case WM_NOTIFY:
97 NMHDR *lpnm = (NMHDR *)lParam;
98 if (lpnm->code == RBN_HEIGHTCHANGE)
99 GetClientRect(hRebar, &height_change_notify_rect);
101 break;
103 return DefWindowProcA(hWnd, msg, wParam, lParam);
106 #if 0 /* use this to generate more tests*/
108 static void dump_sizes(HWND hRebar)
110 SIZE sz;
111 RECT r;
112 int count;
113 int i, h;
115 GetClientRect(hRebar, &r);
116 count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
117 printf(" { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
118 SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
119 if (count == 0)
120 printf("0, ");
121 for (i = 0; i < count; i++) /* rows */
122 printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
123 printf("}, ");
125 count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
126 printf("%d, {", count);
127 if (count == 0)
128 printf("{{0, 0, 0, 0}, 0, 0},");
129 for (i=0; i<count; i++)
131 REBARBANDINFO rbi;
132 rbi.cbSize = sizeof(REBARBANDINFO);
133 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
134 ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
135 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
136 printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom,
137 rbi.fStyle, rbi.cx);
139 printf("\n }, }, \n");
142 #define check_sizes() dump_sizes(hRebar);
143 #define check_sizes_todo(todomask) dump_sizes(hRebar);
145 #else
147 typedef struct {
148 RECT rc;
149 DWORD fStyle;
150 INT cx;
151 } rbband_result_t;
153 typedef struct {
154 RECT rcClient;
155 int cyBarHeight;
156 int nRows;
157 int cyRowHeights[50];
158 int nBands;
159 rbband_result_t bands[50];
160 } rbsize_result_t;
162 rbsize_result_t rbsize_results[] = {
163 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
164 }, },
165 { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
166 { { 0, 0, 672, 4}, 0x00, 200},
167 }, },
168 { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
169 { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
170 }, },
171 { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
172 { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
173 { {400, 0, 672, 30}, 0x00, 200},
174 }, },
175 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
176 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
177 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
178 }, },
179 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
180 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
181 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
182 }, },
183 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
184 { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
185 { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
186 }, },
187 { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
188 { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
189 { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
190 { {202, 36, 672, 70}, 0x04, 66},
191 }, },
192 { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
193 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
194 { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
195 { {629, 0, 672, 34}, 0x04, 66},
196 }, },
197 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
198 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
199 { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
200 }, },
201 { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
202 { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
203 { {617, 0, 672, 34}, 0x04, 66},
204 }, },
205 { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
206 { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
207 }, },
208 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
209 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
210 { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
211 { { 0, 20, 672, 40}, 0x00, 200},
212 }, },
213 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
214 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
215 { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
216 { { 0, 20, 672, 40}, 0x00, 200},
217 }, },
218 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
219 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
220 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
221 { { 0, 20, 672, 40}, 0x00, 200},
222 }, },
223 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
224 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
225 { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
226 { { 0, 20, 672, 40}, 0x00, 200},
227 }, },
228 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
229 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
230 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
231 { { 0, 20, 672, 40}, 0x00, 200},
232 }, },
233 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
234 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
235 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
236 { { 0, 20, 672, 40}, 0x00, 200},
237 }, },
238 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
239 }, },
240 { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
241 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
242 { {180, 0, 672, 65}, 0x40, 90},
243 }, },
244 { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
245 }, },
246 { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
247 { { 0, 0, 226, 65}, 0x40, 90},
248 }, },
249 { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
250 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
251 }, },
252 { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
253 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
254 { {163, 0, 226, 65}, 0x40, 90},
255 }, },
258 static int rbsize_numtests = 0;
260 #define check_sizes_todo(todomask) { \
261 RECT rc; \
262 REBARBANDINFO rbi; \
263 int count, i/*, mask=(todomask)*/; \
264 rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
265 assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
266 GetClientRect(hRebar, &rc); \
267 check_rect("client", rc, res->rcClient); \
268 count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
269 compare(count, res->nRows, "%d"); \
270 for (i=0; i<min(count, res->nRows); i++) { \
271 int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
272 ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
274 count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
275 compare(count, res->nBands, "%d"); \
276 for (i=0; i<min(count, res->nBands); i++) { \
277 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_ITEMRECT\n"); \
278 if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
279 check_rect("band", rc, res->bands[i].rc); \
280 rbi.cbSize = sizeof(REBARBANDINFO); \
281 rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
282 ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
283 compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
284 compare(rbi.cx, res->bands[i].cx, "%d"); \
286 rbsize_numtests++; \
289 #define check_sizes() check_sizes_todo(0)
291 #endif
293 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
295 CHAR buffer[MAX_PATH];
296 REBARBANDINFO rbi;
298 if (lpszText != NULL)
299 strcpy(buffer, lpszText);
300 rbi.cbSize = sizeof(rbi);
301 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
302 rbi.cx = cx;
303 rbi.cxMinChild = cxMinChild;
304 rbi.cxIdeal = cxIdeal;
305 rbi.cyMinChild = 20;
306 rbi.hwndChild = build_toolbar(1, hRebar);
307 rbi.lpText = (lpszText ? buffer : NULL);
308 SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
311 static void layout_test(void)
313 HWND hRebar = NULL;
314 REBARBANDINFO rbi;
316 rebuild_rebar(&hRebar);
317 check_sizes();
318 rbi.cbSize = sizeof(rbi);
319 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
320 rbi.cx = 200;
321 rbi.cxMinChild = 100;
322 rbi.cyMinChild = 30;
323 rbi.hwndChild = NULL;
324 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
325 check_sizes();
327 rbi.fMask |= RBBIM_STYLE;
328 rbi.fStyle = RBBS_CHILDEDGE;
329 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
330 check_sizes();
332 rbi.fStyle = 0;
333 rbi.cx = 200;
334 rbi.cxMinChild = 30;
335 rbi.cyMinChild = 30;
336 rbi.hwndChild = build_toolbar(0, hRebar);
337 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
338 check_sizes();
340 rbi.fStyle = RBBS_CHILDEDGE;
341 rbi.cx = 68;
342 rbi.hwndChild = build_toolbar(0, hRebar);
343 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
344 check_sizes();
346 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
347 check_sizes(); /* a style change won't start a relayout */
348 rbi.fMask = RBBIM_SIZE;
349 rbi.cx = 66;
350 SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
351 check_sizes(); /* here it will be relayouted */
353 /* this will force a new row */
354 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
355 rbi.cx = 200;
356 rbi.cxMinChild = 400;
357 rbi.cyMinChild = 30;
358 rbi.hwndChild = build_toolbar(0, hRebar);
359 SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
360 check_sizes();
362 rbi.fMask = RBBIM_STYLE;
363 rbi.fStyle = RBBS_HIDDEN;
364 SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
365 check_sizes();
367 SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
368 check_sizes();
369 SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
370 check_sizes();
371 SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
372 check_sizes();
374 rebuild_rebar(&hRebar);
375 add_band_w(hRebar, "ABC", 70, 40, 100);
376 add_band_w(hRebar, NULL, 40, 70, 100);
377 add_band_w(hRebar, NULL, 170, 240, 100);
378 add_band_w(hRebar, "MMMMMMM", 60, 60, 100);
379 add_band_w(hRebar, NULL, 200, 200, 100);
380 check_sizes();
381 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
382 check_sizes();
383 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
384 check_sizes();
385 SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
386 check_sizes();
387 SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
388 check_sizes();
389 SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
390 check_sizes();
392 /* VARHEIGHT resizing test on a horizontal rebar */
393 rebuild_rebar(&hRebar);
394 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
395 check_sizes();
396 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
397 rbi.fStyle = RBBS_VARIABLEHEIGHT;
398 rbi.cxMinChild = 50;
399 rbi.cyMinChild = 10;
400 rbi.cyIntegral = 11;
401 rbi.cyChild = 70;
402 rbi.cyMaxChild = 200;
403 rbi.cx = 90;
404 rbi.hwndChild = build_toolbar(0, hRebar);
405 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
407 rbi.cyChild = 50;
408 rbi.hwndChild = build_toolbar(0, hRebar);
409 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
411 rbi.cyMinChild = 40;
412 rbi.cyChild = 50;
413 rbi.cyIntegral = 5;
414 rbi.hwndChild = build_toolbar(0, hRebar);
415 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
416 check_sizes();
418 /* VARHEIGHT resizing on a vertical rebar */
419 rebuild_rebar(&hRebar);
420 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
421 check_sizes();
422 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
423 rbi.fStyle = RBBS_VARIABLEHEIGHT;
424 rbi.cxMinChild = 50;
425 rbi.cyMinChild = 10;
426 rbi.cyIntegral = 11;
427 rbi.cyChild = 70;
428 rbi.cyMaxChild = 90;
429 rbi.cx = 90;
430 rbi.hwndChild = build_toolbar(0, hRebar);
431 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
432 check_sizes();
434 rbi.cyChild = 50;
435 rbi.hwndChild = build_toolbar(0, hRebar);
436 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
437 check_sizes();
439 rbi.cyMinChild = 40;
440 rbi.cyChild = 50;
441 rbi.cyIntegral = 5;
442 rbi.hwndChild = build_toolbar(0, hRebar);
443 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
444 check_sizes();
446 DestroyWindow(hRebar);
449 #if 0 /* use this to generate more tests */
451 static void dump_client(HWND hRebar)
453 RECT r;
454 BOOL notify;
455 GetWindowRect(hRebar, &r);
456 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
457 if (height_change_notify_rect.top != -1)
459 RECT rcClient;
460 GetClientRect(hRebar, &rcClient);
461 assert(EqualRect(&rcClient, &height_change_notify_rect));
462 notify = TRUE;
464 else
465 notify = FALSE;
466 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
467 notify ? "TRUE" : "FALSE");
468 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
471 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
472 #define check_client() dump_client(hRebar)
474 #else
476 typedef struct {
477 RECT rc;
478 INT iNumRows;
479 BOOL heightNotify;
480 } rbresize_test_result_t;
482 rbresize_test_result_t resize_results[] = {
483 /* style 00000001 */
484 {{0, 2, 672, 2}, 0, FALSE},
485 {{0, 2, 672, 22}, 1, TRUE},
486 {{0, 2, 672, 22}, 1, FALSE},
487 {{0, 2, 672, 22}, 1, FALSE},
488 {{0, 2, 672, 22}, 1, FALSE},
489 {{0, 2, 672, 22}, 0, FALSE},
490 /* style 00000041 */
491 {{0, 0, 672, 0}, 0, FALSE},
492 {{0, 0, 672, 20}, 1, TRUE},
493 {{0, 0, 672, 20}, 1, FALSE},
494 {{0, 0, 672, 20}, 1, FALSE},
495 {{0, 0, 672, 20}, 1, FALSE},
496 {{0, 0, 672, 20}, 0, FALSE},
497 /* style 00000003 */
498 {{0, 226, 672, 226}, 0, FALSE},
499 {{0, 206, 672, 226}, 1, TRUE},
500 {{0, 206, 672, 226}, 1, FALSE},
501 {{0, 206, 672, 226}, 1, FALSE},
502 {{0, 206, 672, 226}, 1, FALSE},
503 {{0, 206, 672, 226}, 0, FALSE},
504 /* style 00000043 */
505 {{0, 226, 672, 226}, 0, FALSE},
506 {{0, 206, 672, 226}, 1, TRUE},
507 {{0, 206, 672, 226}, 1, FALSE},
508 {{0, 206, 672, 226}, 1, FALSE},
509 {{0, 206, 672, 226}, 1, FALSE},
510 {{0, 206, 672, 226}, 0, FALSE},
511 /* style 00000080 */
512 {{2, 0, 2, 226}, 0, FALSE},
513 {{2, 0, 22, 226}, 1, TRUE},
514 {{2, 0, 22, 226}, 1, FALSE},
515 {{2, 0, 22, 226}, 1, FALSE},
516 {{2, 0, 22, 226}, 1, FALSE},
517 {{2, 0, 22, 226}, 0, FALSE},
518 /* style 00000083 */
519 {{672, 0, 672, 226}, 0, FALSE},
520 {{652, 0, 672, 226}, 1, TRUE},
521 {{652, 0, 672, 226}, 1, FALSE},
522 {{652, 0, 672, 226}, 1, FALSE},
523 {{652, 0, 672, 226}, 1, FALSE},
524 {{652, 0, 672, 226}, 0, FALSE},
525 /* style 00000008 */
526 {{10, 11, 510, 11}, 0, FALSE},
527 {{10, 15, 510, 35}, 1, TRUE},
528 {{10, 17, 510, 37}, 1, FALSE},
529 {{10, 14, 110, 54}, 2, TRUE},
530 {{0, 4, 0, 44}, 2, FALSE},
531 {{0, 6, 0, 46}, 2, FALSE},
532 {{0, 8, 0, 48}, 2, FALSE},
533 {{0, 12, 0, 32}, 1, TRUE},
534 {{0, 4, 100, 24}, 0, FALSE},
535 /* style 00000048 */
536 {{10, 5, 510, 5}, 0, FALSE},
537 {{10, 5, 510, 25}, 1, TRUE},
538 {{10, 5, 510, 25}, 1, FALSE},
539 {{10, 10, 110, 50}, 2, TRUE},
540 {{0, 0, 0, 40}, 2, FALSE},
541 {{0, 0, 0, 40}, 2, FALSE},
542 {{0, 0, 0, 40}, 2, FALSE},
543 {{0, 0, 0, 20}, 1, TRUE},
544 {{0, 0, 100, 20}, 0, FALSE},
545 /* style 00000004 */
546 {{10, 5, 510, 20}, 0, FALSE},
547 {{10, 5, 510, 20}, 1, TRUE},
548 {{10, 10, 110, 110}, 2, TRUE},
549 {{0, 0, 0, 0}, 2, FALSE},
550 {{0, 0, 0, 0}, 2, FALSE},
551 {{0, 0, 0, 0}, 2, FALSE},
552 {{0, 0, 0, 0}, 1, TRUE},
553 {{0, 0, 100, 100}, 0, FALSE},
554 /* style 00000002 */
555 {{0, 5, 672, 5}, 0, FALSE},
556 {{0, 5, 672, 25}, 1, TRUE},
557 {{0, 10, 672, 30}, 1, FALSE},
558 {{0, 0, 672, 20}, 1, FALSE},
559 {{0, 0, 672, 20}, 1, FALSE},
560 {{0, 0, 672, 20}, 0, FALSE},
561 /* style 00000082 */
562 {{10, 0, 10, 226}, 0, FALSE},
563 {{10, 0, 30, 226}, 1, TRUE},
564 {{10, 0, 30, 226}, 1, FALSE},
565 {{0, 0, 20, 226}, 1, FALSE},
566 {{0, 0, 20, 226}, 1, FALSE},
567 {{0, 0, 20, 226}, 0, FALSE},
568 /* style 00800001 */
569 {{-2, 0, 674, 4}, 0, FALSE},
570 {{-2, 0, 674, 24}, 1, TRUE},
571 {{-2, 0, 674, 24}, 1, FALSE},
572 {{-2, 0, 674, 24}, 1, FALSE},
573 {{-2, 0, 674, 24}, 1, FALSE},
574 {{-2, 0, 674, 24}, 0, FALSE},
575 /* style 00800048 */
576 {{10, 5, 510, 9}, 0, FALSE},
577 {{10, 5, 510, 29}, 1, TRUE},
578 {{10, 5, 510, 29}, 1, FALSE},
579 {{10, 10, 110, 54}, 2, TRUE},
580 {{0, 0, 0, 44}, 2, FALSE},
581 {{0, 0, 0, 44}, 2, FALSE},
582 {{0, 0, 0, 44}, 2, FALSE},
583 {{0, 0, 0, 24}, 1, TRUE},
584 {{0, 0, 100, 24}, 0, FALSE},
585 /* style 00800004 */
586 {{10, 5, 510, 20}, 0, FALSE},
587 {{10, 5, 510, 20}, 1, TRUE},
588 {{10, 10, 110, 110}, 2, TRUE},
589 {{0, 0, 0, 0}, 2, FALSE},
590 {{0, 0, 0, 0}, 2, FALSE},
591 {{0, 0, 0, 0}, 2, FALSE},
592 {{0, 0, 0, 0}, 1, TRUE},
593 {{0, 0, 100, 100}, 0, FALSE},
594 /* style 00800002 */
595 {{-2, 5, 674, 9}, 0, FALSE},
596 {{-2, 5, 674, 29}, 1, TRUE},
597 {{-2, 10, 674, 34}, 1, FALSE},
598 {{-2, 0, 674, 24}, 1, FALSE},
599 {{-2, 0, 674, 24}, 1, FALSE},
600 {{-2, 0, 674, 24}, 0, FALSE},
603 static int resize_numtests = 0;
605 #define comment(fmt, arg1)
606 #define check_client() { \
607 RECT r; \
608 rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
609 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
610 GetWindowRect(hRebar, &r); \
611 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
612 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
613 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
614 } else { \
615 check_rect("client", r, res->rc); \
617 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
618 if (res->heightNotify) { \
619 RECT rcClient; \
620 GetClientRect(hRebar, &rcClient); \
621 check_rect("notify", height_change_notify_rect, rcClient); \
622 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
623 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
626 #endif
628 static void resize_test(void)
630 DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
631 CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
632 CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
633 CCS_NOMOVEY | WS_BORDER};
635 const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
636 int i;
638 for (i = 0; i < styles_count; i++)
640 comment("style %08x", dwStyles[i]);
641 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
642 hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
643 check_client();
644 add_band_w(hRebar, NULL, 70, 100, 0);
645 if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
646 check_client();
647 add_band_w(hRebar, NULL, 70, 100, 0);
648 check_client();
649 MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
650 check_client();
651 MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
652 check_client();
653 /* try to fool the rebar by sending invalid width/height - won't work */
654 if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
656 WINDOWPOS pos;
657 pos.hwnd = hRebar;
658 pos.hwndInsertAfter = NULL;
659 pos.cx = 500;
660 pos.cy = 500;
661 pos.x = 10;
662 pos.y = 10;
663 pos.flags = 0;
664 SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
665 SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
666 check_client();
667 SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
668 check_client();
670 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
671 check_client();
672 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
673 MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
674 check_client();
675 DestroyWindow(hRebar);
679 static void expect_band_content(UINT uBand, UINT fStyle, COLORREF clrFore,
680 COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
681 UINT cxMinChild, UINT cyMinChild, UINT cx, HBITMAP hbmBack, UINT wID,
682 UINT cyChild, UINT cyMaxChild, UINT cyIntegral, UINT cxIdeal, LPARAM lParam,
683 UINT cxHeader)
685 CHAR buf[MAX_PATH] = "abc";
686 REBARBANDINFO rb;
688 memset(&rb, 0xdd, sizeof(rb));
689 rb.cbSize = sizeof(rb);
690 rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
691 | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
692 | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
693 rb.lpText = buf;
694 rb.cch = MAX_PATH;
695 ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
696 expect_eq(rb.fStyle, fStyle, int, "%x");
697 todo_wine expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
698 todo_wine expect_eq(rb.clrBack, clrBack, int, "%x");
699 expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
700 expect_eq(rb.iImage, iImage, int, "%x");
701 expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
702 expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
703 expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
704 expect_eq(rb.cx, cx, int, "%d");
705 expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
706 expect_eq(rb.wID, wID, int, "%d");
707 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
708 expect_eq(rb.cyChild, cyChild, int, "%x");
709 expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
710 expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
711 expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
712 expect_eq(rb.lParam, lParam, LPARAM, "%ld");
713 expect_eq(rb.cxHeader, cxHeader, int, "%d");
716 static void bandinfo_test(void)
718 REBARBANDINFOA rb;
719 CHAR szABC[] = "ABC";
720 CHAR szABCD[] = "ABCD";
722 rebuild_rebar(&hRebar);
723 rb.cbSize = sizeof(REBARBANDINFO);
724 rb.fMask = 0;
725 ok(SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
726 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
728 rb.fMask = RBBIM_CHILDSIZE;
729 rb.cxMinChild = 15;
730 rb.cyMinChild = 20;
731 rb.cyChild = 30;
732 rb.cyMaxChild = 20;
733 rb.cyIntegral = 10;
734 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
735 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
737 rb.fMask = RBBIM_TEXT;
738 rb.lpText = szABC;
739 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
740 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35);
742 rb.cbSize = sizeof(REBARBANDINFO);
743 rb.fMask = 0;
744 ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
745 expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9);
746 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40);
748 rb.fMask = RBBIM_HEADERSIZE;
749 rb.cxHeader = 50;
750 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
751 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50);
753 rb.cxHeader = 5;
754 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
755 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
757 rb.fMask = RBBIM_TEXT;
758 rb.lpText = szABCD;
759 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
760 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
761 rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
762 rb.fStyle = RBBS_VARIABLEHEIGHT;
763 rb.lpText = szABC;
764 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
765 expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40);
767 DestroyWindow(hRebar);
770 START_TEST(rebar)
772 INITCOMMONCONTROLSEX icc;
773 WNDCLASSA wc;
774 MSG msg;
775 RECT rc;
777 icc.dwSize = sizeof(icc);
778 icc.dwICC = ICC_COOL_CLASSES;
779 InitCommonControlsEx(&icc);
781 wc.style = CS_HREDRAW | CS_VREDRAW;
782 wc.cbClsExtra = 0;
783 wc.cbWndExtra = 0;
784 wc.hInstance = GetModuleHandleA(NULL);
785 wc.hIcon = NULL;
786 wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
787 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
788 wc.lpszMenuName = NULL;
789 wc.lpszClassName = "MyTestWnd";
790 wc.lpfnWndProc = MyWndProc;
791 RegisterClassA(&wc);
792 hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
793 CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
794 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
795 NULL, NULL, GetModuleHandleA(NULL), 0);
796 GetClientRect(hMainWnd, &rc);
797 ShowWindow(hMainWnd, SW_SHOW);
799 bandinfo_test();
800 layout_test();
801 resize_test();
802 PostQuitMessage(0);
803 while(GetMessageA(&msg,0,0,0)) {
804 TranslateMessage(&msg);
805 DispatchMessageA(&msg);
807 DestroyWindow(hMainWnd);