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