push cc8bc80451cc24f4d7cf75168b569f0ebfe19547
[wine/hacks.git] / dlls / comctl32 / tests / rebar.c
blobc819bc78f9ba4b99bb723871c279ac0c955cf043
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 /* make sure the structures work with a comctl32 v5.x */
21 #define _WIN32_WINNT 0x500
22 #define _WIN32_IE 0x500
24 #include <assert.h>
25 #include <stdarg.h>
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <uxtheme.h>
31 #include "wine/test.h"
33 RECT height_change_notify_rect;
34 static HWND hMainWnd;
35 static HWND hRebar;
38 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
39 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
40 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
42 #define check_rect_no_top(name, val, exp) { \
43 ok((val.bottom - val.top == exp.bottom - exp.top) && \
44 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
45 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
48 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
50 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
52 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
54 return 0;
57 static BOOL is_font_installed(const char *name)
59 HDC hdc = GetDC(0);
60 BOOL ret = FALSE;
62 if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
63 ret = TRUE;
65 ReleaseDC(0, hdc);
66 return ret;
69 static void rebuild_rebar(HWND *hRebar)
71 if (*hRebar)
72 DestroyWindow(*hRebar);
74 *hRebar = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
75 hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
76 SendMessageA(*hRebar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
79 static HWND build_toolbar(int nr, HWND hParent)
81 TBBUTTON btns[8];
82 HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
83 hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
84 int iBitmapId = 0;
85 int i;
87 ok(hToolbar != NULL, "Toolbar creation problem\n");
88 ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
89 ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
90 ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
92 for (i=0; i<5+nr; i++)
94 btns[i].iBitmap = i;
95 btns[i].idCommand = i;
96 btns[i].fsStyle = BTNS_BUTTON;
97 btns[i].fsState = TBSTATE_ENABLED;
98 btns[i].iString = 0;
101 switch (nr)
103 case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
104 case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
105 case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
107 ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGES failed\n");
108 ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
109 return hToolbar;
112 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
114 switch (msg)
116 case WM_NOTIFY:
118 NMHDR *lpnm = (NMHDR *)lParam;
119 if (lpnm->code == RBN_HEIGHTCHANGE)
120 GetClientRect(hRebar, &height_change_notify_rect);
122 break;
124 return DefWindowProcA(hWnd, msg, wParam, lParam);
127 #if 0 /* use this to generate more tests*/
129 static void dump_sizes(HWND hRebar)
131 SIZE sz;
132 RECT r;
133 int count;
134 int i, h;
136 GetClientRect(hRebar, &r);
137 count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
138 printf(" { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
139 SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
140 if (count == 0)
141 printf("0, ");
142 for (i = 0; i < count; i++) /* rows */
143 printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
144 printf("}, ");
146 count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
147 printf("%d, {", count);
148 if (count == 0)
149 printf("{{0, 0, 0, 0}, 0, 0},");
150 for (i=0; i<count; i++)
152 REBARBANDINFO rbi;
153 rbi.cbSize = sizeof(REBARBANDINFO);
154 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
155 ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
156 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
157 printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom,
158 rbi.fStyle, rbi.cx);
160 printf("\n }, },\n");
163 #define check_sizes() dump_sizes(hRebar);
164 #define check_sizes_todo(todomask) dump_sizes(hRebar);
166 #else
168 typedef struct {
169 RECT rc;
170 DWORD fStyle;
171 INT cx;
172 } rbband_result_t;
174 typedef struct {
175 RECT rcClient;
176 int cyBarHeight;
177 int nRows;
178 int cyRowHeights[50];
179 int nBands;
180 rbband_result_t bands[50];
181 } rbsize_result_t;
183 rbsize_result_t rbsize_results[] = {
184 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
185 }, },
186 { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
187 { { 0, 0, 672, 4}, 0x00, 200},
188 }, },
189 { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
190 { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
191 }, },
192 { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
193 { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
194 { {400, 0, 672, 30}, 0x00, 200},
195 }, },
196 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
197 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
198 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
199 }, },
200 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
201 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
202 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
203 }, },
204 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
205 { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
206 { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
207 }, },
208 { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
209 { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
210 { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
211 { {202, 36, 672, 70}, 0x04, 66},
212 }, },
213 { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
214 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
215 { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
216 { {629, 0, 672, 34}, 0x04, 66},
217 }, },
218 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
219 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
220 { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
221 }, },
222 { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
223 { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
224 { {617, 0, 672, 34}, 0x04, 66},
225 }, },
226 { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
227 { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
228 }, },
229 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
230 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
231 { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
232 { { 0, 20, 672, 40}, 0x00, 200},
233 }, },
234 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
235 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
236 { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
237 { { 0, 20, 672, 40}, 0x00, 200},
238 }, },
239 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
240 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
241 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
242 { { 0, 20, 672, 40}, 0x00, 200},
243 }, },
244 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
245 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
246 { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
247 { { 0, 20, 672, 40}, 0x00, 200},
248 }, },
249 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
250 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
251 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
252 { { 0, 20, 672, 40}, 0x00, 200},
253 }, },
254 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
255 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
256 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
257 { { 0, 20, 672, 40}, 0x00, 200},
258 }, },
259 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
260 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
261 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
262 { { 0, 28, 672, 56}, 0x00, 200},
263 }, },
264 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
265 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
266 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
267 { { 0, 20, 672, 40}, 0x00, 200},
268 }, },
269 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
270 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
271 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
272 { { 0, 28, 672, 56}, 0x00, 200},
273 }, },
274 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
275 }, },
276 { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
277 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
278 { {180, 0, 672, 65}, 0x40, 90},
279 }, },
280 { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
281 }, },
282 { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
283 { { 0, 0, 226, 65}, 0x40, 90},
284 }, },
285 { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
286 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
287 }, },
288 { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
289 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
290 { {163, 0, 226, 65}, 0x40, 90},
291 }, },
294 static int rbsize_numtests = 0;
296 #define check_sizes_todo(todomask) { \
297 RECT rc; \
298 REBARBANDINFO rbi; \
299 int count, i/*, mask=(todomask)*/; \
300 rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
301 assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
302 GetClientRect(hRebar, &rc); \
303 check_rect("client", rc, res->rcClient); \
304 count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
305 compare(count, res->nRows, "%d"); \
306 for (i=0; i<min(count, res->nRows); i++) { \
307 int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
308 ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
310 count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
311 compare(count, res->nBands, "%d"); \
312 for (i=0; i<min(count, res->nBands); i++) { \
313 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \
314 if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
315 check_rect("band", rc, res->bands[i].rc); \
316 rbi.cbSize = sizeof(REBARBANDINFO); \
317 rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
318 ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
319 compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
320 compare(rbi.cx, res->bands[i].cx, "%d"); \
322 rbsize_numtests++; \
325 #define check_sizes() check_sizes_todo(0)
327 #endif
329 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
331 CHAR buffer[MAX_PATH];
332 REBARBANDINFO rbi;
334 if (lpszText != NULL)
335 strcpy(buffer, lpszText);
336 rbi.cbSize = sizeof(rbi);
337 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
338 rbi.cx = cx;
339 rbi.cxMinChild = cxMinChild;
340 rbi.cxIdeal = cxIdeal;
341 rbi.cyMinChild = 20;
342 rbi.hwndChild = build_toolbar(1, hRebar);
343 rbi.lpText = (lpszText ? buffer : NULL);
344 SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
347 static void layout_test(void)
349 HWND hRebar = NULL;
350 REBARBANDINFO rbi;
351 HIMAGELIST himl;
352 REBARINFO ri;
354 rebuild_rebar(&hRebar);
355 check_sizes();
356 rbi.cbSize = sizeof(rbi);
357 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
358 rbi.cx = 200;
359 rbi.cxMinChild = 100;
360 rbi.cyMinChild = 30;
361 rbi.hwndChild = NULL;
362 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
363 check_sizes();
365 rbi.fMask |= RBBIM_STYLE;
366 rbi.fStyle = RBBS_CHILDEDGE;
367 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
368 check_sizes();
370 rbi.fStyle = 0;
371 rbi.cx = 200;
372 rbi.cxMinChild = 30;
373 rbi.cyMinChild = 30;
374 rbi.hwndChild = build_toolbar(0, hRebar);
375 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
376 check_sizes();
378 rbi.fStyle = RBBS_CHILDEDGE;
379 rbi.cx = 68;
380 rbi.hwndChild = build_toolbar(0, hRebar);
381 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
382 check_sizes();
384 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
385 check_sizes(); /* a style change won't start a relayout */
386 rbi.fMask = RBBIM_SIZE;
387 rbi.cx = 66;
388 SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
389 check_sizes(); /* here it will be relayouted */
391 /* this will force a new row */
392 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
393 rbi.cx = 200;
394 rbi.cxMinChild = 400;
395 rbi.cyMinChild = 30;
396 rbi.hwndChild = build_toolbar(0, hRebar);
397 SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
398 check_sizes();
400 rbi.fMask = RBBIM_STYLE;
401 rbi.fStyle = RBBS_HIDDEN;
402 SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
403 check_sizes();
405 SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
406 check_sizes();
407 SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
408 check_sizes();
409 SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
410 check_sizes();
412 rebuild_rebar(&hRebar);
413 add_band_w(hRebar, "ABC", 70, 40, 100);
414 add_band_w(hRebar, NULL, 40, 70, 100);
415 add_band_w(hRebar, NULL, 170, 240, 100);
416 add_band_w(hRebar, "MMMMMMM", 60, 60, 100);
417 add_band_w(hRebar, NULL, 200, 200, 100);
418 check_sizes();
419 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
420 check_sizes();
421 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
422 check_sizes();
423 SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
424 check_sizes();
425 SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
426 check_sizes();
427 SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
428 check_sizes();
430 /* an image will increase the band height */
431 himl = ImageList_LoadImage(LoadLibrary("comctl32"), MAKEINTRESOURCE(121), 24, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
432 ri.cbSize = sizeof(ri);
433 ri.fMask = RBIM_IMAGELIST;
434 ri.himl = himl;
435 ok(SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&ri), "RB_SETBARINFO failed\n");
436 rbi.fMask = RBBIM_IMAGE;
437 rbi.iImage = 1;
438 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
439 check_sizes();
441 /* after removing it everything is back to normal*/
442 rbi.iImage = -1;
443 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
444 check_sizes();
446 /* Only -1 means that the image is not present. Other invalid values increase the height */
447 rbi.iImage = -2;
448 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
449 check_sizes();
451 /* VARHEIGHT resizing test on a horizontal rebar */
452 rebuild_rebar(&hRebar);
453 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
454 check_sizes();
455 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
456 rbi.fStyle = RBBS_VARIABLEHEIGHT;
457 rbi.cxMinChild = 50;
458 rbi.cyMinChild = 10;
459 rbi.cyIntegral = 11;
460 rbi.cyChild = 70;
461 rbi.cyMaxChild = 200;
462 rbi.cx = 90;
463 rbi.hwndChild = build_toolbar(0, hRebar);
464 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
466 rbi.cyChild = 50;
467 rbi.hwndChild = build_toolbar(0, hRebar);
468 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
470 rbi.cyMinChild = 40;
471 rbi.cyChild = 50;
472 rbi.cyIntegral = 5;
473 rbi.hwndChild = build_toolbar(0, hRebar);
474 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
475 check_sizes();
477 /* VARHEIGHT resizing on a vertical rebar */
478 rebuild_rebar(&hRebar);
479 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
480 check_sizes();
481 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
482 rbi.fStyle = RBBS_VARIABLEHEIGHT;
483 rbi.cxMinChild = 50;
484 rbi.cyMinChild = 10;
485 rbi.cyIntegral = 11;
486 rbi.cyChild = 70;
487 rbi.cyMaxChild = 90;
488 rbi.cx = 90;
489 rbi.hwndChild = build_toolbar(0, hRebar);
490 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
491 check_sizes();
493 rbi.cyChild = 50;
494 rbi.hwndChild = build_toolbar(0, hRebar);
495 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
496 check_sizes();
498 rbi.cyMinChild = 40;
499 rbi.cyChild = 50;
500 rbi.cyIntegral = 5;
501 rbi.hwndChild = build_toolbar(0, hRebar);
502 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
503 check_sizes();
505 DestroyWindow(hRebar);
508 #if 0 /* use this to generate more tests */
510 static void dump_client(HWND hRebar)
512 RECT r;
513 BOOL notify;
514 GetWindowRect(hRebar, &r);
515 MapWindowPoints(HWND_DESKTOP, hMainWnd, &r, 2);
516 if (height_change_notify_rect.top != -1)
518 RECT rcClient;
519 GetClientRect(hRebar, &rcClient);
520 assert(EqualRect(&rcClient, &height_change_notify_rect));
521 notify = TRUE;
523 else
524 notify = FALSE;
525 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
526 notify ? "TRUE" : "FALSE");
527 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
530 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
531 #define check_client() dump_client(hRebar)
533 #else
535 typedef struct {
536 RECT rc;
537 INT iNumRows;
538 BOOL heightNotify;
539 } rbresize_test_result_t;
541 rbresize_test_result_t resize_results[] = {
542 /* style 00000001 */
543 {{0, 2, 672, 2}, 0, FALSE},
544 {{0, 2, 672, 22}, 1, TRUE},
545 {{0, 2, 672, 22}, 1, FALSE},
546 {{0, 2, 672, 22}, 1, FALSE},
547 {{0, 2, 672, 22}, 1, FALSE},
548 {{0, 2, 672, 22}, 0, FALSE},
549 /* style 00000041 */
550 {{0, 0, 672, 0}, 0, FALSE},
551 {{0, 0, 672, 20}, 1, TRUE},
552 {{0, 0, 672, 20}, 1, FALSE},
553 {{0, 0, 672, 20}, 1, FALSE},
554 {{0, 0, 672, 20}, 1, FALSE},
555 {{0, 0, 672, 20}, 0, FALSE},
556 /* style 00000003 */
557 {{0, 226, 672, 226}, 0, FALSE},
558 {{0, 206, 672, 226}, 1, TRUE},
559 {{0, 206, 672, 226}, 1, FALSE},
560 {{0, 206, 672, 226}, 1, FALSE},
561 {{0, 206, 672, 226}, 1, FALSE},
562 {{0, 206, 672, 226}, 0, FALSE},
563 /* style 00000043 */
564 {{0, 226, 672, 226}, 0, FALSE},
565 {{0, 206, 672, 226}, 1, TRUE},
566 {{0, 206, 672, 226}, 1, FALSE},
567 {{0, 206, 672, 226}, 1, FALSE},
568 {{0, 206, 672, 226}, 1, FALSE},
569 {{0, 206, 672, 226}, 0, FALSE},
570 /* style 00000080 */
571 {{2, 0, 2, 226}, 0, FALSE},
572 {{2, 0, 22, 226}, 1, TRUE},
573 {{2, 0, 22, 226}, 1, FALSE},
574 {{2, 0, 22, 226}, 1, FALSE},
575 {{2, 0, 22, 226}, 1, FALSE},
576 {{2, 0, 22, 226}, 0, FALSE},
577 /* style 00000083 */
578 {{672, 0, 672, 226}, 0, FALSE},
579 {{652, 0, 672, 226}, 1, TRUE},
580 {{652, 0, 672, 226}, 1, FALSE},
581 {{652, 0, 672, 226}, 1, FALSE},
582 {{652, 0, 672, 226}, 1, FALSE},
583 {{652, 0, 672, 226}, 0, FALSE},
584 /* style 00000008 */
585 {{10, 11, 510, 11}, 0, FALSE},
586 {{10, 15, 510, 35}, 1, TRUE},
587 {{10, 17, 510, 37}, 1, FALSE},
588 {{10, 14, 110, 54}, 2, TRUE},
589 {{0, 4, 0, 44}, 2, FALSE},
590 {{0, 6, 0, 46}, 2, FALSE},
591 {{0, 8, 0, 48}, 2, FALSE},
592 {{0, 12, 0, 32}, 1, TRUE},
593 {{0, 4, 100, 24}, 0, FALSE},
594 /* style 00000048 */
595 {{10, 5, 510, 5}, 0, FALSE},
596 {{10, 5, 510, 25}, 1, TRUE},
597 {{10, 5, 510, 25}, 1, FALSE},
598 {{10, 10, 110, 50}, 2, TRUE},
599 {{0, 0, 0, 40}, 2, FALSE},
600 {{0, 0, 0, 40}, 2, FALSE},
601 {{0, 0, 0, 40}, 2, FALSE},
602 {{0, 0, 0, 20}, 1, TRUE},
603 {{0, 0, 100, 20}, 0, FALSE},
604 /* style 00000004 */
605 {{10, 5, 510, 20}, 0, FALSE},
606 {{10, 5, 510, 20}, 1, TRUE},
607 {{10, 10, 110, 110}, 2, TRUE},
608 {{0, 0, 0, 0}, 2, FALSE},
609 {{0, 0, 0, 0}, 2, FALSE},
610 {{0, 0, 0, 0}, 2, FALSE},
611 {{0, 0, 0, 0}, 1, TRUE},
612 {{0, 0, 100, 100}, 0, FALSE},
613 /* style 00000002 */
614 {{0, 5, 672, 5}, 0, FALSE},
615 {{0, 5, 672, 25}, 1, TRUE},
616 {{0, 10, 672, 30}, 1, FALSE},
617 {{0, 0, 672, 20}, 1, FALSE},
618 {{0, 0, 672, 20}, 1, FALSE},
619 {{0, 0, 672, 20}, 0, FALSE},
620 /* style 00000082 */
621 {{10, 0, 10, 226}, 0, FALSE},
622 {{10, 0, 30, 226}, 1, TRUE},
623 {{10, 0, 30, 226}, 1, FALSE},
624 {{0, 0, 20, 226}, 1, FALSE},
625 {{0, 0, 20, 226}, 1, FALSE},
626 {{0, 0, 20, 226}, 0, FALSE},
627 /* style 00800001 */
628 {{-2, 0, 674, 4}, 0, FALSE},
629 {{-2, 0, 674, 24}, 1, TRUE},
630 {{-2, 0, 674, 24}, 1, FALSE},
631 {{-2, 0, 674, 24}, 1, FALSE},
632 {{-2, 0, 674, 24}, 1, FALSE},
633 {{-2, 0, 674, 24}, 0, FALSE},
634 /* style 00800048 */
635 {{10, 5, 510, 9}, 0, FALSE},
636 {{10, 5, 510, 29}, 1, TRUE},
637 {{10, 5, 510, 29}, 1, FALSE},
638 {{10, 10, 110, 54}, 2, TRUE},
639 {{0, 0, 0, 44}, 2, FALSE},
640 {{0, 0, 0, 44}, 2, FALSE},
641 {{0, 0, 0, 44}, 2, FALSE},
642 {{0, 0, 0, 24}, 1, TRUE},
643 {{0, 0, 100, 24}, 0, FALSE},
644 /* style 00800004 */
645 {{10, 5, 510, 20}, 0, FALSE},
646 {{10, 5, 510, 20}, 1, TRUE},
647 {{10, 10, 110, 110}, 2, TRUE},
648 {{0, 0, 0, 0}, 2, FALSE},
649 {{0, 0, 0, 0}, 2, FALSE},
650 {{0, 0, 0, 0}, 2, FALSE},
651 {{0, 0, 0, 0}, 1, TRUE},
652 {{0, 0, 100, 100}, 0, FALSE},
653 /* style 00800002 */
654 {{-2, 5, 674, 9}, 0, FALSE},
655 {{-2, 5, 674, 29}, 1, TRUE},
656 {{-2, 10, 674, 34}, 1, FALSE},
657 {{-2, 0, 674, 24}, 1, FALSE},
658 {{-2, 0, 674, 24}, 1, FALSE},
659 {{-2, 0, 674, 24}, 0, FALSE},
662 static int resize_numtests = 0;
664 #define comment(fmt, arg1)
665 #define check_client() { \
666 RECT r; \
667 rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
668 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
669 GetWindowRect(hRebar, &r); \
670 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
671 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
672 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
673 } else { \
674 check_rect("client", r, res->rc); \
676 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
677 if (res->heightNotify) { \
678 RECT rcClient; \
679 GetClientRect(hRebar, &rcClient); \
680 check_rect("notify", height_change_notify_rect, rcClient); \
681 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
682 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
685 #endif
687 static void resize_test(void)
689 DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
690 CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
691 CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
692 CCS_NOMOVEY | WS_BORDER};
694 const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
695 int i;
697 for (i = 0; i < styles_count; i++)
699 comment("style %08x", dwStyles[i]);
700 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
701 hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
702 check_client();
703 add_band_w(hRebar, NULL, 70, 100, 0);
704 if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
705 check_client();
706 add_band_w(hRebar, NULL, 70, 100, 0);
707 check_client();
708 MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
709 check_client();
710 MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
711 check_client();
712 /* try to fool the rebar by sending invalid width/height - won't work */
713 if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
715 WINDOWPOS pos;
716 pos.hwnd = hRebar;
717 pos.hwndInsertAfter = NULL;
718 pos.cx = 500;
719 pos.cy = 500;
720 pos.x = 10;
721 pos.y = 10;
722 pos.flags = 0;
723 SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
724 SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
725 check_client();
726 SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
727 check_client();
729 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
730 check_client();
731 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
732 MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
733 check_client();
734 DestroyWindow(hRebar);
738 static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
739 COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
740 INT cxMinChild, INT cyMinChild, INT cx, HBITMAP hbmBack, INT wID,
741 INT cyChild, INT cyMaxChild, INT cyIntegral, INT cxIdeal, LPARAM lParam,
742 INT cxHeader)
744 CHAR buf[MAX_PATH] = "abc";
745 REBARBANDINFO rb;
747 memset(&rb, 0xdd, sizeof(rb));
748 rb.cbSize = sizeof(rb);
749 rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
750 | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
751 | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
752 rb.lpText = buf;
753 rb.cch = MAX_PATH;
754 ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
755 expect_eq(rb.fStyle, fStyle, int, "%x");
756 todo_wine expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
757 todo_wine expect_eq(rb.clrBack, clrBack, unsigned, "%x");
758 expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
759 expect_eq(rb.iImage, iImage, int, "%x");
760 expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
761 expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
762 expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
763 expect_eq(rb.cx, cx, int, "%d");
764 expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
765 expect_eq(rb.wID, wID, int, "%d");
766 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
767 expect_eq(rb.cyChild, cyChild, int, "%x");
768 expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
769 expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
770 expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
771 expect_eq(rb.lParam, lParam, LPARAM, "%ld");
772 expect_eq(rb.cxHeader, cxHeader, int, "%d");
775 static void bandinfo_test(void)
777 REBARBANDINFOA rb;
778 CHAR szABC[] = "ABC";
779 CHAR szABCD[] = "ABCD";
781 rebuild_rebar(&hRebar);
782 rb.cbSize = sizeof(REBARBANDINFO);
783 rb.fMask = 0;
784 ok(SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
785 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
787 rb.fMask = RBBIM_CHILDSIZE;
788 rb.cxMinChild = 15;
789 rb.cyMinChild = 20;
790 rb.cyChild = 30;
791 rb.cyMaxChild = 20;
792 rb.cyIntegral = 10;
793 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
794 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
796 rb.fMask = RBBIM_TEXT;
797 rb.lpText = szABC;
798 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
799 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35);
801 rb.cbSize = sizeof(REBARBANDINFO);
802 rb.fMask = 0;
803 ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
804 expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9);
805 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40);
807 rb.fMask = RBBIM_HEADERSIZE;
808 rb.cxHeader = 50;
809 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
810 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50);
812 rb.cxHeader = 5;
813 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
814 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
816 rb.fMask = RBBIM_TEXT;
817 rb.lpText = szABCD;
818 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
819 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
820 rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
821 rb.fStyle = RBBS_VARIABLEHEIGHT;
822 rb.lpText = szABC;
823 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
824 expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40);
826 DestroyWindow(hRebar);
829 START_TEST(rebar)
831 HMODULE hComctl32;
832 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
833 INITCOMMONCONTROLSEX iccex;
834 WNDCLASSA wc;
835 MSG msg;
836 RECT rc;
838 /* LoadLibrary is needed. This file has no references to functions in comctl32 */
839 hComctl32 = LoadLibraryA("comctl32.dll");
840 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
841 if (!pInitCommonControlsEx)
843 skip("InitCommonControlsEx() is missing. Skipping the tests\n");
844 return;
846 iccex.dwSize = sizeof(iccex);
847 iccex.dwICC = ICC_COOL_CLASSES;
848 pInitCommonControlsEx(&iccex);
850 wc.style = CS_HREDRAW | CS_VREDRAW;
851 wc.cbClsExtra = 0;
852 wc.cbWndExtra = 0;
853 wc.hInstance = GetModuleHandleA(NULL);
854 wc.hIcon = NULL;
855 wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
856 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
857 wc.lpszMenuName = NULL;
858 wc.lpszClassName = "MyTestWnd";
859 wc.lpfnWndProc = MyWndProc;
860 RegisterClassA(&wc);
861 hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
862 CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
863 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
864 NULL, NULL, GetModuleHandleA(NULL), 0);
865 GetClientRect(hMainWnd, &rc);
866 ShowWindow(hMainWnd, SW_SHOW);
868 bandinfo_test();
870 if(is_font_installed("System") && is_font_installed("Tahoma"))
872 layout_test();
873 resize_test();
874 } else
875 skip("Missing System or Tahoma font\n");
877 PostQuitMessage(0);
878 while(GetMessageA(&msg,0,0,0)) {
879 TranslateMessage(&msg);
880 DispatchMessageA(&msg);
882 DestroyWindow(hMainWnd);
884 FreeLibrary(hComctl32);