push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / comctl32 / tests / rebar.c
blob45b3c066ac35e55629cf5d0d7ac8ceb13ac914ef
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 = REBARBANDINFOA_V6_SIZE;
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 = REBARBANDINFOA_V6_SIZE; \
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 REBARBANDINFOA rbi;
334 if (lpszText != NULL)
335 strcpy(buffer, lpszText);
336 rbi.cbSize = REBARBANDINFOA_V6_SIZE;
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 = REBARBANDINFOA_V6_SIZE;
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);
506 ImageList_Destroy(himl);
509 #if 0 /* use this to generate more tests */
511 static void dump_client(HWND hRebar)
513 RECT r;
514 BOOL notify;
515 GetWindowRect(hRebar, &r);
516 MapWindowPoints(HWND_DESKTOP, hMainWnd, &r, 2);
517 if (height_change_notify_rect.top != -1)
519 RECT rcClient;
520 GetClientRect(hRebar, &rcClient);
521 assert(EqualRect(&rcClient, &height_change_notify_rect));
522 notify = TRUE;
524 else
525 notify = FALSE;
526 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
527 notify ? "TRUE" : "FALSE");
528 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
531 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
532 #define check_client() dump_client(hRebar)
534 #else
536 typedef struct {
537 RECT rc;
538 INT iNumRows;
539 BOOL heightNotify;
540 } rbresize_test_result_t;
542 rbresize_test_result_t resize_results[] = {
543 /* style 00000001 */
544 {{0, 2, 672, 2}, 0, FALSE},
545 {{0, 2, 672, 22}, 1, TRUE},
546 {{0, 2, 672, 22}, 1, FALSE},
547 {{0, 2, 672, 22}, 1, FALSE},
548 {{0, 2, 672, 22}, 1, FALSE},
549 {{0, 2, 672, 22}, 0, FALSE},
550 /* style 00000041 */
551 {{0, 0, 672, 0}, 0, FALSE},
552 {{0, 0, 672, 20}, 1, TRUE},
553 {{0, 0, 672, 20}, 1, FALSE},
554 {{0, 0, 672, 20}, 1, FALSE},
555 {{0, 0, 672, 20}, 1, FALSE},
556 {{0, 0, 672, 20}, 0, FALSE},
557 /* style 00000003 */
558 {{0, 226, 672, 226}, 0, FALSE},
559 {{0, 206, 672, 226}, 1, TRUE},
560 {{0, 206, 672, 226}, 1, FALSE},
561 {{0, 206, 672, 226}, 1, FALSE},
562 {{0, 206, 672, 226}, 1, FALSE},
563 {{0, 206, 672, 226}, 0, FALSE},
564 /* style 00000043 */
565 {{0, 226, 672, 226}, 0, FALSE},
566 {{0, 206, 672, 226}, 1, TRUE},
567 {{0, 206, 672, 226}, 1, FALSE},
568 {{0, 206, 672, 226}, 1, FALSE},
569 {{0, 206, 672, 226}, 1, FALSE},
570 {{0, 206, 672, 226}, 0, FALSE},
571 /* style 00000080 */
572 {{2, 0, 2, 226}, 0, FALSE},
573 {{2, 0, 22, 226}, 1, TRUE},
574 {{2, 0, 22, 226}, 1, FALSE},
575 {{2, 0, 22, 226}, 1, FALSE},
576 {{2, 0, 22, 226}, 1, FALSE},
577 {{2, 0, 22, 226}, 0, FALSE},
578 /* style 00000083 */
579 {{672, 0, 672, 226}, 0, FALSE},
580 {{652, 0, 672, 226}, 1, TRUE},
581 {{652, 0, 672, 226}, 1, FALSE},
582 {{652, 0, 672, 226}, 1, FALSE},
583 {{652, 0, 672, 226}, 1, FALSE},
584 {{652, 0, 672, 226}, 0, FALSE},
585 /* style 00000008 */
586 {{10, 11, 510, 11}, 0, FALSE},
587 {{10, 15, 510, 35}, 1, TRUE},
588 {{10, 17, 510, 37}, 1, FALSE},
589 {{10, 14, 110, 54}, 2, TRUE},
590 {{0, 4, 0, 44}, 2, FALSE},
591 {{0, 6, 0, 46}, 2, FALSE},
592 {{0, 8, 0, 48}, 2, FALSE},
593 {{0, 12, 0, 32}, 1, TRUE},
594 {{0, 4, 100, 24}, 0, FALSE},
595 /* style 00000048 */
596 {{10, 5, 510, 5}, 0, FALSE},
597 {{10, 5, 510, 25}, 1, TRUE},
598 {{10, 5, 510, 25}, 1, FALSE},
599 {{10, 10, 110, 50}, 2, TRUE},
600 {{0, 0, 0, 40}, 2, FALSE},
601 {{0, 0, 0, 40}, 2, FALSE},
602 {{0, 0, 0, 40}, 2, FALSE},
603 {{0, 0, 0, 20}, 1, TRUE},
604 {{0, 0, 100, 20}, 0, FALSE},
605 /* style 00000004 */
606 {{10, 5, 510, 20}, 0, FALSE},
607 {{10, 5, 510, 20}, 1, TRUE},
608 {{10, 10, 110, 110}, 2, TRUE},
609 {{0, 0, 0, 0}, 2, FALSE},
610 {{0, 0, 0, 0}, 2, FALSE},
611 {{0, 0, 0, 0}, 2, FALSE},
612 {{0, 0, 0, 0}, 1, TRUE},
613 {{0, 0, 100, 100}, 0, FALSE},
614 /* style 00000002 */
615 {{0, 5, 672, 5}, 0, FALSE},
616 {{0, 5, 672, 25}, 1, TRUE},
617 {{0, 10, 672, 30}, 1, FALSE},
618 {{0, 0, 672, 20}, 1, FALSE},
619 {{0, 0, 672, 20}, 1, FALSE},
620 {{0, 0, 672, 20}, 0, FALSE},
621 /* style 00000082 */
622 {{10, 0, 10, 226}, 0, FALSE},
623 {{10, 0, 30, 226}, 1, TRUE},
624 {{10, 0, 30, 226}, 1, FALSE},
625 {{0, 0, 20, 226}, 1, FALSE},
626 {{0, 0, 20, 226}, 1, FALSE},
627 {{0, 0, 20, 226}, 0, FALSE},
628 /* style 00800001 */
629 {{-2, 0, 674, 4}, 0, FALSE},
630 {{-2, 0, 674, 24}, 1, TRUE},
631 {{-2, 0, 674, 24}, 1, FALSE},
632 {{-2, 0, 674, 24}, 1, FALSE},
633 {{-2, 0, 674, 24}, 1, FALSE},
634 {{-2, 0, 674, 24}, 0, FALSE},
635 /* style 00800048 */
636 {{10, 5, 510, 9}, 0, FALSE},
637 {{10, 5, 510, 29}, 1, TRUE},
638 {{10, 5, 510, 29}, 1, FALSE},
639 {{10, 10, 110, 54}, 2, TRUE},
640 {{0, 0, 0, 44}, 2, FALSE},
641 {{0, 0, 0, 44}, 2, FALSE},
642 {{0, 0, 0, 44}, 2, FALSE},
643 {{0, 0, 0, 24}, 1, TRUE},
644 {{0, 0, 100, 24}, 0, FALSE},
645 /* style 00800004 */
646 {{10, 5, 510, 20}, 0, FALSE},
647 {{10, 5, 510, 20}, 1, TRUE},
648 {{10, 10, 110, 110}, 2, TRUE},
649 {{0, 0, 0, 0}, 2, FALSE},
650 {{0, 0, 0, 0}, 2, FALSE},
651 {{0, 0, 0, 0}, 2, FALSE},
652 {{0, 0, 0, 0}, 1, TRUE},
653 {{0, 0, 100, 100}, 0, FALSE},
654 /* style 00800002 */
655 {{-2, 5, 674, 9}, 0, FALSE},
656 {{-2, 5, 674, 29}, 1, TRUE},
657 {{-2, 10, 674, 34}, 1, FALSE},
658 {{-2, 0, 674, 24}, 1, FALSE},
659 {{-2, 0, 674, 24}, 1, FALSE},
660 {{-2, 0, 674, 24}, 0, FALSE},
663 static int resize_numtests = 0;
665 #define comment(fmt, arg1)
666 #define check_client() { \
667 RECT r; \
668 rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
669 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
670 GetWindowRect(hRebar, &r); \
671 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
672 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
673 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
674 } else { \
675 check_rect("client", r, res->rc); \
677 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
678 if (res->heightNotify) { \
679 RECT rcClient; \
680 GetClientRect(hRebar, &rcClient); \
681 check_rect("notify", height_change_notify_rect, rcClient); \
682 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
683 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
686 #endif
688 static void resize_test(void)
690 DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
691 CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
692 CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
693 CCS_NOMOVEY | WS_BORDER};
695 const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
696 int i;
698 for (i = 0; i < styles_count; i++)
700 comment("style %08x", dwStyles[i]);
701 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
702 hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
703 check_client();
704 add_band_w(hRebar, NULL, 70, 100, 0);
705 if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
706 check_client();
707 add_band_w(hRebar, NULL, 70, 100, 0);
708 check_client();
709 MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
710 check_client();
711 MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
712 check_client();
713 /* try to fool the rebar by sending invalid width/height - won't work */
714 if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
716 WINDOWPOS pos;
717 pos.hwnd = hRebar;
718 pos.hwndInsertAfter = NULL;
719 pos.cx = 500;
720 pos.cy = 500;
721 pos.x = 10;
722 pos.y = 10;
723 pos.flags = 0;
724 SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
725 SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
726 check_client();
727 SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
728 check_client();
730 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
731 check_client();
732 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
733 MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
734 check_client();
735 DestroyWindow(hRebar);
739 static void expect_band_content(UINT uBand, INT fStyle, COLORREF clrFore,
740 COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
741 INT cxMinChild, INT cyMinChild, INT cx, HBITMAP hbmBack, INT wID,
742 INT cyChild, INT cyMaxChild, INT cyIntegral, INT cxIdeal, LPARAM lParam,
743 INT cxHeader, INT cxHeader_broken)
745 CHAR buf[MAX_PATH] = "abc";
746 REBARBANDINFOA rb;
748 memset(&rb, 0xdd, sizeof(rb));
749 rb.cbSize = REBARBANDINFOA_V6_SIZE;
750 rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
751 | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
752 | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
753 rb.lpText = buf;
754 rb.cch = MAX_PATH;
755 ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
756 expect_eq(rb.fStyle, fStyle, int, "%x");
757 todo_wine expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
758 todo_wine expect_eq(rb.clrBack, clrBack, unsigned, "%x");
759 expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
760 expect_eq(rb.iImage, iImage, int, "%x");
761 expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
762 expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
763 expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
764 expect_eq(rb.cx, cx, int, "%d");
765 expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
766 expect_eq(rb.wID, wID, int, "%d");
767 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
768 expect_eq(rb.cyChild, cyChild, int, "%x");
769 expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
770 expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
771 expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
772 expect_eq(rb.lParam, lParam, LPARAM, "%ld");
773 ok( rb.cxHeader == cxHeader || broken(rb.cxHeader == cxHeader_broken),
774 "expected %d for %d\n", cxHeader, rb.cxHeader );
777 static void bandinfo_test(void)
779 REBARBANDINFOA rb;
780 CHAR szABC[] = "ABC";
781 CHAR szABCD[] = "ABCD";
783 rebuild_rebar(&hRebar);
784 rb.cbSize = REBARBANDINFOA_V6_SIZE;
785 rb.fMask = 0;
786 if (!SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb))
788 win_skip( "V6 info not supported\n" );
789 DestroyWindow(hRebar);
790 return;
792 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
794 rb.fMask = RBBIM_CHILDSIZE;
795 rb.cxMinChild = 15;
796 rb.cyMinChild = 20;
797 rb.cyChild = 30;
798 rb.cyMaxChild = 20;
799 rb.cyIntegral = 10;
800 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
801 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
803 rb.fMask = RBBIM_TEXT;
804 rb.lpText = szABC;
805 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
806 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35, -1);
808 rb.cbSize = REBARBANDINFOA_V6_SIZE;
809 rb.fMask = 0;
810 ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
811 expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9, -1);
812 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40, -1);
814 rb.fMask = RBBIM_HEADERSIZE;
815 rb.cxHeader = 50;
816 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
817 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50, -1);
819 rb.cxHeader = 5;
820 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
821 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
823 rb.fMask = RBBIM_TEXT;
824 rb.lpText = szABCD;
825 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
826 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
827 rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
828 rb.fStyle = RBBS_VARIABLEHEIGHT;
829 rb.lpText = szABC;
830 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
831 expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40, 5);
833 DestroyWindow(hRebar);
836 START_TEST(rebar)
838 HMODULE hComctl32;
839 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
840 INITCOMMONCONTROLSEX iccex;
841 WNDCLASSA wc;
842 MSG msg;
843 RECT rc;
845 /* LoadLibrary is needed. This file has no references to functions in comctl32 */
846 hComctl32 = LoadLibraryA("comctl32.dll");
847 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
848 if (!pInitCommonControlsEx)
850 skip("InitCommonControlsEx() is missing. Skipping the tests\n");
851 return;
853 iccex.dwSize = sizeof(iccex);
854 iccex.dwICC = ICC_COOL_CLASSES;
855 pInitCommonControlsEx(&iccex);
857 wc.style = CS_HREDRAW | CS_VREDRAW;
858 wc.cbClsExtra = 0;
859 wc.cbWndExtra = 0;
860 wc.hInstance = GetModuleHandleA(NULL);
861 wc.hIcon = NULL;
862 wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
863 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
864 wc.lpszMenuName = NULL;
865 wc.lpszClassName = "MyTestWnd";
866 wc.lpfnWndProc = MyWndProc;
867 RegisterClassA(&wc);
868 hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
869 CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
870 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
871 NULL, NULL, GetModuleHandleA(NULL), 0);
872 GetClientRect(hMainWnd, &rc);
873 ShowWindow(hMainWnd, SW_SHOW);
875 bandinfo_test();
877 if(is_font_installed("System") && is_font_installed("Tahoma"))
879 layout_test();
880 resize_test();
881 } else
882 skip("Missing System or Tahoma font\n");
884 PostQuitMessage(0);
885 while(GetMessageA(&msg,0,0,0)) {
886 TranslateMessage(&msg);
887 DispatchMessageA(&msg);
889 DestroyWindow(hMainWnd);
891 FreeLibrary(hComctl32);