comctl32/tests: Remove commented out struct declaration.
[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 static RECT height_change_notify_rect;
34 static HWND hMainWnd;
35 static int system_font_height;
36
37
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);
41
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); \
46     }
47
48 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
49
50 #define expect_eq(line, expr, value, type, format) { type ret = expr;\
51         ok((value) == ret, #expr " expected " format "  got " format " from line %d\n", (value), (ret), line); }
52
53 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
54 {
55     return 0;
56 }
57
58 static BOOL is_font_installed(const char *name)
59 {
60     HDC hdc = GetDC(0);
61     BOOL ret = FALSE;
62
63     if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
64         ret = TRUE;
65
66     ReleaseDC(0, hdc);
67     return ret;
68 }
69
70 static void init_system_font_height(void) {
71     HDC hDC;
72     TEXTMETRIC tm;
73
74     hDC = CreateCompatibleDC(NULL);
75     GetTextMetrics(hDC, &tm);
76     DeleteDC(NULL);
77
78     system_font_height = tm.tmHeight;
79 }
80
81 static HWND create_rebar_control(void)
82 {
83     HWND hwnd;
84
85     hwnd = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
86         hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
87     ok(hwnd != NULL, "Failed to create Rebar\n");
88
89     SendMessageA(hwnd, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
90
91     return hwnd;
92 }
93
94 static HWND build_toolbar(int nr, HWND hParent)
95 {
96     TBBUTTON btns[8];
97     HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
98         hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
99     int iBitmapId = 0;
100     int i;
101
102     ok(hToolbar != NULL, "Toolbar creation problem\n");
103     ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
104     ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
105     ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
106
107     for (i=0; i<5+nr; i++)
108     {
109         btns[i].iBitmap = i;
110         btns[i].idCommand = i;
111         btns[i].fsStyle = BTNS_BUTTON;
112         btns[i].fsState = TBSTATE_ENABLED;
113         btns[i].iString = 0;
114     }
115
116     switch (nr)
117     {
118         case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
119         case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
120         case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
121     }
122     ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGES failed\n");
123     ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
124     return hToolbar;
125 }
126
127 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
128 {
129     switch (msg)
130     {
131         case WM_NOTIFY:
132             {
133                 NMHDR *lpnm = (NMHDR *)lParam;
134                 if (lpnm->code == RBN_HEIGHTCHANGE)
135                     GetClientRect(lpnm->hwndFrom, &height_change_notify_rect);
136             }
137             break;
138     }
139     return DefWindowProcA(hWnd, msg, wParam, lParam);
140 }
141
142 #if 0  /* use this to generate more tests*/
143
144 static void dump_sizes(HWND hRebar)
145 {
146     SIZE sz;
147     RECT r;
148     int count;
149     int i, h;
150
151     GetClientRect(hRebar, &r);
152     count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
153     printf("  { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
154         SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
155     if (count == 0)
156         printf("0, ");
157     for (i = 0; i < count; i++)  /* rows */
158         printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
159     printf("}, ");
160
161     count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
162     printf("%d, {", count);
163     if (count == 0)
164         printf("{{0, 0, 0, 0}, 0, 0},");
165     for (i=0; i<count; i++)
166     {
167         REBARBANDINFO rbi;
168         rbi.cbSize = REBARBANDINFOA_V6_SIZE;
169         rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
170         ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
171         ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
172         printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n    " : ""), r.left, r.top, r.right, r.bottom,
173             rbi.fStyle, rbi.cx);
174     }
175     printf("\n  }, },\n");
176 }
177
178 #define check_sizes() dump_sizes(hRebar);
179 #define check_sizes_todo(todomask) dump_sizes(hRebar);
180
181 #else
182
183 static int string_width(const CHAR *s) {
184     SIZE sz;
185     HDC hdc;
186
187     hdc = CreateCompatibleDC(NULL);
188     GetTextExtentPoint32A(hdc, s, strlen(s), &sz);
189     DeleteDC(hdc);
190
191     return sz.cx;
192 }
193
194 typedef struct {
195     RECT rc;
196     DWORD fStyle;
197     UINT cx;
198 } rbband_result_t;
199
200 typedef struct {
201     RECT rcClient;
202     int cyBarHeight;
203     int nRows;
204     int *cyRowHeights;
205     int nBands;
206     rbband_result_t *bands;
207 } rbsize_result_t;
208
209 static rbsize_result_t rbsize_init(int cleft, int ctop, int cright, int cbottom, int cyBarHeight, int nRows, int nBands)
210 {
211     rbsize_result_t ret;
212
213     SetRect(&ret.rcClient, cleft, ctop, cright, cbottom);
214     ret.cyBarHeight = cyBarHeight;
215     ret.nRows = 0;
216     ret.cyRowHeights = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nRows*sizeof(int));
217     ret.nBands = 0;
218     ret.bands = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nBands*sizeof(rbband_result_t));
219
220     return ret;
221 }
222
223 static void rbsize_add_row(rbsize_result_t *rbsr, int rowHeight) {
224     rbsr->cyRowHeights[rbsr->nRows] = rowHeight;
225     rbsr->nRows++;
226 }
227
228 static void rbsize_add_band(rbsize_result_t *rbsr, int left, int top, int right, int bottom, DWORD fStyle, UINT cx)
229 {
230     SetRect(&(rbsr->bands[rbsr->nBands].rc), left, top, right, bottom);
231     rbsr->bands[rbsr->nBands].fStyle = fStyle;
232     rbsr->bands[rbsr->nBands].cx = cx;
233     rbsr->nBands++;
234 }
235
236 static rbsize_result_t *rbsize_results;
237
238 #define rbsize_results_num 27
239
240 static void rbsize_results_init(void)
241 {
242     rbsize_results = HeapAlloc(GetProcessHeap(), 0, rbsize_results_num*sizeof(rbsize_result_t));
243
244     rbsize_results[0] = rbsize_init(0, 0, 672, 0, 0, 0, 0);
245
246     rbsize_results[1] = rbsize_init(0, 0, 672, 4, 4, 1, 1);
247     rbsize_add_row(&rbsize_results[1], 4);
248     rbsize_add_band(&rbsize_results[1], 0, 0, 672, 4, 0x00, 200);
249
250     rbsize_results[2] = rbsize_init(0, 0, 672, 4, 4, 1, 2);
251     rbsize_add_row(&rbsize_results[2], 4);
252     rbsize_add_band(&rbsize_results[2], 0, 0, 200, 4, 0x00, 200);
253     rbsize_add_band(&rbsize_results[2], 200, 0, 672, 4, 0x04, 200);
254
255     rbsize_results[3] = rbsize_init(0, 0, 672, 30, 30, 1, 3);
256     rbsize_add_row(&rbsize_results[3], 30);
257     rbsize_add_band(&rbsize_results[3], 0, 0, 200, 30, 0x00, 200);
258     rbsize_add_band(&rbsize_results[3], 200, 0, 400, 30, 0x04, 200);
259     rbsize_add_band(&rbsize_results[3], 400, 0, 672, 30, 0x00, 200);
260
261     rbsize_results[4] = rbsize_init(0, 0, 672, 34, 34, 1, 4);
262     rbsize_add_row(&rbsize_results[4], 34);
263     rbsize_add_band(&rbsize_results[4], 0, 0, 200, 34, 0x00, 200);
264     rbsize_add_band(&rbsize_results[4], 200, 0, 400, 34, 0x04, 200);
265     rbsize_add_band(&rbsize_results[4], 400, 0, 604, 34, 0x00, 200);
266     rbsize_add_band(&rbsize_results[4], 604, 0, 672, 34, 0x04, 68);
267
268     rbsize_results[5] = rbsize_init(0, 0, 672, 34, 34, 1, 4);
269     rbsize_add_row(&rbsize_results[5], 34);
270     rbsize_add_band(&rbsize_results[5], 0, 0, 200, 34, 0x00, 200);
271     rbsize_add_band(&rbsize_results[5], 200, 0, 400, 34, 0x04, 200);
272     rbsize_add_band(&rbsize_results[5], 400, 0, 604, 34, 0x00, 200);
273     rbsize_add_band(&rbsize_results[5], 604, 0, 672, 34, 0x04, 68);
274
275     rbsize_results[6] = rbsize_init(0, 0, 672, 34, 34, 1, 4);
276     rbsize_add_row(&rbsize_results[6], 34);
277     rbsize_add_band(&rbsize_results[6], 0, 0, 200, 34, 0x00, 200);
278     rbsize_add_band(&rbsize_results[6], 202, 0, 402, 34, 0x04, 200);
279     rbsize_add_band(&rbsize_results[6], 404, 0, 604, 34, 0x00, 200);
280     rbsize_add_band(&rbsize_results[6], 606, 0, 672, 34, 0x04, 66);
281
282     rbsize_results[7] = rbsize_init(0, 0, 672, 70, 70, 2, 5);
283     rbsize_add_row(&rbsize_results[7], 34);
284     rbsize_add_row(&rbsize_results[7], 34);
285     rbsize_add_band(&rbsize_results[7], 0, 0, 142, 34, 0x00, 200);
286     rbsize_add_band(&rbsize_results[7], 144, 0, 557, 34, 0x00, 200);
287     rbsize_add_band(&rbsize_results[7], 559, 0, 672, 34, 0x04, 200);
288     rbsize_add_band(&rbsize_results[7], 0, 36, 200, 70, 0x00, 200);
289     rbsize_add_band(&rbsize_results[7], 202, 36, 672, 70, 0x04, 66);
290
291     rbsize_results[8] = rbsize_init(0, 0, 672, 34, 34, 1, 5);
292     rbsize_add_row(&rbsize_results[8], 34);
293     rbsize_add_band(&rbsize_results[8], 0, 0, 167, 34, 0x00, 200);
294     rbsize_add_band(&rbsize_results[8], 169, 0, 582, 34, 0x00, 200);
295     rbsize_add_band(&rbsize_results[8], 559, 0, 759, 34, 0x08, 200);
296     rbsize_add_band(&rbsize_results[8], 584, 0, 627, 34, 0x00, 200);
297     rbsize_add_band(&rbsize_results[8], 629, 0, 672, 34, 0x04, 66);
298
299     rbsize_results[9] = rbsize_init(0, 0, 672, 34, 34, 1, 4);
300     rbsize_add_row(&rbsize_results[9], 34);
301     rbsize_add_band(&rbsize_results[9], 0, 0, 167, 34, 0x00, 200);
302     rbsize_add_band(&rbsize_results[9], 169, 0, 582, 34, 0x00, 200);
303     rbsize_add_band(&rbsize_results[9], 584, 0, 627, 34, 0x00, 200);
304     rbsize_add_band(&rbsize_results[9], 629, 0, 672, 34, 0x04, 66);
305
306     rbsize_results[10] = rbsize_init(0, 0, 672, 34, 34, 1, 3);
307     rbsize_add_row(&rbsize_results[10], 34);
308     rbsize_add_band(&rbsize_results[10], 0, 0, 413, 34, 0x00, 200);
309     rbsize_add_band(&rbsize_results[10], 415, 0, 615, 34, 0x00, 200);
310     rbsize_add_band(&rbsize_results[10], 617, 0, 672, 34, 0x04, 66);
311
312     rbsize_results[11] = rbsize_init(0, 0, 672, 34, 34, 1, 2);
313     rbsize_add_row(&rbsize_results[11], 34);
314     rbsize_add_band(&rbsize_results[11], 0, 0, 604, 34, 0x00, 200);
315     rbsize_add_band(&rbsize_results[11], 606, 0, 672, 34, 0x04, 66);
316
317     rbsize_results[12] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
318     rbsize_add_row(&rbsize_results[12], 4 + system_font_height);
319     rbsize_add_row(&rbsize_results[12], 4 + system_font_height);
320     rbsize_add_band(&rbsize_results[12], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
321     rbsize_add_band(&rbsize_results[12], 87 + string_width("ABC"), 0, 157 + string_width("ABC"), 4 + system_font_height, 0x00, 70);
322     rbsize_add_band(&rbsize_results[12], 157 + string_width("ABC"), 0, 397 + string_width("ABC"), 4 + system_font_height, 0x00, 240);
323     rbsize_add_band(&rbsize_results[12], 397 + string_width("ABC"), 0, 672, 4 + system_font_height, 0x00, 60);
324     rbsize_add_band(&rbsize_results[12], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
325
326     rbsize_results[13] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
327     rbsize_add_row(&rbsize_results[13], 4 + system_font_height);
328     rbsize_add_row(&rbsize_results[13], 4 + system_font_height);
329     rbsize_add_band(&rbsize_results[13], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
330     rbsize_add_band(&rbsize_results[13], 87 + string_width("ABC"), 0, 200 + string_width("ABC"), 4 + system_font_height, 0x00, 113);
331     rbsize_add_band(&rbsize_results[13], 200 + string_width("ABC"), 0, 397 + string_width("ABC"), 4 + system_font_height, 0x00, 197);
332     rbsize_add_band(&rbsize_results[13], 397 + string_width("ABC"), 0, 672, 4 + system_font_height, 0x00, 60);
333     rbsize_add_band(&rbsize_results[13], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
334
335     rbsize_results[14] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
336     rbsize_add_row(&rbsize_results[14], 4 + system_font_height);
337     rbsize_add_row(&rbsize_results[14], 4 + system_font_height);
338     rbsize_add_band(&rbsize_results[14], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
339     rbsize_add_band(&rbsize_results[14], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
340     rbsize_add_band(&rbsize_results[14], 412 - string_width("MMMMMMM"), 0, 595 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 183);
341     rbsize_add_band(&rbsize_results[14], 595 - string_width("MMMMMMM"), 0, 672, 4 + system_font_height, 0x00, 77 + string_width("MMMMMMM"));
342     rbsize_add_band(&rbsize_results[14], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
343
344     rbsize_results[15] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
345     rbsize_add_row(&rbsize_results[15], 4 + system_font_height);
346     rbsize_add_row(&rbsize_results[15], 4 + system_font_height);
347     rbsize_add_band(&rbsize_results[15], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
348     rbsize_add_band(&rbsize_results[15], 87 + string_width("ABC"), 0, 140 + string_width("ABC"), 4 + system_font_height, 0x00, 53);
349     rbsize_add_band(&rbsize_results[15], 140 + string_width("ABC"), 0, 595 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 455 - string_width("MMMMMMM") - string_width("ABC"));
350     rbsize_add_band(&rbsize_results[15], 595 - string_width("MMMMMMM"), 0, 672, 4 + system_font_height, 0x00, 77 + string_width("MMMMMMM"));
351     rbsize_add_band(&rbsize_results[15], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
352
353     rbsize_results[16] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
354     rbsize_add_row(&rbsize_results[16], 4 + system_font_height);
355     rbsize_add_row(&rbsize_results[16], 4 + system_font_height);
356     rbsize_add_band(&rbsize_results[16], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
357     rbsize_add_band(&rbsize_results[16], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
358     rbsize_add_band(&rbsize_results[16], 412 - string_width("MMMMMMM"), 0, 595 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 183);
359     rbsize_add_band(&rbsize_results[16], 595 - string_width("MMMMMMM"), 0, 672, 4 + system_font_height, 0x00, 77 + string_width("MMMMMMM"));
360     rbsize_add_band(&rbsize_results[16], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
361
362     rbsize_results[17] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
363     rbsize_add_row(&rbsize_results[17], 4 + system_font_height);
364     rbsize_add_row(&rbsize_results[17], 4 + system_font_height);
365     rbsize_add_band(&rbsize_results[17], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
366     rbsize_add_band(&rbsize_results[17], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
367     rbsize_add_band(&rbsize_results[17], 412 - string_width("MMMMMMM"), 0, 595 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 183);
368     rbsize_add_band(&rbsize_results[17], 595 - string_width("MMMMMMM"), 0, 672, 4 + system_font_height, 0x00, 77 + string_width("MMMMMMM"));
369     rbsize_add_band(&rbsize_results[17], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
370
371     rbsize_results[18] = rbsize_init(0, 0, 672, 56, 56, 2, 5);
372     rbsize_add_row(&rbsize_results[18], 28);
373     rbsize_add_row(&rbsize_results[18], 28);
374     rbsize_add_band(&rbsize_results[18], 0, 0, 87 + string_width("ABC"), 28, 0x00, 40);
375     rbsize_add_band(&rbsize_results[18], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 28, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
376     rbsize_add_band(&rbsize_results[18], 412 - string_width("MMMMMMM"), 0, 595 - string_width("MMMMMMM"), 28, 0x00, 183);
377     rbsize_add_band(&rbsize_results[18], 595 - string_width("MMMMMMM"), 0, 672, 28, 0x00, 77 + string_width("MMMMMMM"));
378     rbsize_add_band(&rbsize_results[18], 0, 28, 672, 56, 0x00, 200);
379
380     rbsize_results[19] = rbsize_init(0, 0, 672, 8 + 2*system_font_height, 40, 2, 5);
381     rbsize_add_row(&rbsize_results[19], 4 + system_font_height);
382     rbsize_add_row(&rbsize_results[19], 4 + system_font_height);
383     rbsize_add_band(&rbsize_results[19], 0, 0, 87 + string_width("ABC"), 4 + system_font_height, 0x00, 40);
384     rbsize_add_band(&rbsize_results[19], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
385     rbsize_add_band(&rbsize_results[19], 412 - string_width("MMMMMMM"), 0, 595 - string_width("MMMMMMM"), 4 + system_font_height, 0x00, 183);
386     rbsize_add_band(&rbsize_results[19], 595 - string_width("MMMMMMM"), 0, 672, 4 + system_font_height, 0x00, 77 + string_width("MMMMMMM"));
387     rbsize_add_band(&rbsize_results[19], 0, 4 + system_font_height, 672, 8 + 2*system_font_height, 0x00, 200);
388
389     rbsize_results[20] = rbsize_init(0, 0, 672, 56, 56, 2, 5);
390     rbsize_add_row(&rbsize_results[20], 28);
391     rbsize_add_row(&rbsize_results[20], 28);
392     rbsize_add_band(&rbsize_results[20], 0, 0, 87 + string_width("ABC"), 28, 0x00, 40);
393     rbsize_add_band(&rbsize_results[20], 87 + string_width("ABC"), 0, 412 - string_width("MMMMMMM"), 28, 0x00, 325 - string_width("ABC") - string_width("MMMMMMM"));
394     rbsize_add_band(&rbsize_results[20], 412 - string_width("MMMMMMM"), 0,  595 - string_width("MMMMMMM"), 28, 0x00, 183);
395     rbsize_add_band(&rbsize_results[20],  595 - string_width("MMMMMMM"), 0, 672, 28, 0x00, 77 + string_width("MMMMMMM"));
396     rbsize_add_band(&rbsize_results[20], 0, 28, 672, 56, 0x00, 200);
397
398     rbsize_results[21] = rbsize_init(0, 0, 672, 0, 0, 0, 0);
399
400     rbsize_results[22] = rbsize_init(0, 0, 672, 65, 56, 1, 3);
401     rbsize_add_row(&rbsize_results[22], 65);
402     rbsize_add_band(&rbsize_results[22], 0, 0, 90, 65, 0x40, 90);
403     rbsize_add_band(&rbsize_results[22], 90, 0, 180, 65, 0x40, 90);
404     rbsize_add_band(&rbsize_results[22], 180, 0, 672, 65, 0x40, 90);
405
406     rbsize_results[23] = rbsize_init(0, 0, 0, 226, 0, 0, 0);
407
408     rbsize_results[24] = rbsize_init(0, 0, 65, 226, 65, 1, 1);
409     rbsize_add_row(&rbsize_results[24], 65);
410     rbsize_add_band(&rbsize_results[24], 0, 0, 226, 65, 0x40, 90);
411
412     rbsize_results[25] = rbsize_init(0, 0, 65, 226, 65, 1, 2);
413     rbsize_add_row(&rbsize_results[25], 65);
414     rbsize_add_band(&rbsize_results[25], 0, 0, 90, 65, 0x40, 90);
415     rbsize_add_band(&rbsize_results[25], 90, 0, 226, 65, 0x40, 90);
416
417     rbsize_results[26] = rbsize_init(0, 0, 65, 226, 65, 1, 3);
418     rbsize_add_row(&rbsize_results[26], 65);
419     rbsize_add_band(&rbsize_results[26], 0, 0, 90, 65, 0x40, 90);
420     rbsize_add_band(&rbsize_results[26], 90, 0, 163, 65, 0x40, 90);
421     rbsize_add_band(&rbsize_results[26], 163, 0, 226, 65, 0x40, 90);
422 }
423
424 static void rbsize_results_free(void)
425 {
426     int i;
427
428     for (i = 0; i < rbsize_results_num; i++) {
429         HeapFree(GetProcessHeap(), 0, rbsize_results[i].cyRowHeights);
430         HeapFree(GetProcessHeap(), 0, rbsize_results[i].bands);
431     }
432     HeapFree(GetProcessHeap(), 0, rbsize_results);
433     rbsize_results = NULL;
434 }
435
436 static int rbsize_numtests = 0;
437
438 #define check_sizes_todo(todomask) { \
439         RECT rc; \
440         REBARBANDINFO rbi; \
441         int count, i/*, mask=(todomask)*/; \
442         const rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
443         GetClientRect(hRebar, &rc); \
444         check_rect("client", rc, res->rcClient); \
445         count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
446         compare(count, res->nRows, "%d"); \
447         for (i=0; i<min(count, res->nRows); i++) { \
448             int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
449             ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
450         } \
451         count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
452         compare(count, res->nBands, "%d"); \
453         for (i=0; i<min(count, res->nBands); i++) { \
454             ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \
455             if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
456                 check_rect("band", rc, res->bands[i].rc); \
457             rbi.cbSize = REBARBANDINFOA_V6_SIZE; \
458             rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
459             ok(SendMessageA(hRebar, RB_GETBANDINFO,  i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
460             compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
461             compare(rbi.cx, res->bands[i].cx, "%d"); \
462         } \
463         rbsize_numtests++; \
464     }
465
466 #define check_sizes() check_sizes_todo(0)
467
468 #endif
469
470 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
471 {
472     CHAR buffer[MAX_PATH];
473     REBARBANDINFOA rbi;
474
475     if (lpszText != NULL)
476         strcpy(buffer, lpszText);
477     rbi.cbSize = REBARBANDINFOA_V6_SIZE;
478     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
479     rbi.cx = cx;
480     rbi.cxMinChild = cxMinChild;
481     rbi.cxIdeal = cxIdeal;
482     rbi.cyMinChild = 20;
483     rbi.hwndChild = build_toolbar(1, hRebar);
484     rbi.lpText = (lpszText ? buffer : NULL);
485     SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
486 }
487
488 static void test_layout(void)
489 {
490     HWND hRebar;
491     REBARBANDINFO rbi;
492     HIMAGELIST himl;
493     REBARINFO ri;
494
495     rbsize_results_init();
496
497     hRebar = create_rebar_control();
498     check_sizes();
499     rbi.cbSize = REBARBANDINFOA_V6_SIZE;
500     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
501     rbi.cx = 200;
502     rbi.cxMinChild = 100;
503     rbi.cyMinChild = 30;
504     rbi.hwndChild = NULL;
505     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
506     check_sizes();
507
508     rbi.fMask |= RBBIM_STYLE;
509     rbi.fStyle = RBBS_CHILDEDGE;
510     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
511     check_sizes();
512
513     rbi.fStyle = 0;
514     rbi.cx = 200;
515     rbi.cxMinChild = 30;
516     rbi.cyMinChild = 30;
517     rbi.hwndChild = build_toolbar(0, hRebar);
518     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
519     check_sizes();
520
521     rbi.fStyle = RBBS_CHILDEDGE;
522     rbi.cx = 68;
523     rbi.hwndChild = build_toolbar(0, hRebar);
524     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
525     check_sizes();
526
527     SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
528     check_sizes();      /* a style change won't start a relayout */
529     rbi.fMask = RBBIM_SIZE;
530     rbi.cx = 66;
531     SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
532     check_sizes();      /* here it will be relayouted */
533
534     /* this will force a new row */
535     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
536     rbi.cx = 200;
537     rbi.cxMinChild = 400;
538     rbi.cyMinChild = 30;
539     rbi.hwndChild = build_toolbar(0, hRebar);
540     SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
541     check_sizes();
542
543     rbi.fMask = RBBIM_STYLE;
544     rbi.fStyle = RBBS_HIDDEN;
545     SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
546     check_sizes();
547
548     SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
549     check_sizes();
550     SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
551     check_sizes();
552     SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
553     check_sizes();
554
555     DestroyWindow(hRebar);
556
557     hRebar = create_rebar_control();
558     add_band_w(hRebar, "ABC",     70,  40, 100);
559     add_band_w(hRebar, NULL,      40,  70, 100);
560     add_band_w(hRebar, NULL,     170, 240, 100);
561     add_band_w(hRebar, "MMMMMMM", 60,  60, 100);
562     add_band_w(hRebar, NULL,     200, 200, 100);
563     check_sizes();
564     SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
565     check_sizes();
566     SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
567     check_sizes();
568     SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
569     check_sizes();
570     SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
571     check_sizes();
572     SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
573     check_sizes();
574
575     /* an image will increase the band height */
576     himl = ImageList_LoadImage(LoadLibrary("comctl32"), MAKEINTRESOURCE(121), 24, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
577     ri.cbSize = sizeof(ri);
578     ri.fMask = RBIM_IMAGELIST;
579     ri.himl = himl;
580     ok(SendMessage(hRebar, RB_SETBARINFO, 0, (LPARAM)&ri), "RB_SETBARINFO failed\n");
581     rbi.fMask = RBBIM_IMAGE;
582     rbi.iImage = 1;
583     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
584     check_sizes();
585
586     /* after removing it everything is back to normal*/
587     rbi.iImage = -1;
588     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
589     check_sizes();
590
591     /* Only -1 means that the image is not present. Other invalid values increase the height */
592     rbi.iImage = -2;
593     SendMessage(hRebar, RB_SETBANDINFO, 1, (LPARAM)&rbi);
594     check_sizes();
595
596     DestroyWindow(hRebar);
597
598     /* VARHEIGHT resizing test on a horizontal rebar */
599     hRebar = create_rebar_control();
600     SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
601     check_sizes();
602     rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
603     rbi.fStyle = RBBS_VARIABLEHEIGHT;
604     rbi.cxMinChild = 50;
605     rbi.cyMinChild = 10;
606     rbi.cyIntegral = 11;
607     rbi.cyChild = 70;
608     rbi.cyMaxChild = 200;
609     rbi.cx = 90;
610     rbi.hwndChild = build_toolbar(0, hRebar);
611     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
612
613     rbi.cyChild = 50;
614     rbi.hwndChild = build_toolbar(0, hRebar);
615     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
616
617     rbi.cyMinChild = 40;
618     rbi.cyChild = 50;
619     rbi.cyIntegral = 5;
620     rbi.hwndChild = build_toolbar(0, hRebar);
621     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
622     check_sizes();
623
624     DestroyWindow(hRebar);
625
626     /* VARHEIGHT resizing on a vertical rebar */
627     hRebar = create_rebar_control();
628     SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
629     check_sizes();
630     rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
631     rbi.fStyle = RBBS_VARIABLEHEIGHT;
632     rbi.cxMinChild = 50;
633     rbi.cyMinChild = 10;
634     rbi.cyIntegral = 11;
635     rbi.cyChild = 70;
636     rbi.cyMaxChild = 90;
637     rbi.cx = 90;
638     rbi.hwndChild = build_toolbar(0, hRebar);
639     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
640     check_sizes();
641
642     rbi.cyChild = 50;
643     rbi.hwndChild = build_toolbar(0, hRebar);
644     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
645     check_sizes();
646
647     rbi.cyMinChild = 40;
648     rbi.cyChild = 50;
649     rbi.cyIntegral = 5;
650     rbi.hwndChild = build_toolbar(0, hRebar);
651     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
652     check_sizes();
653
654     rbsize_results_free();
655     DestroyWindow(hRebar);
656     ImageList_Destroy(himl);
657 }
658
659 #if 0       /* use this to generate more tests */
660
661 static void dump_client(HWND hRebar)
662 {
663     RECT r;
664     BOOL notify;
665     GetWindowRect(hRebar, &r);
666     MapWindowPoints(HWND_DESKTOP, hMainWnd, &r, 2);
667     if (height_change_notify_rect.top != -1)
668     {
669         RECT rcClient;
670         GetClientRect(hRebar, &rcClient);
671         assert(EqualRect(&rcClient, &height_change_notify_rect));
672         notify = TRUE;
673     }
674     else
675         notify = FALSE;
676     printf("    {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
677         notify ? "TRUE" : "FALSE");
678     SetRect(&height_change_notify_rect, -1, -1, -1, -1);
679 }
680
681 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
682 #define check_client() dump_client(hRebar)
683
684 #else
685
686 typedef struct {
687     RECT rc;
688     INT iNumRows;
689     BOOL heightNotify;
690 } rbresize_test_result_t;
691
692 static const rbresize_test_result_t resize_results[] = {
693 /* style 00000001 */
694     {{0, 2, 672, 2}, 0, FALSE},
695     {{0, 2, 672, 22}, 1, TRUE},
696     {{0, 2, 672, 22}, 1, FALSE},
697     {{0, 2, 672, 22}, 1, FALSE},
698     {{0, 2, 672, 22}, 1, FALSE},
699     {{0, 2, 672, 22}, 0, FALSE},
700 /* style 00000041 */
701     {{0, 0, 672, 0}, 0, FALSE},
702     {{0, 0, 672, 20}, 1, TRUE},
703     {{0, 0, 672, 20}, 1, FALSE},
704     {{0, 0, 672, 20}, 1, FALSE},
705     {{0, 0, 672, 20}, 1, FALSE},
706     {{0, 0, 672, 20}, 0, FALSE},
707 /* style 00000003 */
708     {{0, 226, 672, 226}, 0, FALSE},
709     {{0, 206, 672, 226}, 1, TRUE},
710     {{0, 206, 672, 226}, 1, FALSE},
711     {{0, 206, 672, 226}, 1, FALSE},
712     {{0, 206, 672, 226}, 1, FALSE},
713     {{0, 206, 672, 226}, 0, FALSE},
714 /* style 00000043 */
715     {{0, 226, 672, 226}, 0, FALSE},
716     {{0, 206, 672, 226}, 1, TRUE},
717     {{0, 206, 672, 226}, 1, FALSE},
718     {{0, 206, 672, 226}, 1, FALSE},
719     {{0, 206, 672, 226}, 1, FALSE},
720     {{0, 206, 672, 226}, 0, FALSE},
721 /* style 00000080 */
722     {{2, 0, 2, 226}, 0, FALSE},
723     {{2, 0, 22, 226}, 1, TRUE},
724     {{2, 0, 22, 226}, 1, FALSE},
725     {{2, 0, 22, 226}, 1, FALSE},
726     {{2, 0, 22, 226}, 1, FALSE},
727     {{2, 0, 22, 226}, 0, FALSE},
728 /* style 00000083 */
729     {{672, 0, 672, 226}, 0, FALSE},
730     {{652, 0, 672, 226}, 1, TRUE},
731     {{652, 0, 672, 226}, 1, FALSE},
732     {{652, 0, 672, 226}, 1, FALSE},
733     {{652, 0, 672, 226}, 1, FALSE},
734     {{652, 0, 672, 226}, 0, FALSE},
735 /* style 00000008 */
736     {{10, 11, 510, 11}, 0, FALSE},
737     {{10, 15, 510, 35}, 1, TRUE},
738     {{10, 17, 510, 37}, 1, FALSE},
739     {{10, 14, 110, 54}, 2, TRUE},
740     {{0, 4, 0, 44}, 2, FALSE},
741     {{0, 6, 0, 46}, 2, FALSE},
742     {{0, 8, 0, 48}, 2, FALSE},
743     {{0, 12, 0, 32}, 1, TRUE},
744     {{0, 4, 100, 24}, 0, FALSE},
745 /* style 00000048 */
746     {{10, 5, 510, 5}, 0, FALSE},
747     {{10, 5, 510, 25}, 1, TRUE},
748     {{10, 5, 510, 25}, 1, FALSE},
749     {{10, 10, 110, 50}, 2, TRUE},
750     {{0, 0, 0, 40}, 2, FALSE},
751     {{0, 0, 0, 40}, 2, FALSE},
752     {{0, 0, 0, 40}, 2, FALSE},
753     {{0, 0, 0, 20}, 1, TRUE},
754     {{0, 0, 100, 20}, 0, FALSE},
755 /* style 00000004 */
756     {{10, 5, 510, 20}, 0, FALSE},
757     {{10, 5, 510, 20}, 1, TRUE},
758     {{10, 10, 110, 110}, 2, TRUE},
759     {{0, 0, 0, 0}, 2, FALSE},
760     {{0, 0, 0, 0}, 2, FALSE},
761     {{0, 0, 0, 0}, 2, FALSE},
762     {{0, 0, 0, 0}, 1, TRUE},
763     {{0, 0, 100, 100}, 0, FALSE},
764 /* style 00000002 */
765     {{0, 5, 672, 5}, 0, FALSE},
766     {{0, 5, 672, 25}, 1, TRUE},
767     {{0, 10, 672, 30}, 1, FALSE},
768     {{0, 0, 672, 20}, 1, FALSE},
769     {{0, 0, 672, 20}, 1, FALSE},
770     {{0, 0, 672, 20}, 0, FALSE},
771 /* style 00000082 */
772     {{10, 0, 10, 226}, 0, FALSE},
773     {{10, 0, 30, 226}, 1, TRUE},
774     {{10, 0, 30, 226}, 1, FALSE},
775     {{0, 0, 20, 226}, 1, FALSE},
776     {{0, 0, 20, 226}, 1, FALSE},
777     {{0, 0, 20, 226}, 0, FALSE},
778 /* style 00800001 */
779     {{-2, 0, 674, 4}, 0, FALSE},
780     {{-2, 0, 674, 24}, 1, TRUE},
781     {{-2, 0, 674, 24}, 1, FALSE},
782     {{-2, 0, 674, 24}, 1, FALSE},
783     {{-2, 0, 674, 24}, 1, FALSE},
784     {{-2, 0, 674, 24}, 0, FALSE},
785 /* style 00800048 */
786     {{10, 5, 510, 9}, 0, FALSE},
787     {{10, 5, 510, 29}, 1, TRUE},
788     {{10, 5, 510, 29}, 1, FALSE},
789     {{10, 10, 110, 54}, 2, TRUE},
790     {{0, 0, 0, 44}, 2, FALSE},
791     {{0, 0, 0, 44}, 2, FALSE},
792     {{0, 0, 0, 44}, 2, FALSE},
793     {{0, 0, 0, 24}, 1, TRUE},
794     {{0, 0, 100, 24}, 0, FALSE},
795 /* style 00800004 */
796     {{10, 5, 510, 20}, 0, FALSE},
797     {{10, 5, 510, 20}, 1, TRUE},
798     {{10, 10, 110, 110}, 2, TRUE},
799     {{0, 0, 0, 0}, 2, FALSE},
800     {{0, 0, 0, 0}, 2, FALSE},
801     {{0, 0, 0, 0}, 2, FALSE},
802     {{0, 0, 0, 0}, 1, TRUE},
803     {{0, 0, 100, 100}, 0, FALSE},
804 /* style 00800002 */
805     {{-2, 5, 674, 9}, 0, FALSE},
806     {{-2, 5, 674, 29}, 1, TRUE},
807     {{-2, 10, 674, 34}, 1, FALSE},
808     {{-2, 0, 674, 24}, 1, FALSE},
809     {{-2, 0, 674, 24}, 1, FALSE},
810     {{-2, 0, 674, 24}, 0, FALSE},
811 };
812
813 static DWORD resize_numtests = 0;
814
815 #define comment(fmt, arg1)
816 #define check_client() { \
817         RECT r; \
818         int value; \
819         const rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
820         assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
821         GetWindowRect(hRebar, &r); \
822         MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
823         if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
824             check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
825         } else { \
826             check_rect("client", r, res->rc); \
827         } \
828         value = (int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
829         ok(res->iNumRows == value, "RB_GETROWCOUNT expected %d got %d\n", res->iNumRows, value); \
830         if (res->heightNotify) { \
831             RECT rcClient; \
832             GetClientRect(hRebar, &rcClient); \
833             check_rect("notify", height_change_notify_rect, rcClient); \
834         } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
835         SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
836     }
837
838 #endif
839
840 static void test_resize(void)
841 {
842     DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
843         CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
844         CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
845         CCS_NOMOVEY | WS_BORDER};
846
847     const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
848     int i;
849
850     for (i = 0; i < styles_count; i++)
851     {
852         HWND hRebar;
853
854         comment("style %08x", dwStyles[i]);
855         SetRect(&height_change_notify_rect, -1, -1, -1, -1);
856         hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
857         check_client();
858         add_band_w(hRebar, NULL, 70, 100, 0);
859         if (dwStyles[i] & CCS_NOPARENTALIGN)  /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
860             check_client();
861         add_band_w(hRebar, NULL, 70, 100, 0);
862         check_client();
863         MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
864         check_client();
865         MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
866         check_client();
867         /* try to fool the rebar by sending invalid width/height - won't work */
868         if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
869         {
870             WINDOWPOS pos;
871             pos.hwnd = hRebar;
872             pos.hwndInsertAfter = NULL;
873             pos.cx = 500;
874             pos.cy = 500;
875             pos.x = 10;
876             pos.y = 10;
877             pos.flags = 0;
878             SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
879             SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
880             check_client();
881             SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
882             check_client();
883         }
884         SendMessage(hRebar, RB_DELETEBAND, 0, 0);
885         check_client();
886         SendMessage(hRebar, RB_DELETEBAND, 0, 0);
887         MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
888         check_client();
889         DestroyWindow(hRebar);
890     }
891 }
892
893 static void expect_band_content_(int line, HWND hRebar, UINT uBand, INT fStyle, COLORREF clrFore,
894     COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
895     INT cxMinChild, INT cyMinChild, INT cx, HBITMAP hbmBack, INT wID,
896     INT cyChild, INT cyMaxChild, INT cyIntegral, INT cxIdeal, LPARAM lParam,
897     UINT cxHeader, UINT cxHeader_broken)
898 {
899     CHAR buf[MAX_PATH] = "abc";
900     REBARBANDINFOA rb;
901
902     memset(&rb, 0xdd, sizeof(rb));
903     rb.cbSize = REBARBANDINFOA_V6_SIZE;
904     rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
905         | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
906         | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
907     rb.lpText = buf;
908     rb.cch = MAX_PATH;
909     ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed from line %d\n", line);
910     expect_eq(line, rb.fStyle, fStyle, int, "%x");
911     expect_eq(line, rb.clrFore, clrFore, COLORREF, "%x");
912     expect_eq(line, rb.clrBack, clrBack, COLORREF, "%x");
913     expect_eq(line, strcmp(rb.lpText, lpText), 0, int, "%d");
914     expect_eq(line, rb.iImage, iImage, int, "%x");
915     expect_eq(line, rb.hwndChild, hwndChild, HWND, "%p");
916     expect_eq(line, rb.cxMinChild, cxMinChild, int, "%d");
917     expect_eq(line, rb.cyMinChild, cyMinChild, int, "%d");
918     expect_eq(line, rb.cx, cx, int, "%d");
919     expect_eq(line, rb.hbmBack, hbmBack, HBITMAP, "%p");
920     expect_eq(line, rb.wID, wID, int, "%d");
921     /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
922     expect_eq(line, rb.cyChild, cyChild, int, "%x");
923     expect_eq(line, rb.cyMaxChild, cyMaxChild, int, "%x");
924     expect_eq(line, rb.cyIntegral, cyIntegral, int, "%x");
925     expect_eq(line, rb.cxIdeal, cxIdeal, int, "%d");
926     expect_eq(line, rb.lParam, lParam, LPARAM, "%ld");
927     ok(rb.cxHeader == cxHeader || rb.cxHeader == cxHeader + 1 || broken(rb.cxHeader == cxHeader_broken),
928         "expected %d for %d from line %d\n", cxHeader, rb.cxHeader, line);
929 }
930
931 #define expect_band_content(hRebar, uBand, fStyle, clrFore, clrBack,\
932  lpText, iImage, hwndChild, cxMinChild, cyMinChild, cx, hbmBack, wID,\
933  cyChild, cyMaxChild, cyIntegral, cxIdeal, lParam, cxHeader, cxHeader_broken) \
934  expect_band_content_(__LINE__, hRebar, uBand, fStyle, clrFore, clrBack,\
935  lpText, iImage, hwndChild, cxMinChild, cyMinChild, cx, hbmBack, wID,\
936  cyChild, cyMaxChild, cyIntegral, cxIdeal, lParam, cxHeader, cxHeader_broken)
937
938 static void test_bandinfo(void)
939 {
940     REBARBANDINFOA rb;
941     CHAR szABC[] = "ABC";
942     CHAR szABCD[] = "ABCD";
943     HWND hRebar;
944
945     hRebar = create_rebar_control();
946     rb.cbSize = REBARBANDINFOA_V6_SIZE;
947     rb.fMask = 0;
948     if (!SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb))
949     {
950         win_skip( "V6 info not supported\n" );
951         DestroyWindow(hRebar);
952         return;
953     }
954     expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
955
956     rb.fMask = RBBIM_CHILDSIZE;
957     rb.cxMinChild = 15;
958     rb.cyMinChild = 20;
959     rb.cyChild = 30;
960     rb.cyMaxChild = 20;
961     rb.cyIntegral = 10;
962     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
963     expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
964
965     rb.fMask = RBBIM_TEXT;
966     rb.lpText = szABC;
967     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
968     expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 3 + 2*system_font_height, -1);
969
970     rb.cbSize = REBARBANDINFOA_V6_SIZE;
971     rb.fMask = 0;
972     ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
973     expect_band_content(hRebar, 1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9, -1);
974     expect_band_content(hRebar, 0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 8 + 2*system_font_height, -1);
975
976     rb.fMask = RBBIM_HEADERSIZE;
977     rb.cxHeader = 50;
978     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
979     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);
980
981     rb.cxHeader = 5;
982     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
983     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);
984
985     rb.fMask = RBBIM_TEXT;
986     rb.lpText = szABCD;
987     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
988     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);
989     rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
990     rb.fStyle = RBBS_VARIABLEHEIGHT;
991     rb.lpText = szABC;
992     ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_SETBANDINFO failed\n");
993     expect_band_content(hRebar, 0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 8 + 2*system_font_height, 5);
994
995     DestroyWindow(hRebar);
996 }
997
998 static void test_colors(void)
999 {
1000     COLORSCHEME scheme;
1001     COLORREF clr;
1002     BOOL ret;
1003     HWND hRebar;
1004     REBARBANDINFOA bi;
1005
1006     hRebar = create_rebar_control();
1007
1008     /* test default colors */
1009     clr = SendMessage(hRebar, RB_GETTEXTCOLOR, 0, 0);
1010     compare(clr, CLR_NONE, "%x");
1011     clr = SendMessage(hRebar, RB_GETBKCOLOR, 0, 0);
1012     compare(clr, CLR_NONE, "%x");
1013
1014     scheme.dwSize = sizeof(scheme);
1015     scheme.clrBtnHighlight = 0;
1016     scheme.clrBtnShadow = 0;
1017     ret = SendMessage(hRebar, RB_GETCOLORSCHEME, 0, (LPARAM)&scheme);
1018     if (ret)
1019     {
1020         compare(scheme.clrBtnHighlight, CLR_DEFAULT, "%x");
1021         compare(scheme.clrBtnShadow, CLR_DEFAULT, "%x");
1022     }
1023     else
1024         skip("RB_GETCOLORSCHEME not supported\n");
1025
1026     /* check default band colors */
1027     add_band_w(hRebar, "", 0, 10, 10);
1028     bi.cbSize = REBARBANDINFOA_V6_SIZE;
1029     bi.fMask = RBBIM_COLORS;
1030     bi.clrFore = bi.clrBack = 0xc0ffe;
1031     ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
1032     ok(ret, "RB_GETBANDINFO failed\n");
1033     compare(bi.clrFore, RGB(0, 0, 0), "%x");
1034     compare(bi.clrBack, GetSysColor(COLOR_3DFACE), "%x");
1035
1036     SendMessage(hRebar, RB_SETTEXTCOLOR, 0, RGB(255, 0, 0));
1037     bi.clrFore = bi.clrBack = 0xc0ffe;
1038     ret = SendMessage(hRebar, RB_GETBANDINFO, 0, (LPARAM)&bi);
1039     ok(ret, "RB_GETBANDINFO failed\n");
1040     compare(bi.clrFore, RGB(0, 0, 0), "%x");
1041
1042     DestroyWindow(hRebar);
1043 }
1044
1045
1046 static BOOL register_parent_wnd_class(void)
1047 {
1048     WNDCLASSA wc;
1049
1050     wc.style = CS_HREDRAW | CS_VREDRAW;
1051     wc.cbClsExtra = 0;
1052     wc.cbWndExtra = 0;
1053     wc.hInstance = GetModuleHandleA(NULL);
1054     wc.hIcon = NULL;
1055     wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
1056     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
1057     wc.lpszMenuName = NULL;
1058     wc.lpszClassName = "MyTestWnd";
1059     wc.lpfnWndProc = MyWndProc;
1060
1061     return RegisterClassA(&wc);
1062 }
1063
1064 static HWND create_parent_window(void)
1065 {
1066     HWND hwnd;
1067
1068     if (!register_parent_wnd_class()) return NULL;
1069
1070     hwnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
1071       CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
1072       226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
1073       NULL, NULL, GetModuleHandleA(NULL), 0);
1074
1075     ShowWindow(hwnd, SW_SHOW);
1076     return hwnd;
1077 }
1078
1079 static void test_showband(void)
1080 {
1081     HWND hRebar;
1082     REBARBANDINFOA rbi;
1083     BOOL ret;
1084
1085     hRebar = create_rebar_control();
1086
1087     /* no bands */
1088     ret = SendMessageA(hRebar, RB_SHOWBAND, 0, TRUE);
1089     ok(ret == FALSE, "got %d\n", ret);
1090
1091     rbi.cbSize = REBARBANDINFOA_V6_SIZE;
1092     rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
1093     rbi.cx = 200;
1094     rbi.cxMinChild = 100;
1095     rbi.cyMinChild = 30;
1096     rbi.hwndChild = NULL;
1097     SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
1098
1099     /* index out of range */
1100     ret = SendMessageA(hRebar, RB_SHOWBAND, 1, TRUE);
1101     ok(ret == FALSE, "got %d\n", ret);
1102
1103     ret = SendMessageA(hRebar, RB_SHOWBAND, 0, TRUE);
1104     ok(ret == TRUE, "got %d\n", ret);
1105
1106     DestroyWindow(hRebar);
1107 }
1108
1109 START_TEST(rebar)
1110 {
1111     HMODULE hComctl32;
1112     BOOL (WINAPI *pInitCommonControlsEx)(const INITCOMMONCONTROLSEX*);
1113     INITCOMMONCONTROLSEX iccex;
1114     MSG msg;
1115
1116     init_system_font_height();
1117
1118     /* LoadLibrary is needed. This file has no reference to functions in comctl32 */
1119     hComctl32 = LoadLibraryA("comctl32.dll");
1120     pInitCommonControlsEx = (void*)GetProcAddress(hComctl32, "InitCommonControlsEx");
1121     if (!pInitCommonControlsEx)
1122     {
1123         win_skip("InitCommonControlsEx() is missing. Skipping the tests\n");
1124         return;
1125     }
1126     iccex.dwSize = sizeof(iccex);
1127     iccex.dwICC = ICC_COOL_CLASSES;
1128     pInitCommonControlsEx(&iccex);
1129
1130     hMainWnd = create_parent_window();
1131
1132     test_bandinfo();
1133     test_colors();
1134     test_showband();
1135
1136     if(!is_font_installed("System") || !is_font_installed("Tahoma"))
1137     {
1138         skip("Missing System or Tahoma font\n");
1139         goto out;
1140     }
1141
1142     test_layout();
1143     test_resize();
1144
1145 out:
1146     PostQuitMessage(0);
1147     while(GetMessageA(&msg,0,0,0)) {
1148         TranslateMessage(&msg);
1149         DispatchMessageA(&msg);
1150     }
1151     DestroyWindow(hMainWnd);
1152
1153     FreeLibrary(hComctl32);
1154 }