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
31 #include "wine/test.h"
33 static RECT height_change_notify_rect;
37 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
38 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
39 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
41 #define check_rect_no_top(name, val, exp) { \
42 ok((val.bottom - val.top == exp.bottom - exp.top) && \
43 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
44 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
47 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
49 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
51 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
56 static BOOL is_font_installed(const char *name)
61 if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
68 static HWND create_rebar_control(void)
72 hwnd = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
73 hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
74 ok(hwnd != NULL, "Failed to create Rebar\n");
76 SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
81 static HWND build_toolbar(int nr, HWND hParent)
84 HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
85 hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
89 ok(hToolbar != NULL, "Toolbar creation problem\n");
90 ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
91 ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
92 ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
94 for (i=0; i<5+nr; i++)
97 btns[i].idCommand = i;
98 btns[i].fsStyle = BTNS_BUTTON;
99 btns[i].fsState = TBSTATE_ENABLED;
105 case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
106 case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
107 case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
109 ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGES failed\n");
110 ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
114 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
120 NMHDR *lpnm = (NMHDR *)lParam;
121 if (lpnm->code == RBN_HEIGHTCHANGE)
122 GetClientRect(lpnm->hwndFrom, &height_change_notify_rect);
126 return DefWindowProcA(hWnd, msg, wParam, lParam);
129 #if 0 /* use this to generate more tests*/
131 static void dump_sizes(HWND hRebar)
138 GetClientRect(hRebar, &r);
139 count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
140 printf(" { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
141 SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
144 for (i = 0; i < count; i++) /* rows */
145 printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
148 count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
149 printf("%d, {", count);
151 printf("{{0, 0, 0, 0}, 0, 0},");
152 for (i=0; i<count; i++)
155 rbi.cbSize = REBARBANDINFOA_V6_SIZE;
156 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
157 ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
158 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
159 printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom,
162 printf("\n }, },\n");
165 #define check_sizes() dump_sizes(hRebar);
166 #define check_sizes_todo(todomask) dump_sizes(hRebar);
180 int cyRowHeights[50];
182 rbband_result_t bands[50];
185 static const rbsize_result_t rbsize_results[] = {
186 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
188 { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
189 { { 0, 0, 672, 4}, 0x00, 200},
191 { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
192 { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
194 { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
195 { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
196 { {400, 0, 672, 30}, 0x00, 200},
198 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
199 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
200 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
202 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
203 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
204 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
206 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
207 { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
208 { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
210 { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
211 { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
212 { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
213 { {202, 36, 672, 70}, 0x04, 66},
215 { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
216 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
217 { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
218 { {629, 0, 672, 34}, 0x04, 66},
220 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
221 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
222 { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
224 { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
225 { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
226 { {617, 0, 672, 34}, 0x04, 66},
228 { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
229 { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
231 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
232 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
233 { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
234 { { 0, 20, 672, 40}, 0x00, 200},
236 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
237 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
238 { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
239 { { 0, 20, 672, 40}, 0x00, 200},
241 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
242 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
243 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
244 { { 0, 20, 672, 40}, 0x00, 200},
246 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
247 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
248 { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
249 { { 0, 20, 672, 40}, 0x00, 200},
251 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
252 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
253 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
254 { { 0, 20, 672, 40}, 0x00, 200},
256 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
257 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
258 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
259 { { 0, 20, 672, 40}, 0x00, 200},
261 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
262 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
263 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
264 { { 0, 28, 672, 56}, 0x00, 200},
266 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
267 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
268 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
269 { { 0, 20, 672, 40}, 0x00, 200},
271 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
272 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
273 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
274 { { 0, 28, 672, 56}, 0x00, 200},
276 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
278 { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
279 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
280 { {180, 0, 672, 65}, 0x40, 90},
282 { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
284 { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
285 { { 0, 0, 226, 65}, 0x40, 90},
287 { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
288 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
290 { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
291 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
292 { {163, 0, 226, 65}, 0x40, 90},
296 static int rbsize_numtests = 0;
298 #define check_sizes_todo(todomask) { \
301 int count, i/*, mask=(todomask)*/; \
302 const rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
303 assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
304 GetClientRect(hRebar, &rc); \
305 check_rect("client", rc, res->rcClient); \
306 count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
307 compare(count, res->nRows, "%d"); \
308 for (i=0; i<min(count, res->nRows); i++) { \
309 int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
310 ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
312 count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
313 compare(count, res->nBands, "%d"); \
314 for (i=0; i<min(count, res->nBands); i++) { \
315 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \
316 if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
317 check_rect("band", rc, res->bands[i].rc); \
318 rbi.cbSize = REBARBANDINFOA_V6_SIZE; \
319 rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
320 ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
321 compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
322 compare(rbi.cx, res->bands[i].cx, "%d"); \
327 #define check_sizes() check_sizes_todo(0)
331 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
333 CHAR buffer[MAX_PATH];
336 if (lpszText != NULL)
337 strcpy(buffer, lpszText);
338 rbi.cbSize = REBARBANDINFOA_V6_SIZE;
339 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
341 rbi.cxMinChild = cxMinChild;
342 rbi.cxIdeal = cxIdeal;
344 rbi.hwndChild = build_toolbar(1, hRebar);
345 rbi.lpText = (lpszText ? buffer : NULL);
346 SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
349 static void test_layout(void)
356 hRebar = create_rebar_control();
358 rbi.cbSize = REBARBANDINFOA_V6_SIZE;
359 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
361 rbi.cxMinChild = 100;
363 rbi.hwndChild = NULL;
364 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
367 rbi.fMask |= RBBIM_STYLE;
368 rbi.fStyle = RBBS_CHILDEDGE;
369 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
376 rbi.hwndChild = build_toolbar(0, hRebar);
377 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
380 rbi.fStyle = RBBS_CHILDEDGE;
382 rbi.hwndChild = build_toolbar(0, hRebar);
383 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
386 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
387 check_sizes(); /* a style change won't start a relayout */
388 rbi.fMask = RBBIM_SIZE;
390 SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
391 check_sizes(); /* here it will be relayouted */
393 /* this will force a new row */
394 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
396 rbi.cxMinChild = 400;
398 rbi.hwndChild = build_toolbar(0, hRebar);
399 SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
402 rbi.fMask = RBBIM_STYLE;
403 rbi.fStyle = RBBS_HIDDEN;
404 SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
407 SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
409 SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
411 SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
414 DestroyWindow(hRebar);
416 hRebar = create_rebar_control();
417 add_band_w(hRebar, "ABC", 70, 40, 100);
418 add_band_w(hRebar, NULL, 40, 70, 100);
419 add_band_w(hRebar, NULL, 170, 240, 100);
420 add_band_w(hRebar, "MMMMMMM", 60, 60, 100);
421 add_band_w(hRebar, NULL, 200, 200, 100);
423 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
425 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
427 SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
429 SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
431 SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
434 /* an image will increase the band height */
435 himl = ImageList_LoadImage(LoadLibrary("comctl32"), MAKEINTRESOURCE(121), 24, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
436 ri.cbSize = sizeof(ri);
437 ri.fMask = RBIM_IMAGELIST;
439 ok(SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&ri), "RB_SETBARINFO failed\n");
440 rbi.fMask = RBBIM_IMAGE;
442 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
445 /* after removing it everything is back to normal*/
447 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
450 /* Only -1 means that the image is not present. Other invalid values increase the height */
452 SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
455 DestroyWindow(hRebar);
457 /* VARHEIGHT resizing test on a horizontal rebar */
458 hRebar = create_rebar_control();
459 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
461 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
462 rbi.fStyle = RBBS_VARIABLEHEIGHT;
467 rbi.cyMaxChild = 200;
469 rbi.hwndChild = build_toolbar(0, hRebar);
470 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
473 rbi.hwndChild = build_toolbar(0, hRebar);
474 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
479 rbi.hwndChild = build_toolbar(0, hRebar);
480 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
483 DestroyWindow(hRebar);
485 /* VARHEIGHT resizing on a vertical rebar */
486 hRebar = create_rebar_control();
487 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
489 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
490 rbi.fStyle = RBBS_VARIABLEHEIGHT;
497 rbi.hwndChild = build_toolbar(0, hRebar);
498 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
502 rbi.hwndChild = build_toolbar(0, hRebar);
503 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
509 rbi.hwndChild = build_toolbar(0, hRebar);
510 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
513 DestroyWindow(hRebar);
514 ImageList_Destroy(himl);
517 #if 0 /* use this to generate more tests */
519 static void dump_client(HWND hRebar)
523 GetWindowRect(hRebar, &r);
524 MapWindowPoints(HWND_DESKTOP, hMainWnd, &r, 2);
525 if (height_change_notify_rect.top != -1)
528 GetClientRect(hRebar, &rcClient);
529 assert(EqualRect(&rcClient, &height_change_notify_rect));
534 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
535 notify ? "TRUE" : "FALSE");
536 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
539 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
540 #define check_client() dump_client(hRebar)
548 } rbresize_test_result_t;
550 static const rbresize_test_result_t resize_results[] = {
552 {{0, 2, 672, 2}, 0, FALSE},
553 {{0, 2, 672, 22}, 1, TRUE},
554 {{0, 2, 672, 22}, 1, FALSE},
555 {{0, 2, 672, 22}, 1, FALSE},
556 {{0, 2, 672, 22}, 1, FALSE},
557 {{0, 2, 672, 22}, 0, FALSE},
559 {{0, 0, 672, 0}, 0, FALSE},
560 {{0, 0, 672, 20}, 1, TRUE},
561 {{0, 0, 672, 20}, 1, FALSE},
562 {{0, 0, 672, 20}, 1, FALSE},
563 {{0, 0, 672, 20}, 1, FALSE},
564 {{0, 0, 672, 20}, 0, FALSE},
566 {{0, 226, 672, 226}, 0, FALSE},
567 {{0, 206, 672, 226}, 1, TRUE},
568 {{0, 206, 672, 226}, 1, FALSE},
569 {{0, 206, 672, 226}, 1, FALSE},
570 {{0, 206, 672, 226}, 1, FALSE},
571 {{0, 206, 672, 226}, 0, FALSE},
573 {{0, 226, 672, 226}, 0, FALSE},
574 {{0, 206, 672, 226}, 1, TRUE},
575 {{0, 206, 672, 226}, 1, FALSE},
576 {{0, 206, 672, 226}, 1, FALSE},
577 {{0, 206, 672, 226}, 1, FALSE},
578 {{0, 206, 672, 226}, 0, FALSE},
580 {{2, 0, 2, 226}, 0, FALSE},
581 {{2, 0, 22, 226}, 1, TRUE},
582 {{2, 0, 22, 226}, 1, FALSE},
583 {{2, 0, 22, 226}, 1, FALSE},
584 {{2, 0, 22, 226}, 1, FALSE},
585 {{2, 0, 22, 226}, 0, FALSE},
587 {{672, 0, 672, 226}, 0, FALSE},
588 {{652, 0, 672, 226}, 1, TRUE},
589 {{652, 0, 672, 226}, 1, FALSE},
590 {{652, 0, 672, 226}, 1, FALSE},
591 {{652, 0, 672, 226}, 1, FALSE},
592 {{652, 0, 672, 226}, 0, FALSE},
594 {{10, 11, 510, 11}, 0, FALSE},
595 {{10, 15, 510, 35}, 1, TRUE},
596 {{10, 17, 510, 37}, 1, FALSE},
597 {{10, 14, 110, 54}, 2, TRUE},
598 {{0, 4, 0, 44}, 2, FALSE},
599 {{0, 6, 0, 46}, 2, FALSE},
600 {{0, 8, 0, 48}, 2, FALSE},
601 {{0, 12, 0, 32}, 1, TRUE},
602 {{0, 4, 100, 24}, 0, FALSE},
604 {{10, 5, 510, 5}, 0, FALSE},
605 {{10, 5, 510, 25}, 1, TRUE},
606 {{10, 5, 510, 25}, 1, FALSE},
607 {{10, 10, 110, 50}, 2, TRUE},
608 {{0, 0, 0, 40}, 2, FALSE},
609 {{0, 0, 0, 40}, 2, FALSE},
610 {{0, 0, 0, 40}, 2, FALSE},
611 {{0, 0, 0, 20}, 1, TRUE},
612 {{0, 0, 100, 20}, 0, FALSE},
614 {{10, 5, 510, 20}, 0, FALSE},
615 {{10, 5, 510, 20}, 1, TRUE},
616 {{10, 10, 110, 110}, 2, TRUE},
617 {{0, 0, 0, 0}, 2, FALSE},
618 {{0, 0, 0, 0}, 2, FALSE},
619 {{0, 0, 0, 0}, 2, FALSE},
620 {{0, 0, 0, 0}, 1, TRUE},
621 {{0, 0, 100, 100}, 0, FALSE},
623 {{0, 5, 672, 5}, 0, FALSE},
624 {{0, 5, 672, 25}, 1, TRUE},
625 {{0, 10, 672, 30}, 1, FALSE},
626 {{0, 0, 672, 20}, 1, FALSE},
627 {{0, 0, 672, 20}, 1, FALSE},
628 {{0, 0, 672, 20}, 0, FALSE},
630 {{10, 0, 10, 226}, 0, FALSE},
631 {{10, 0, 30, 226}, 1, TRUE},
632 {{10, 0, 30, 226}, 1, FALSE},
633 {{0, 0, 20, 226}, 1, FALSE},
634 {{0, 0, 20, 226}, 1, FALSE},
635 {{0, 0, 20, 226}, 0, FALSE},
637 {{-2, 0, 674, 4}, 0, FALSE},
638 {{-2, 0, 674, 24}, 1, TRUE},
639 {{-2, 0, 674, 24}, 1, FALSE},
640 {{-2, 0, 674, 24}, 1, FALSE},
641 {{-2, 0, 674, 24}, 1, FALSE},
642 {{-2, 0, 674, 24}, 0, FALSE},
644 {{10, 5, 510, 9}, 0, FALSE},
645 {{10, 5, 510, 29}, 1, TRUE},
646 {{10, 5, 510, 29}, 1, FALSE},
647 {{10, 10, 110, 54}, 2, TRUE},
648 {{0, 0, 0, 44}, 2, FALSE},
649 {{0, 0, 0, 44}, 2, FALSE},
650 {{0, 0, 0, 44}, 2, FALSE},
651 {{0, 0, 0, 24}, 1, TRUE},
652 {{0, 0, 100, 24}, 0, FALSE},
654 {{10, 5, 510, 20}, 0, FALSE},
655 {{10, 5, 510, 20}, 1, TRUE},
656 {{10, 10, 110, 110}, 2, TRUE},
657 {{0, 0, 0, 0}, 2, FALSE},
658 {{0, 0, 0, 0}, 2, FALSE},
659 {{0, 0, 0, 0}, 2, FALSE},
660 {{0, 0, 0, 0}, 1, TRUE},
661 {{0, 0, 100, 100}, 0, FALSE},
663 {{-2, 5, 674, 9}, 0, FALSE},
664 {{-2, 5, 674, 29}, 1, TRUE},
665 {{-2, 10, 674, 34}, 1, FALSE},
666 {{-2, 0, 674, 24}, 1, FALSE},
667 {{-2, 0, 674, 24}, 1, FALSE},
668 {{-2, 0, 674, 24}, 0, FALSE},
671 static int resize_numtests = 0;
673 #define comment(fmt, arg1)
674 #define check_client() { \
676 const rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
677 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
678 GetWindowRect(hRebar, &r); \
679 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
680 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
681 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
683 check_rect("client", r, res->rc); \
685 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
686 if (res->heightNotify) { \
688 GetClientRect(hRebar, &rcClient); \
689 check_rect("notify", height_change_notify_rect, rcClient); \
690 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
691 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
696 static void test_resize(void)
698 DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
699 CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
700 CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
701 CCS_NOMOVEY | WS_BORDER};
703 const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
706 for (i = 0; i < styles_count; i++)
710 comment("style %08x", dwStyles[i]);
711 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
712 hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
714 add_band_w(hRebar, NULL, 70, 100, 0);
715 if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
717 add_band_w(hRebar, NULL, 70, 100, 0);
719 MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
721 MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
723 /* try to fool the rebar by sending invalid width/height - won't work */
724 if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
728 pos.hwndInsertAfter = NULL;
734 SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
735 SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
737 SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
740 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
742 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
743 MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
745 DestroyWindow(hRebar);
749 static void expect_band_content(HWND hRebar, UINT uBand, INT fStyle, COLORREF clrFore,
750 COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
751 INT cxMinChild, INT cyMinChild, INT cx, HBITMAP hbmBack, INT wID,
752 INT cyChild, INT cyMaxChild, INT cyIntegral, INT cxIdeal, LPARAM lParam,
753 INT cxHeader, INT cxHeader_broken)
755 CHAR buf[MAX_PATH] = "abc";
758 memset(&rb, 0xdd, sizeof(rb));
759 rb.cbSize = REBARBANDINFOA_V6_SIZE;
760 rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
761 | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
762 | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
765 ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
766 expect_eq(rb.fStyle, fStyle, int, "%x");
767 expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
768 expect_eq(rb.clrBack, clrBack, COLORREF, "%x");
769 expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
770 expect_eq(rb.iImage, iImage, int, "%x");
771 expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
772 expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
773 expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
774 expect_eq(rb.cx, cx, int, "%d");
775 expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
776 expect_eq(rb.wID, wID, int, "%d");
777 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
778 expect_eq(rb.cyChild, cyChild, int, "%x");
779 expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
780 expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
781 expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
782 expect_eq(rb.lParam, lParam, LPARAM, "%ld");
783 ok( rb.cxHeader == cxHeader || broken(rb.cxHeader == cxHeader_broken),
784 "expected %d for %d\n", cxHeader, rb.cxHeader );
787 static void test_bandinfo(void)
790 CHAR szABC[] = "ABC";
791 CHAR szABCD[] = "ABCD";
794 hRebar = create_rebar_control();
795 rb.cbSize = REBARBANDINFOA_V6_SIZE;
797 if (!SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb))
799 win_skip( "V6 info not supported\n" );
800 DestroyWindow(hRebar);
803 expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
805 rb.fMask = RBBIM_CHILDSIZE;
811 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
812 expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
814 rb.fMask = RBBIM_TEXT;
816 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
817 expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35, -1);
819 rb.cbSize = REBARBANDINFOA_V6_SIZE;
821 ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
822 expect_band_content(hRebar, 1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9, -1);
823 expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40, -1);
825 rb.fMask = RBBIM_HEADERSIZE;
827 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
828 expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50, -1);
831 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
832 expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
834 rb.fMask = RBBIM_TEXT;
836 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
837 expect_band_content(hRebar, 0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5, -1);
838 rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
839 rb.fStyle = RBBS_VARIABLEHEIGHT;
841 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
842 expect_band_content(hRebar, 0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40, 5);
844 DestroyWindow(hRebar);
847 static void test_colors(void)
855 hRebar = create_rebar_control();
857 /* test default colors */
858 clr = SendMessage(hRebar, RB_GETTEXTCOLOR, 0, 0);
859 compare(clr, CLR_NONE, "%x");
860 clr = SendMessage(hRebar, RB_GETBKCOLOR, 0, 0);
861 compare(clr, CLR_NONE, "%x");
863 scheme.dwSize = sizeof(scheme);
864 scheme.clrBtnHighlight = 0;
865 scheme.clrBtnShadow = 0;
866 ret = SendMessage(hRebar, RB_GETCOLORSCHEME, 0, (LPARAM)&scheme);
869 compare(scheme.clrBtnHighlight, CLR_DEFAULT, "%x");
870 compare(scheme.clrBtnShadow, CLR_DEFAULT, "%x");
873 skip("RB_GETCOLORSCHEME not supported\n");
875 /* check default band colors */
876 add_band_w(hRebar, "", 0, 10, 10);
877 bi.cbSize = REBARBANDINFOA_V6_SIZE;
878 bi.fMask = RBBIM_COLORS;
879 bi.clrFore = bi.clrBack = 0xc0ffe;
880 ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
881 ok(ret, "RB_GETBANDINFO failed\n");
882 compare(bi.clrFore, RGB(0, 0, 0), "%x");
883 compare(bi.clrBack, GetSysColor(COLOR_3DFACE), "%x");
885 SendMessage(hRebar, RB_SETTEXTCOLOR, 0, RGB(255, 0, 0));
886 bi.clrFore = bi.clrBack = 0xc0ffe;
887 ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
888 ok(ret, "RB_GETBANDINFO failed\n");
889 compare(bi.clrFore, RGB(0, 0, 0), "%x");
891 DestroyWindow(hRebar);
895 static BOOL register_parent_wnd_class(void)
899 wc.style = CS_HREDRAW | CS_VREDRAW;
902 wc.hInstance = GetModuleHandleA(NULL);
904 wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
905 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
906 wc.lpszMenuName = NULL;
907 wc.lpszClassName = "MyTestWnd";
908 wc.lpfnWndProc = MyWndProc;
910 return RegisterClassA(&wc);
913 static HWND create_parent_window(void)
917 if (!register_parent_wnd_class()) return NULL;
919 hwnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
920 CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
921 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
922 NULL, NULL, GetModuleHandleA(NULL), 0);
924 ShowWindow(hwnd, SW_SHOW);
928 static void test_showband(void)
934 hRebar = create_rebar_control();
937 ret = SendMessageA(hRebar, RB_SHOWBAND, 0, TRUE);
938 ok(ret == FALSE, "got %d\n", ret);
940 rbi.cbSize = REBARBANDINFOA_V6_SIZE;
941 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
943 rbi.cxMinChild = 100;
945 rbi.hwndChild = NULL;
946 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
948 /* index out of range */
949 ret = SendMessageA(hRebar, RB_SHOWBAND, 1, TRUE);
950 ok(ret == FALSE, "got %d\n", ret);
952 ret = SendMessageA(hRebar, RB_SHOWBAND, 0, TRUE);
953 ok(ret == TRUE, "got %d\n", ret);
955 DestroyWindow(hRebar);
961 BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
962 INITCOMMONCONTROLSEX iccex;
965 /* LoadLibrary is needed. This file has no references to functions in comctl32 */
966 hComctl32 = LoadLibraryA("comctl32.dll");
967 pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
968 if (!pInitCommonControlsEx)
970 win_skip("InitCommonControlsEx() is missing. Skipping the tests\n");
973 iccex.dwSize = sizeof(iccex);
974 iccex.dwICC = ICC_COOL_CLASSES;
975 pInitCommonControlsEx(&iccex);
977 hMainWnd = create_parent_window();
983 if(!is_font_installed("System") || !is_font_installed("Tahoma"))
985 skip("Missing System or Tahoma font\n");
994 while(GetMessageA(&msg,0,0,0)) {
995 TranslateMessage(&msg);
996 DispatchMessageA(&msg);
998 DestroyWindow(hMainWnd);
1000 FreeLibrary(hComctl32);