comctl32/tests: Remove some superfluous casts around SendMessage().
[wine] / dlls / comctl32 / tests / rebar.c
1 /* Unit tests for rebar.
2  *
3  * Copyright 2007 Mikolaj Zalewski
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /* make sure the structures work with a comctl32 v5.x */
21 #define _WIN32_WINNT 0x500
22 #define _WIN32_IE 0x500
23
24 #include <assert.h>
25 #include <stdarg.h>
26
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <uxtheme.h>
30
31 #include "wine/test.h"
32
33 RECT height_change_notify_rect;
34 static HWND hMainWnd;
35
36
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);
40
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); \
45     }
46
47 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
48
49 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format "  got " format "\n", (value), (ret)); }
50
51 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
52 {
53     return 0;
54 }
55
56 static BOOL is_font_installed(const char *name)
57 {
58     HDC hdc = GetDC(0);
59     BOOL ret = FALSE;
60
61     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
62         ret = TRUE;
63
64     ReleaseDC(0, hdc);
65     return ret;
66 }
67
68 static HWND create_rebar_control(void)
69 {
70     HWND hwnd;
71
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");
75
76     SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
77
78     return hwnd;
79 }
80
81 static HWND build_toolbar(int nr, HWND hParent)
82 {
83     TBBUTTON btns[8];
84     HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
85         hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
86     int iBitmapId = 0;
87     int i;
88
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");
93
94     for (i=0; i<5+nr; i++)
95     {
96         btns[i].iBitmap = i;
97         btns[i].idCommand = i;
98         btns[i].fsStyle = BTNS_BUTTON;
99         btns[i].fsState = TBSTATE_ENABLED;
100         btns[i].iString = 0;
101     }
102
103     switch (nr)
104     {
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;
108     }
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");
111     return hToolbar;
112 }
113
114 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
115 {
116     switch (msg)
117     {
118         case WM_NOTIFY:
119             {
120                 NMHDR *lpnm = (NMHDR *)lParam;
121                 if (lpnm->code == RBN_HEIGHTCHANGE)
122                     GetClientRect(lpnm->hwndFrom, &height_change_notify_rect);
123             }
124             break;
125     }
126     return DefWindowProcA(hWnd, msg, wParam, lParam);
127 }
128
129 #if 0  /* use this to generate more tests*/
130
131 static void dump_sizes(HWND hRebar)
132 {
133     SIZE sz;
134     RECT r;
135     int count;
136     int i, h;
137
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);
142     if (count == 0)
143         printf("0, ");
144     for (i = 0; i < count; i++)  /* rows */
145         printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
146     printf("}, ");
147
148     count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
149     printf("%d, {", count);
150     if (count == 0)
151         printf("{{0, 0, 0, 0}, 0, 0},");
152     for (i=0; i<count; i++)
153     {
154         REBARBANDINFO rbi;
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,
160             rbi.fStyle, rbi.cx);
161     }
162     printf("\n  }, },\n");
163 }
164
165 #define check_sizes() dump_sizes(hRebar);
166 #define check_sizes_todo(todomask) dump_sizes(hRebar);
167
168 #else
169
170 typedef struct {
171     RECT rc;
172     DWORD fStyle;
173     INT cx;
174 } rbband_result_t;
175
176 typedef struct {
177     RECT rcClient;
178     int cyBarHeight;
179     int nRows;
180     int cyRowHeights[50];
181     int nBands;
182     rbband_result_t bands[50];
183 } rbsize_result_t;
184
185 rbsize_result_t rbsize_results[] = {
186   { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
187   }, },
188   { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
189     { {  0,   0, 672,   4}, 0x00, 200},
190   }, },
191   { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
192     { {  0,   0, 200,   4}, 0x00, 200}, { {200,   0, 672,   4}, 0x04, 200},
193   }, },
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},
197   }, },
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},
201   }, },
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},
205   }, },
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},
209   }, },
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},
214   }, },
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},
219   }, },
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},
223   }, },
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},
227   }, },
228   { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
229     { {  0,   0, 604,  34}, 0x00, 200}, { {606,   0, 672,  34}, 0x04, 66},
230   }, },
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},
235   }, },
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},
240   }, },
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},
245   }, },
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},
250   }, },
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},
255   }, },
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},
260   }, },
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},
265   }, },
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},
270   }, },
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},
275   }, },
276   { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
277   }, },
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},
281   }, },
282   { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
283   }, },
284   { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
285     { {  0,   0, 226,  65}, 0x40, 90},
286   }, },
287   { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
288     { {  0,   0,  90,  65}, 0x40, 90}, { { 90,   0, 226,  65}, 0x40, 90},
289   }, },
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},
293   }, },
294 };
295
296 static int rbsize_numtests = 0;
297
298 #define check_sizes_todo(todomask) { \
299         RECT rc; \
300         REBARBANDINFO rbi; \
301         int count, i/*, mask=(todomask)*/; \
302         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); \
311         } \
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"); \
323         } \
324         rbsize_numtests++; \
325     }
326
327 #define check_sizes() check_sizes_todo(0)
328
329 #endif
330
331 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
332 {
333     CHAR buffer[MAX_PATH];
334     REBARBANDINFOA rbi;
335
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;
340     rbi.cx = cx;
341     rbi.cxMinChild = cxMinChild;
342     rbi.cxIdeal = cxIdeal;
343     rbi.cyMinChild = 20;
344     rbi.hwndChild = build_toolbar(1, hRebar);
345     rbi.lpText = (lpszText ? buffer : NULL);
346     SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
347 }
348
349 static void test_layout(void)
350 {
351     HWND hRebar;
352     REBARBANDINFO rbi;
353     HIMAGELIST himl;
354     REBARINFO ri;
355
356     hRebar = create_rebar_control();
357     check_sizes();
358     rbi.cbSize = REBARBANDINFOA_V6_SIZE;
359     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
360     rbi.cx = 200;
361     rbi.cxMinChild = 100;
362     rbi.cyMinChild = 30;
363     rbi.hwndChild = NULL;
364     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
365     check_sizes();
366
367     rbi.fMask |= RBBIM_STYLE;
368     rbi.fStyle = RBBS_CHILDEDGE;
369     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
370     check_sizes();
371
372     rbi.fStyle = 0;
373     rbi.cx = 200;
374     rbi.cxMinChild = 30;
375     rbi.cyMinChild = 30;
376     rbi.hwndChild = build_toolbar(0, hRebar);
377     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
378     check_sizes();
379
380     rbi.fStyle = RBBS_CHILDEDGE;
381     rbi.cx = 68;
382     rbi.hwndChild = build_toolbar(0, hRebar);
383     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
384     check_sizes();
385
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;
389     rbi.cx = 66;
390     SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
391     check_sizes();      /* here it will be relayouted */
392
393     /* this will force a new row */
394     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
395     rbi.cx = 200;
396     rbi.cxMinChild = 400;
397     rbi.cyMinChild = 30;
398     rbi.hwndChild = build_toolbar(0, hRebar);
399     SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
400     check_sizes();
401
402     rbi.fMask = RBBIM_STYLE;
403     rbi.fStyle = RBBS_HIDDEN;
404     SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
405     check_sizes();
406
407     SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
408     check_sizes();
409     SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
410     check_sizes();
411     SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
412     check_sizes();
413
414     DestroyWindow(hRebar);
415
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);
422     check_sizes();
423     SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
424     check_sizes();
425     SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
426     check_sizes();
427     SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
428     check_sizes();
429     SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
430     check_sizes();
431     SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
432     check_sizes();
433
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;
438     ri.himl = himl;
439     ok(SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&ri), "RB_SETBARINFO failed\n");
440     rbi.fMask = RBBIM_IMAGE;
441     rbi.iImage = 1;
442     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
443     check_sizes();
444
445     /* after removing it everything is back to normal*/
446     rbi.iImage = -1;
447     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
448     check_sizes();
449
450     /* Only -1 means that the image is not present. Other invalid values increase the height */
451     rbi.iImage = -2;
452     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
453     check_sizes();
454
455     DestroyWindow(hRebar);
456
457     /* VARHEIGHT resizing test on a horizontal rebar */
458     hRebar = create_rebar_control();
459     SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
460     check_sizes();
461     rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
462     rbi.fStyle = RBBS_VARIABLEHEIGHT;
463     rbi.cxMinChild = 50;
464     rbi.cyMinChild = 10;
465     rbi.cyIntegral = 11;
466     rbi.cyChild = 70;
467     rbi.cyMaxChild = 200;
468     rbi.cx = 90;
469     rbi.hwndChild = build_toolbar(0, hRebar);
470     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
471
472     rbi.cyChild = 50;
473     rbi.hwndChild = build_toolbar(0, hRebar);
474     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
475
476     rbi.cyMinChild = 40;
477     rbi.cyChild = 50;
478     rbi.cyIntegral = 5;
479     rbi.hwndChild = build_toolbar(0, hRebar);
480     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
481     check_sizes();
482
483     DestroyWindow(hRebar);
484
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);
488     check_sizes();
489     rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
490     rbi.fStyle = RBBS_VARIABLEHEIGHT;
491     rbi.cxMinChild = 50;
492     rbi.cyMinChild = 10;
493     rbi.cyIntegral = 11;
494     rbi.cyChild = 70;
495     rbi.cyMaxChild = 90;
496     rbi.cx = 90;
497     rbi.hwndChild = build_toolbar(0, hRebar);
498     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
499     check_sizes();
500
501     rbi.cyChild = 50;
502     rbi.hwndChild = build_toolbar(0, hRebar);
503     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
504     check_sizes();
505
506     rbi.cyMinChild = 40;
507     rbi.cyChild = 50;
508     rbi.cyIntegral = 5;
509     rbi.hwndChild = build_toolbar(0, hRebar);
510     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
511     check_sizes();
512
513     DestroyWindow(hRebar);
514     ImageList_Destroy(himl);
515 }
516
517 #if 0       /* use this to generate more tests */
518
519 static void dump_client(HWND hRebar)
520 {
521     RECT r;
522     BOOL notify;
523     GetWindowRect(hRebar, &r);
524     MapWindowPoints(HWND_DESKTOP, hMainWnd, &r, 2);
525     if (height_change_notify_rect.top != -1)
526     {
527         RECT rcClient;
528         GetClientRect(hRebar, &rcClient);
529         assert(EqualRect(&rcClient, &height_change_notify_rect));
530         notify = TRUE;
531     }
532     else
533         notify = FALSE;
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);
537 }
538
539 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
540 #define check_client() dump_client(hRebar)
541
542 #else
543
544 typedef struct {
545     RECT rc;
546     INT iNumRows;
547     BOOL heightNotify;
548 } rbresize_test_result_t;
549
550 rbresize_test_result_t resize_results[] = {
551 /* style 00000001 */
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},
558 /* style 00000041 */
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},
565 /* style 00000003 */
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},
572 /* style 00000043 */
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},
579 /* style 00000080 */
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},
586 /* style 00000083 */
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},
593 /* style 00000008 */
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},
603 /* style 00000048 */
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},
613 /* style 00000004 */
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},
622 /* style 00000002 */
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},
629 /* style 00000082 */
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},
636 /* style 00800001 */
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},
643 /* style 00800048 */
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},
653 /* style 00800004 */
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},
662 /* style 00800002 */
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},
669 };
670
671 static int resize_numtests = 0;
672
673 #define comment(fmt, arg1)
674 #define check_client() { \
675         RECT r; \
676         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 */ \
682         } else { \
683             check_rect("client", r, res->rc); \
684         } \
685         expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
686         if (res->heightNotify) { \
687             RECT rcClient; \
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); \
692     }
693
694 #endif
695
696 static void test_resize(void)
697 {
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};
702
703     const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
704     int i;
705
706     for (i = 0; i < styles_count; i++)
707     {
708         HWND hRebar;
709
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);
713         check_client();
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 */
716             check_client();
717         add_band_w(hRebar, NULL, 70, 100, 0);
718         check_client();
719         MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
720         check_client();
721         MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
722         check_client();
723         /* try to fool the rebar by sending invalid width/height - won't work */
724         if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
725         {
726             WINDOWPOS pos;
727             pos.hwnd = hRebar;
728             pos.hwndInsertAfter = NULL;
729             pos.cx = 500;
730             pos.cy = 500;
731             pos.x = 10;
732             pos.y = 10;
733             pos.flags = 0;
734             SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
735             SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
736             check_client();
737             SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
738             check_client();
739         }
740         SendMessage(hRebar, RB_DELETEBAND, 0, 0);
741         check_client();
742         SendMessage(hRebar, RB_DELETEBAND, 0, 0);
743         MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
744         check_client();
745         DestroyWindow(hRebar);
746     }
747 }
748
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)
754 {
755     CHAR buf[MAX_PATH] = "abc";
756     REBARBANDINFOA rb;
757
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;
763     rb.lpText = buf;
764     rb.cch = MAX_PATH;
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 );
785 }
786
787 static void test_bandinfo(void)
788 {
789     REBARBANDINFOA rb;
790     CHAR szABC[] = "ABC";
791     CHAR szABCD[] = "ABCD";
792     HWND hRebar;
793
794     hRebar = create_rebar_control();
795     rb.cbSize = REBARBANDINFOA_V6_SIZE;
796     rb.fMask = 0;
797     if (!SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb))
798     {
799         win_skip( "V6 info not supported\n" );
800         DestroyWindow(hRebar);
801         return;
802     }
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);
804
805     rb.fMask = RBBIM_CHILDSIZE;
806     rb.cxMinChild = 15;
807     rb.cyMinChild = 20;
808     rb.cyChild = 30;
809     rb.cyMaxChild = 20;
810     rb.cyIntegral = 10;
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);
813
814     rb.fMask = RBBIM_TEXT;
815     rb.lpText = szABC;
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);
818
819     rb.cbSize = REBARBANDINFOA_V6_SIZE;
820     rb.fMask = 0;
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);
824
825     rb.fMask = RBBIM_HEADERSIZE;
826     rb.cxHeader = 50;
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);
829
830     rb.cxHeader = 5;
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);
833
834     rb.fMask = RBBIM_TEXT;
835     rb.lpText = szABCD;
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;
840     rb.lpText = szABC;
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);
843
844     DestroyWindow(hRebar);
845 }
846
847 static void test_colors(void)
848 {
849     COLORSCHEME scheme;
850     COLORREF clr;
851     BOOL ret;
852     HWND hRebar;
853     REBARBANDINFOA bi;
854
855     hRebar = create_rebar_control();
856
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");
862
863     scheme.dwSize = sizeof(scheme);
864     scheme.clrBtnHighlight = 0;
865     scheme.clrBtnShadow = 0;
866     ret = SendMessage(hRebar, RB_GETCOLORSCHEME, 0, (LPARAM)&scheme);
867     if (ret)
868     {
869         compare(scheme.clrBtnHighlight, CLR_DEFAULT, "%x");
870         compare(scheme.clrBtnShadow, CLR_DEFAULT, "%x");
871     }
872     else
873         skip("RB_GETCOLORSCHEME not supported\n");
874
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");
884
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");
890
891     DestroyWindow(hRebar);
892 }
893
894
895 static BOOL register_parent_wnd_class(void)
896 {
897     WNDCLASSA wc;
898
899     wc.style = CS_HREDRAW | CS_VREDRAW;
900     wc.cbClsExtra = 0;
901     wc.cbWndExtra = 0;
902     wc.hInstance = GetModuleHandleA(NULL);
903     wc.hIcon = 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;
909
910     return RegisterClassA(&wc);
911 }
912
913 static HWND create_parent_window(void)
914 {
915     HWND hwnd;
916
917     if (!register_parent_wnd_class()) return NULL;
918
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);
923
924     ShowWindow(hwnd, SW_SHOW);
925     return hwnd;
926 }
927
928 START_TEST(rebar)
929 {
930     HMODULE hComctl32;
931     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
932     INITCOMMONCONTROLSEX iccex;
933     MSG msg;
934
935     /* LoadLibrary is needed. This file has no references to functions in comctl32 */
936     hComctl32 = LoadLibraryA("comctl32.dll");
937     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
938     if (!pInitCommonControlsEx)
939     {
940         win_skip("InitCommonControlsEx() is missing. Skipping the tests\n");
941         return;
942     }
943     iccex.dwSize = sizeof(iccex);
944     iccex.dwICC = ICC_COOL_CLASSES;
945     pInitCommonControlsEx(&iccex);
946
947     hMainWnd = create_parent_window();
948
949     test_bandinfo();
950     test_colors();
951
952     if(!is_font_installed("System") || !is_font_installed("Tahoma"))
953     {
954         skip("Missing System or Tahoma font\n");
955         goto out;
956     }
957
958     test_layout();
959     test_resize();
960
961 out:
962     PostQuitMessage(0);
963     while(GetMessageA(&msg,0,0,0)) {
964         TranslateMessage(&msg);
965         DispatchMessageA(&msg);
966     }
967     DestroyWindow(hMainWnd);
968
969     FreeLibrary(hComctl32);
970 }