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