push 5db4b94c26956368fbcfd31d792d3acf0eb5f8e6
[wine/hacks.git] / dlls / comctl32 / tests / rebar.c
blob2b318d2b87bf461e7f121a546c9b697f58ea867e
1 /* Unit tests for rebar.
3 * Copyright 2007 Mikolaj Zalewski
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <assert.h>
21 #include <stdarg.h>
23 #include <windows.h>
24 #include <commctrl.h>
25 #include <uxtheme.h>
27 #include "wine/test.h"
29 RECT height_change_notify_rect;
30 static HWND hMainWnd;
31 static HWND hRebar;
34 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
35 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
36 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
38 #define check_rect_no_top(name, val, exp) { \
39 ok((val.bottom - val.top == exp.bottom - exp.top) && \
40 val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d), ignoring top\n", \
41 val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom); \
44 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
46 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
48 static INT CALLBACK is_font_installed_proc(const LOGFONT *elf, const TEXTMETRIC *ntm, DWORD type, LPARAM lParam)
50 return 0;
53 static BOOL is_font_installed(const char *name)
55 HDC hdc = GetDC(0);
56 BOOL ret = FALSE;
58 if(!EnumFontFamiliesA(hdc, name, is_font_installed_proc, 0))
59 ret = TRUE;
61 ReleaseDC(0, hdc);
62 return ret;
65 static void rebuild_rebar(HWND *hRebar)
67 if (*hRebar)
68 DestroyWindow(*hRebar);
70 *hRebar = CreateWindow(REBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
71 hMainWnd, (HMENU)17, GetModuleHandle(NULL), NULL);
72 SendMessageA(*hRebar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0);
75 static HWND build_toolbar(int nr, HWND hParent)
77 TBBUTTON btns[8];
78 HWND hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | CCS_NORESIZE, 0, 0, 0, 0,
79 hParent, (HMENU)5, GetModuleHandle(NULL), NULL);
80 int iBitmapId = 0;
81 int i;
83 ok(hToolbar != NULL, "Toolbar creation problem\n");
84 ok(SendMessage(hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
85 ok(SendMessage(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
86 ok(SendMessage(hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
88 for (i=0; i<5+nr; i++)
90 btns[i].iBitmap = i;
91 btns[i].idCommand = i;
92 btns[i].fsStyle = BTNS_BUTTON;
93 btns[i].fsState = TBSTATE_ENABLED;
94 btns[i].iString = 0;
97 switch (nr)
99 case 0: iBitmapId = IDB_HIST_SMALL_COLOR; break;
100 case 1: iBitmapId = IDB_VIEW_SMALL_COLOR; break;
101 case 2: iBitmapId = IDB_STD_SMALL_COLOR; break;
103 ok(SendMessage(hToolbar, TB_LOADIMAGES, iBitmapId, (LPARAM)HINST_COMMCTRL) == 0, "TB_LOADIMAGE failed\n");
104 ok(SendMessage(hToolbar, TB_ADDBUTTONS, 5+nr, (LPARAM)btns), "TB_ADDBUTTONS failed\n");
105 return hToolbar;
108 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
110 switch (msg)
112 case WM_NOTIFY:
114 NMHDR *lpnm = (NMHDR *)lParam;
115 if (lpnm->code == RBN_HEIGHTCHANGE)
116 GetClientRect(hRebar, &height_change_notify_rect);
118 break;
120 return DefWindowProcA(hWnd, msg, wParam, lParam);
123 #if 0 /* use this to generate more tests*/
125 static void dump_sizes(HWND hRebar)
127 SIZE sz;
128 RECT r;
129 int count;
130 int i, h;
132 GetClientRect(hRebar, &r);
133 count = SendMessageA(hRebar, RB_GETROWCOUNT, 0, 0);
134 printf(" { {%d, %d, %d, %d}, %d, %d, {", r.left, r.top, r.right, r.bottom,
135 SendMessageA(hRebar, RB_GETBARHEIGHT, 0, 0), count);
136 if (count == 0)
137 printf("0, ");
138 for (i = 0; i < count; i++) /* rows */
139 printf("%d, ", SendMessageA(hRebar, RB_GETROWHEIGHT, i, 0));
140 printf("}, ");
142 count = SendMessageA(hRebar, RB_GETBANDCOUNT, 0, 0);
143 printf("%d, {", count);
144 if (count == 0)
145 printf("{{0, 0, 0, 0}, 0, 0},");
146 for (i=0; i<count; i++)
148 REBARBANDINFO rbi;
149 rbi.cbSize = sizeof(REBARBANDINFO);
150 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_STYLE;
151 ok(SendMessageA(hRebar, RB_GETBANDINFOA, i, (LPARAM)&rbi), "RB_GETBANDINFO failed\n");
152 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&r), "RB_GETRECT failed\n");
153 printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i%2==0 ? "\n " : ""), r.left, r.top, r.right, r.bottom,
154 rbi.fStyle, rbi.cx);
156 printf("\n }, }, \n");
159 #define check_sizes() dump_sizes(hRebar);
160 #define check_sizes_todo(todomask) dump_sizes(hRebar);
162 #else
164 typedef struct {
165 RECT rc;
166 DWORD fStyle;
167 INT cx;
168 } rbband_result_t;
170 typedef struct {
171 RECT rcClient;
172 int cyBarHeight;
173 int nRows;
174 int cyRowHeights[50];
175 int nBands;
176 rbband_result_t bands[50];
177 } rbsize_result_t;
179 rbsize_result_t rbsize_results[] = {
180 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
181 }, },
182 { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
183 { { 0, 0, 672, 4}, 0x00, 200},
184 }, },
185 { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
186 { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
187 }, },
188 { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
189 { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
190 { {400, 0, 672, 30}, 0x00, 200},
191 }, },
192 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
193 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
194 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
195 }, },
196 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
197 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
198 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
199 }, },
200 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
201 { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
202 { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
203 }, },
204 { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
205 { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
206 { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
207 { {202, 36, 672, 70}, 0x04, 66},
208 }, },
209 { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
210 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
211 { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
212 { {629, 0, 672, 34}, 0x04, 66},
213 }, },
214 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
215 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
216 { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
217 }, },
218 { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
219 { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
220 { {617, 0, 672, 34}, 0x04, 66},
221 }, },
222 { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
223 { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
224 }, },
225 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
226 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
227 { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
228 { { 0, 20, 672, 40}, 0x00, 200},
229 }, },
230 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
231 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
232 { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
233 { { 0, 20, 672, 40}, 0x00, 200},
234 }, },
235 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
236 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
237 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
238 { { 0, 20, 672, 40}, 0x00, 200},
239 }, },
240 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
241 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
242 { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
243 { { 0, 20, 672, 40}, 0x00, 200},
244 }, },
245 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
246 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
247 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
248 { { 0, 20, 672, 40}, 0x00, 200},
249 }, },
250 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
251 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
252 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
253 { { 0, 20, 672, 40}, 0x00, 200},
254 }, },
255 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
256 }, },
257 { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
258 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
259 { {180, 0, 672, 65}, 0x40, 90},
260 }, },
261 { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
262 }, },
263 { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
264 { { 0, 0, 226, 65}, 0x40, 90},
265 }, },
266 { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
267 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
268 }, },
269 { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
270 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
271 { {163, 0, 226, 65}, 0x40, 90},
272 }, },
275 static int rbsize_numtests = 0;
277 #define check_sizes_todo(todomask) { \
278 RECT rc; \
279 REBARBANDINFO rbi; \
280 int count, i/*, mask=(todomask)*/; \
281 rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
282 assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
283 GetClientRect(hRebar, &rc); \
284 check_rect("client", rc, res->rcClient); \
285 count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
286 compare(count, res->nRows, "%d"); \
287 for (i=0; i<min(count, res->nRows); i++) { \
288 int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
289 ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
291 count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
292 compare(count, res->nBands, "%d"); \
293 for (i=0; i<min(count, res->nBands); i++) { \
294 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_ITEMRECT\n"); \
295 if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
296 check_rect("band", rc, res->bands[i].rc); \
297 rbi.cbSize = sizeof(REBARBANDINFO); \
298 rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
299 ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
300 compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
301 compare(rbi.cx, res->bands[i].cx, "%d"); \
303 rbsize_numtests++; \
306 #define check_sizes() check_sizes_todo(0)
308 #endif
310 static void add_band_w(HWND hRebar, LPCSTR lpszText, int cxMinChild, int cx, int cxIdeal)
312 CHAR buffer[MAX_PATH];
313 REBARBANDINFO rbi;
315 if (lpszText != NULL)
316 strcpy(buffer, lpszText);
317 rbi.cbSize = sizeof(rbi);
318 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD | RBBIM_IDEALSIZE | RBBIM_TEXT;
319 rbi.cx = cx;
320 rbi.cxMinChild = cxMinChild;
321 rbi.cxIdeal = cxIdeal;
322 rbi.cyMinChild = 20;
323 rbi.hwndChild = build_toolbar(1, hRebar);
324 rbi.lpText = (lpszText ? buffer : NULL);
325 SendMessage(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
328 static void layout_test(void)
330 HWND hRebar = NULL;
331 REBARBANDINFO rbi;
333 rebuild_rebar(&hRebar);
334 check_sizes();
335 rbi.cbSize = sizeof(rbi);
336 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
337 rbi.cx = 200;
338 rbi.cxMinChild = 100;
339 rbi.cyMinChild = 30;
340 rbi.hwndChild = NULL;
341 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
342 check_sizes();
344 rbi.fMask |= RBBIM_STYLE;
345 rbi.fStyle = RBBS_CHILDEDGE;
346 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
347 check_sizes();
349 rbi.fStyle = 0;
350 rbi.cx = 200;
351 rbi.cxMinChild = 30;
352 rbi.cyMinChild = 30;
353 rbi.hwndChild = build_toolbar(0, hRebar);
354 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
355 check_sizes();
357 rbi.fStyle = RBBS_CHILDEDGE;
358 rbi.cx = 68;
359 rbi.hwndChild = build_toolbar(0, hRebar);
360 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
361 check_sizes();
363 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_BANDBORDERS);
364 check_sizes(); /* a style change won't start a relayout */
365 rbi.fMask = RBBIM_SIZE;
366 rbi.cx = 66;
367 SendMessageA(hRebar, RB_SETBANDINFO, 3, (LPARAM)&rbi);
368 check_sizes(); /* here it will be relayouted */
370 /* this will force a new row */
371 rbi.fMask = RBBIM_SIZE | RBBIM_CHILDSIZE | RBBIM_CHILD;
372 rbi.cx = 200;
373 rbi.cxMinChild = 400;
374 rbi.cyMinChild = 30;
375 rbi.hwndChild = build_toolbar(0, hRebar);
376 SendMessageA(hRebar, RB_INSERTBAND, 1, (LPARAM)&rbi);
377 check_sizes();
379 rbi.fMask = RBBIM_STYLE;
380 rbi.fStyle = RBBS_HIDDEN;
381 SendMessageA(hRebar, RB_SETBANDINFO, 2, (LPARAM)&rbi);
382 check_sizes();
384 SendMessageA(hRebar, RB_DELETEBAND, 2, 0);
385 check_sizes();
386 SendMessageA(hRebar, RB_DELETEBAND, 0, 0);
387 check_sizes();
388 SendMessageA(hRebar, RB_DELETEBAND, 1, 0);
389 check_sizes();
391 rebuild_rebar(&hRebar);
392 add_band_w(hRebar, "ABC", 70, 40, 100);
393 add_band_w(hRebar, NULL, 40, 70, 100);
394 add_band_w(hRebar, NULL, 170, 240, 100);
395 add_band_w(hRebar, "MMMMMMM", 60, 60, 100);
396 add_band_w(hRebar, NULL, 200, 200, 100);
397 check_sizes();
398 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
399 check_sizes();
400 SendMessageA(hRebar, RB_MAXIMIZEBAND, 1, TRUE);
401 check_sizes();
402 SendMessageA(hRebar, RB_MAXIMIZEBAND, 2, FALSE);
403 check_sizes();
404 SendMessageA(hRebar, RB_MINIMIZEBAND, 2, 0);
405 check_sizes();
406 SendMessageA(hRebar, RB_MINIMIZEBAND, 0, 0);
407 check_sizes();
409 /* VARHEIGHT resizing test on a horizontal rebar */
410 rebuild_rebar(&hRebar);
411 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | RBS_AUTOSIZE);
412 check_sizes();
413 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
414 rbi.fStyle = RBBS_VARIABLEHEIGHT;
415 rbi.cxMinChild = 50;
416 rbi.cyMinChild = 10;
417 rbi.cyIntegral = 11;
418 rbi.cyChild = 70;
419 rbi.cyMaxChild = 200;
420 rbi.cx = 90;
421 rbi.hwndChild = build_toolbar(0, hRebar);
422 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
424 rbi.cyChild = 50;
425 rbi.hwndChild = build_toolbar(0, hRebar);
426 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
428 rbi.cyMinChild = 40;
429 rbi.cyChild = 50;
430 rbi.cyIntegral = 5;
431 rbi.hwndChild = build_toolbar(0, hRebar);
432 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
433 check_sizes();
435 /* VARHEIGHT resizing on a vertical rebar */
436 rebuild_rebar(&hRebar);
437 SetWindowLong(hRebar, GWL_STYLE, GetWindowLong(hRebar, GWL_STYLE) | CCS_VERT | RBS_AUTOSIZE);
438 check_sizes();
439 rbi.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_SIZE | RBBIM_STYLE;
440 rbi.fStyle = RBBS_VARIABLEHEIGHT;
441 rbi.cxMinChild = 50;
442 rbi.cyMinChild = 10;
443 rbi.cyIntegral = 11;
444 rbi.cyChild = 70;
445 rbi.cyMaxChild = 90;
446 rbi.cx = 90;
447 rbi.hwndChild = build_toolbar(0, hRebar);
448 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
449 check_sizes();
451 rbi.cyChild = 50;
452 rbi.hwndChild = build_toolbar(0, hRebar);
453 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
454 check_sizes();
456 rbi.cyMinChild = 40;
457 rbi.cyChild = 50;
458 rbi.cyIntegral = 5;
459 rbi.hwndChild = build_toolbar(0, hRebar);
460 SendMessageA(hRebar, RB_INSERTBAND, -1, (LPARAM)&rbi);
461 check_sizes();
463 DestroyWindow(hRebar);
466 #if 0 /* use this to generate more tests */
468 static void dump_client(HWND hRebar)
470 RECT r;
471 BOOL notify;
472 GetWindowRect(hRebar, &r);
473 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2);
474 if (height_change_notify_rect.top != -1)
476 RECT rcClient;
477 GetClientRect(hRebar, &rcClient);
478 assert(EqualRect(&rcClient, &height_change_notify_rect));
479 notify = TRUE;
481 else
482 notify = FALSE;
483 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r.left, r.top, r.right, r.bottom, SendMessage(hRebar, RB_GETROWCOUNT, 0, 0),
484 notify ? "TRUE" : "FALSE");
485 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
488 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
489 #define check_client() dump_client(hRebar)
491 #else
493 typedef struct {
494 RECT rc;
495 INT iNumRows;
496 BOOL heightNotify;
497 } rbresize_test_result_t;
499 rbresize_test_result_t resize_results[] = {
500 /* style 00000001 */
501 {{0, 2, 672, 2}, 0, FALSE},
502 {{0, 2, 672, 22}, 1, TRUE},
503 {{0, 2, 672, 22}, 1, FALSE},
504 {{0, 2, 672, 22}, 1, FALSE},
505 {{0, 2, 672, 22}, 1, FALSE},
506 {{0, 2, 672, 22}, 0, FALSE},
507 /* style 00000041 */
508 {{0, 0, 672, 0}, 0, FALSE},
509 {{0, 0, 672, 20}, 1, TRUE},
510 {{0, 0, 672, 20}, 1, FALSE},
511 {{0, 0, 672, 20}, 1, FALSE},
512 {{0, 0, 672, 20}, 1, FALSE},
513 {{0, 0, 672, 20}, 0, FALSE},
514 /* style 00000003 */
515 {{0, 226, 672, 226}, 0, FALSE},
516 {{0, 206, 672, 226}, 1, TRUE},
517 {{0, 206, 672, 226}, 1, FALSE},
518 {{0, 206, 672, 226}, 1, FALSE},
519 {{0, 206, 672, 226}, 1, FALSE},
520 {{0, 206, 672, 226}, 0, FALSE},
521 /* style 00000043 */
522 {{0, 226, 672, 226}, 0, FALSE},
523 {{0, 206, 672, 226}, 1, TRUE},
524 {{0, 206, 672, 226}, 1, FALSE},
525 {{0, 206, 672, 226}, 1, FALSE},
526 {{0, 206, 672, 226}, 1, FALSE},
527 {{0, 206, 672, 226}, 0, FALSE},
528 /* style 00000080 */
529 {{2, 0, 2, 226}, 0, FALSE},
530 {{2, 0, 22, 226}, 1, TRUE},
531 {{2, 0, 22, 226}, 1, FALSE},
532 {{2, 0, 22, 226}, 1, FALSE},
533 {{2, 0, 22, 226}, 1, FALSE},
534 {{2, 0, 22, 226}, 0, FALSE},
535 /* style 00000083 */
536 {{672, 0, 672, 226}, 0, FALSE},
537 {{652, 0, 672, 226}, 1, TRUE},
538 {{652, 0, 672, 226}, 1, FALSE},
539 {{652, 0, 672, 226}, 1, FALSE},
540 {{652, 0, 672, 226}, 1, FALSE},
541 {{652, 0, 672, 226}, 0, FALSE},
542 /* style 00000008 */
543 {{10, 11, 510, 11}, 0, FALSE},
544 {{10, 15, 510, 35}, 1, TRUE},
545 {{10, 17, 510, 37}, 1, FALSE},
546 {{10, 14, 110, 54}, 2, TRUE},
547 {{0, 4, 0, 44}, 2, FALSE},
548 {{0, 6, 0, 46}, 2, FALSE},
549 {{0, 8, 0, 48}, 2, FALSE},
550 {{0, 12, 0, 32}, 1, TRUE},
551 {{0, 4, 100, 24}, 0, FALSE},
552 /* style 00000048 */
553 {{10, 5, 510, 5}, 0, FALSE},
554 {{10, 5, 510, 25}, 1, TRUE},
555 {{10, 5, 510, 25}, 1, FALSE},
556 {{10, 10, 110, 50}, 2, TRUE},
557 {{0, 0, 0, 40}, 2, FALSE},
558 {{0, 0, 0, 40}, 2, FALSE},
559 {{0, 0, 0, 40}, 2, FALSE},
560 {{0, 0, 0, 20}, 1, TRUE},
561 {{0, 0, 100, 20}, 0, FALSE},
562 /* style 00000004 */
563 {{10, 5, 510, 20}, 0, FALSE},
564 {{10, 5, 510, 20}, 1, TRUE},
565 {{10, 10, 110, 110}, 2, TRUE},
566 {{0, 0, 0, 0}, 2, FALSE},
567 {{0, 0, 0, 0}, 2, FALSE},
568 {{0, 0, 0, 0}, 2, FALSE},
569 {{0, 0, 0, 0}, 1, TRUE},
570 {{0, 0, 100, 100}, 0, FALSE},
571 /* style 00000002 */
572 {{0, 5, 672, 5}, 0, FALSE},
573 {{0, 5, 672, 25}, 1, TRUE},
574 {{0, 10, 672, 30}, 1, FALSE},
575 {{0, 0, 672, 20}, 1, FALSE},
576 {{0, 0, 672, 20}, 1, FALSE},
577 {{0, 0, 672, 20}, 0, FALSE},
578 /* style 00000082 */
579 {{10, 0, 10, 226}, 0, FALSE},
580 {{10, 0, 30, 226}, 1, TRUE},
581 {{10, 0, 30, 226}, 1, FALSE},
582 {{0, 0, 20, 226}, 1, FALSE},
583 {{0, 0, 20, 226}, 1, FALSE},
584 {{0, 0, 20, 226}, 0, FALSE},
585 /* style 00800001 */
586 {{-2, 0, 674, 4}, 0, FALSE},
587 {{-2, 0, 674, 24}, 1, TRUE},
588 {{-2, 0, 674, 24}, 1, FALSE},
589 {{-2, 0, 674, 24}, 1, FALSE},
590 {{-2, 0, 674, 24}, 1, FALSE},
591 {{-2, 0, 674, 24}, 0, FALSE},
592 /* style 00800048 */
593 {{10, 5, 510, 9}, 0, FALSE},
594 {{10, 5, 510, 29}, 1, TRUE},
595 {{10, 5, 510, 29}, 1, FALSE},
596 {{10, 10, 110, 54}, 2, TRUE},
597 {{0, 0, 0, 44}, 2, FALSE},
598 {{0, 0, 0, 44}, 2, FALSE},
599 {{0, 0, 0, 44}, 2, FALSE},
600 {{0, 0, 0, 24}, 1, TRUE},
601 {{0, 0, 100, 24}, 0, FALSE},
602 /* style 00800004 */
603 {{10, 5, 510, 20}, 0, FALSE},
604 {{10, 5, 510, 20}, 1, TRUE},
605 {{10, 10, 110, 110}, 2, TRUE},
606 {{0, 0, 0, 0}, 2, FALSE},
607 {{0, 0, 0, 0}, 2, FALSE},
608 {{0, 0, 0, 0}, 2, FALSE},
609 {{0, 0, 0, 0}, 1, TRUE},
610 {{0, 0, 100, 100}, 0, FALSE},
611 /* style 00800002 */
612 {{-2, 5, 674, 9}, 0, FALSE},
613 {{-2, 5, 674, 29}, 1, TRUE},
614 {{-2, 10, 674, 34}, 1, FALSE},
615 {{-2, 0, 674, 24}, 1, FALSE},
616 {{-2, 0, 674, 24}, 1, FALSE},
617 {{-2, 0, 674, 24}, 0, FALSE},
620 static int resize_numtests = 0;
622 #define comment(fmt, arg1)
623 #define check_client() { \
624 RECT r; \
625 rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
626 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
627 GetWindowRect(hRebar, &r); \
628 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
629 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
630 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
631 } else { \
632 check_rect("client", r, res->rc); \
634 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
635 if (res->heightNotify) { \
636 RECT rcClient; \
637 GetClientRect(hRebar, &rcClient); \
638 check_rect("notify", height_change_notify_rect, rcClient); \
639 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
640 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
643 #endif
645 static void resize_test(void)
647 DWORD dwStyles[] = {CCS_TOP, CCS_TOP | CCS_NODIVIDER, CCS_BOTTOM, CCS_BOTTOM | CCS_NODIVIDER, CCS_VERT, CCS_RIGHT,
648 CCS_NOPARENTALIGN, CCS_NOPARENTALIGN | CCS_NODIVIDER, CCS_NORESIZE, CCS_NOMOVEY, CCS_NOMOVEY | CCS_VERT,
649 CCS_TOP | WS_BORDER, CCS_NOPARENTALIGN | CCS_NODIVIDER | WS_BORDER, CCS_NORESIZE | WS_BORDER,
650 CCS_NOMOVEY | WS_BORDER};
652 const int styles_count = sizeof(dwStyles) / sizeof(dwStyles[0]);
653 int i;
655 for (i = 0; i < styles_count; i++)
657 comment("style %08x", dwStyles[i]);
658 SetRect(&height_change_notify_rect, -1, -1, -1, -1);
659 hRebar = CreateWindow(REBARCLASSNAME, "A", dwStyles[i] | WS_CHILD | WS_VISIBLE, 10, 5, 500, 15, hMainWnd, NULL, GetModuleHandle(NULL), 0);
660 check_client();
661 add_band_w(hRebar, NULL, 70, 100, 0);
662 if (dwStyles[i] & CCS_NOPARENTALIGN) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
663 check_client();
664 add_band_w(hRebar, NULL, 70, 100, 0);
665 check_client();
666 MoveWindow(hRebar, 10, 10, 100, 100, TRUE);
667 check_client();
668 MoveWindow(hRebar, 0, 0, 0, 0, TRUE);
669 check_client();
670 /* try to fool the rebar by sending invalid width/height - won't work */
671 if (dwStyles[i] & (CCS_NORESIZE | CCS_NOPARENTALIGN))
673 WINDOWPOS pos;
674 pos.hwnd = hRebar;
675 pos.hwndInsertAfter = NULL;
676 pos.cx = 500;
677 pos.cy = 500;
678 pos.x = 10;
679 pos.y = 10;
680 pos.flags = 0;
681 SendMessage(hRebar, WM_WINDOWPOSCHANGING, 0, (LPARAM)&pos);
682 SendMessage(hRebar, WM_WINDOWPOSCHANGED, 0, (LPARAM)&pos);
683 check_client();
684 SendMessage(hRebar, WM_SIZE, SIZE_RESTORED, MAKELONG(500, 500));
685 check_client();
687 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
688 check_client();
689 SendMessage(hRebar, RB_DELETEBAND, 0, 0);
690 MoveWindow(hRebar, 0, 0, 100, 100, TRUE);
691 check_client();
692 DestroyWindow(hRebar);
696 static void expect_band_content(UINT uBand, UINT fStyle, COLORREF clrFore,
697 COLORREF clrBack, LPCSTR lpText, int iImage, HWND hwndChild,
698 UINT cxMinChild, UINT cyMinChild, UINT cx, HBITMAP hbmBack, UINT wID,
699 UINT cyChild, UINT cyMaxChild, UINT cyIntegral, UINT cxIdeal, LPARAM lParam,
700 UINT cxHeader)
702 CHAR buf[MAX_PATH] = "abc";
703 REBARBANDINFO rb;
705 memset(&rb, 0xdd, sizeof(rb));
706 rb.cbSize = sizeof(rb);
707 rb.fMask = RBBIM_BACKGROUND | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_COLORS
708 | RBBIM_HEADERSIZE | RBBIM_ID | RBBIM_IDEALSIZE | RBBIM_IMAGE | RBBIM_LPARAM
709 | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT;
710 rb.lpText = buf;
711 rb.cch = MAX_PATH;
712 ok(SendMessageA(hRebar, RB_GETBANDINFOA, uBand, (LPARAM)&rb), "RB_GETBANDINFO failed\n");
713 expect_eq(rb.fStyle, fStyle, int, "%x");
714 todo_wine expect_eq(rb.clrFore, clrFore, COLORREF, "%x");
715 todo_wine expect_eq(rb.clrBack, clrBack, int, "%x");
716 expect_eq(strcmp(rb.lpText, lpText), 0, int, "%d");
717 expect_eq(rb.iImage, iImage, int, "%x");
718 expect_eq(rb.hwndChild, hwndChild, HWND, "%p");
719 expect_eq(rb.cxMinChild, cxMinChild, int, "%d");
720 expect_eq(rb.cyMinChild, cyMinChild, int, "%d");
721 expect_eq(rb.cx, cx, int, "%d");
722 expect_eq(rb.hbmBack, hbmBack, HBITMAP, "%p");
723 expect_eq(rb.wID, wID, int, "%d");
724 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
725 expect_eq(rb.cyChild, cyChild, int, "%x");
726 expect_eq(rb.cyMaxChild, cyMaxChild, int, "%x");
727 expect_eq(rb.cyIntegral, cyIntegral, int, "%x");
728 expect_eq(rb.cxIdeal, cxIdeal, int, "%d");
729 expect_eq(rb.lParam, lParam, LPARAM, "%ld");
730 expect_eq(rb.cxHeader, cxHeader, int, "%d");
733 static void bandinfo_test(void)
735 REBARBANDINFOA rb;
736 CHAR szABC[] = "ABC";
737 CHAR szABCD[] = "ABCD";
739 rebuild_rebar(&hRebar);
740 rb.cbSize = sizeof(REBARBANDINFO);
741 rb.fMask = 0;
742 ok(SendMessageA(hRebar, RB_INSERTBANDA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
743 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
745 rb.fMask = RBBIM_CHILDSIZE;
746 rb.cxMinChild = 15;
747 rb.cyMinChild = 20;
748 rb.cyChild = 30;
749 rb.cyMaxChild = 20;
750 rb.cyIntegral = 10;
751 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
752 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0);
754 rb.fMask = RBBIM_TEXT;
755 rb.lpText = szABC;
756 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
757 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 35);
759 rb.cbSize = sizeof(REBARBANDINFO);
760 rb.fMask = 0;
761 ok(SendMessageA(hRebar, RB_INSERTBANDA, 1, (LPARAM)&rb), "RB_INSERTBAND failed\n");
762 expect_band_content(1, 0, 0, GetSysColor(COLOR_3DFACE), "", -1, NULL, 0, 0, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9);
763 expect_band_content(0, 0, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 40);
765 rb.fMask = RBBIM_HEADERSIZE;
766 rb.cxHeader = 50;
767 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
768 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 50);
770 rb.cxHeader = 5;
771 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
772 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
774 rb.fMask = RBBIM_TEXT;
775 rb.lpText = szABCD;
776 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
777 expect_band_content(0, 0x40000000, 0, GetSysColor(COLOR_3DFACE), "ABCD", -1, NULL, 15, 20, 0, NULL, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 5);
778 rb.fMask = RBBIM_STYLE | RBBIM_TEXT;
779 rb.fStyle = RBBS_VARIABLEHEIGHT;
780 rb.lpText = szABC;
781 ok(SendMessageA(hRebar, RB_SETBANDINFOA, 0, (LPARAM)&rb), "RB_INSERTBAND failed\n");
782 expect_band_content(0, RBBS_VARIABLEHEIGHT, 0, GetSysColor(COLOR_3DFACE), "ABC", -1, NULL, 15, 20, 0, NULL, 0, 20, 0x7fffffff, 0, 0, 0, 40);
784 DestroyWindow(hRebar);
787 START_TEST(rebar)
789 INITCOMMONCONTROLSEX icc;
790 WNDCLASSA wc;
791 MSG msg;
792 RECT rc;
794 icc.dwSize = sizeof(icc);
795 icc.dwICC = ICC_COOL_CLASSES;
796 InitCommonControlsEx(&icc);
798 wc.style = CS_HREDRAW | CS_VREDRAW;
799 wc.cbClsExtra = 0;
800 wc.cbWndExtra = 0;
801 wc.hInstance = GetModuleHandleA(NULL);
802 wc.hIcon = NULL;
803 wc.hCursor = LoadCursorA(NULL, MAKEINTRESOURCEA(IDC_IBEAM));
804 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
805 wc.lpszMenuName = NULL;
806 wc.lpszClassName = "MyTestWnd";
807 wc.lpfnWndProc = MyWndProc;
808 RegisterClassA(&wc);
809 hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW,
810 CW_USEDEFAULT, CW_USEDEFAULT, 672+2*GetSystemMetrics(SM_CXSIZEFRAME),
811 226+GetSystemMetrics(SM_CYCAPTION)+2*GetSystemMetrics(SM_CYSIZEFRAME),
812 NULL, NULL, GetModuleHandleA(NULL), 0);
813 GetClientRect(hMainWnd, &rc);
814 ShowWindow(hMainWnd, SW_SHOW);
816 bandinfo_test();
818 if(is_font_installed("System") && is_font_installed("Tahoma"))
820 layout_test();
821 resize_test();
822 } else
823 skip("Missing System or Tahoma font\n");
825 PostQuitMessage(0);
826 while(GetMessageA(&msg,0,0,0)) {
827 TranslateMessage(&msg);
828 DispatchMessageA(&msg);
830 DestroyWindow(hMainWnd);