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 /* make sure the structures work with a comctl32 v5.x */
21 #define _WIN32_WINNT 0x500
22 #define _WIN32_IE 0x500
31 #include "wine/test.h"
33 static RECT height_change_notify_rect
;
35 static int system_font_height
;
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);
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); \
48 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
50 #define expect_eq(expr, value, type, format) { type ret = expr; ok((value) == ret, #expr " expected " format " got " format "\n", (value), (ret)); }
52 static INT CALLBACK
is_font_installed_proc(const LOGFONT
*elf
, const TEXTMETRIC
*ntm
, DWORD type
, LPARAM lParam
)
57 static BOOL
is_font_installed(const char *name
)
62 if(!EnumFontFamiliesA(hdc
, name
, is_font_installed_proc
, 0))
69 static void init_system_font_height(void) {
73 hDC
= CreateCompatibleDC(NULL
);
74 GetTextMetrics(hDC
, &tm
);
77 system_font_height
= tm
.tmHeight
;
80 static HWND
create_rebar_control(void)
84 hwnd
= CreateWindow(REBARCLASSNAME
, NULL
, WS_CHILD
| WS_VISIBLE
, 0, 0, 0, 0,
85 hMainWnd
, (HMENU
)17, GetModuleHandle(NULL
), NULL
);
86 ok(hwnd
!= NULL
, "Failed to create Rebar\n");
88 SendMessageA(hwnd
, WM_SETFONT
, (WPARAM
)GetStockObject(SYSTEM_FONT
), 0);
93 static HWND
build_toolbar(int nr
, HWND hParent
)
96 HWND hToolbar
= CreateWindowEx(0, TOOLBARCLASSNAME
, NULL
, WS_CHILD
| WS_VISIBLE
| CCS_NORESIZE
, 0, 0, 0, 0,
97 hParent
, (HMENU
)5, GetModuleHandle(NULL
), NULL
);
101 ok(hToolbar
!= NULL
, "Toolbar creation problem\n");
102 ok(SendMessage(hToolbar
, TB_BUTTONSTRUCTSIZE
, sizeof(TBBUTTON
), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
103 ok(SendMessage(hToolbar
, TB_AUTOSIZE
, 0, 0) == 0, "TB_AUTOSIZE failed\n");
104 ok(SendMessage(hToolbar
, WM_SETFONT
, (WPARAM
)GetStockObject(SYSTEM_FONT
), 0)==1, "WM_SETFONT\n");
106 for (i
=0; i
<5+nr
; i
++)
109 btns
[i
].idCommand
= i
;
110 btns
[i
].fsStyle
= BTNS_BUTTON
;
111 btns
[i
].fsState
= TBSTATE_ENABLED
;
117 case 0: iBitmapId
= IDB_HIST_SMALL_COLOR
; break;
118 case 1: iBitmapId
= IDB_VIEW_SMALL_COLOR
; break;
119 case 2: iBitmapId
= IDB_STD_SMALL_COLOR
; break;
121 ok(SendMessage(hToolbar
, TB_LOADIMAGES
, iBitmapId
, (LPARAM
)HINST_COMMCTRL
) == 0, "TB_LOADIMAGES failed\n");
122 ok(SendMessage(hToolbar
, TB_ADDBUTTONS
, 5+nr
, (LPARAM
)btns
), "TB_ADDBUTTONS failed\n");
126 static LRESULT CALLBACK
MyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
132 NMHDR
*lpnm
= (NMHDR
*)lParam
;
133 if (lpnm
->code
== RBN_HEIGHTCHANGE
)
134 GetClientRect(lpnm
->hwndFrom
, &height_change_notify_rect
);
138 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
141 #if 0 /* use this to generate more tests*/
143 static void dump_sizes(HWND hRebar
)
150 GetClientRect(hRebar
, &r
);
151 count
= SendMessageA(hRebar
, RB_GETROWCOUNT
, 0, 0);
152 printf(" { {%d, %d, %d, %d}, %d, %d, {", r
.left
, r
.top
, r
.right
, r
.bottom
,
153 SendMessageA(hRebar
, RB_GETBARHEIGHT
, 0, 0), count
);
156 for (i
= 0; i
< count
; i
++) /* rows */
157 printf("%d, ", SendMessageA(hRebar
, RB_GETROWHEIGHT
, i
, 0));
160 count
= SendMessageA(hRebar
, RB_GETBANDCOUNT
, 0, 0);
161 printf("%d, {", count
);
163 printf("{{0, 0, 0, 0}, 0, 0},");
164 for (i
=0; i
<count
; i
++)
167 rbi
.cbSize
= REBARBANDINFOA_V6_SIZE
;
168 rbi
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_STYLE
;
169 ok(SendMessageA(hRebar
, RB_GETBANDINFOA
, i
, (LPARAM
)&rbi
), "RB_GETBANDINFO failed\n");
170 ok(SendMessageA(hRebar
, RB_GETRECT
, i
, (LPARAM
)&r
), "RB_GETRECT failed\n");
171 printf("%s{ {%3d, %3d, %3d, %3d}, 0x%02x, %d}, ", (i
%2==0 ? "\n " : ""), r
.left
, r
.top
, r
.right
, r
.bottom
,
174 printf("\n }, },\n");
177 #define check_sizes() dump_sizes(hRebar);
178 #define check_sizes_todo(todomask) dump_sizes(hRebar);
192 int cyRowHeights
[50];
194 rbband_result_t bands
[50];
197 static const rbsize_result_t rbsize_results
[] = {
198 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
200 { {0, 0, 672, 4}, 4, 1, {4, }, 1, {
201 { { 0, 0, 672, 4}, 0x00, 200},
203 { {0, 0, 672, 4}, 4, 1, {4, }, 2, {
204 { { 0, 0, 200, 4}, 0x00, 200}, { {200, 0, 672, 4}, 0x04, 200},
206 { {0, 0, 672, 30}, 30, 1, {30, }, 3, {
207 { { 0, 0, 200, 30}, 0x00, 200}, { {200, 0, 400, 30}, 0x04, 200},
208 { {400, 0, 672, 30}, 0x00, 200},
210 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
211 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
212 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
214 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
215 { { 0, 0, 200, 34}, 0x00, 200}, { {200, 0, 400, 34}, 0x04, 200},
216 { {400, 0, 604, 34}, 0x00, 200}, { {604, 0, 672, 34}, 0x04, 68},
218 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
219 { { 0, 0, 200, 34}, 0x00, 200}, { {202, 0, 402, 34}, 0x04, 200},
220 { {404, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
222 { {0, 0, 672, 70}, 70, 2, {34, 34, }, 5, {
223 { { 0, 0, 142, 34}, 0x00, 200}, { {144, 0, 557, 34}, 0x00, 200},
224 { {559, 0, 672, 34}, 0x04, 200}, { { 0, 36, 200, 70}, 0x00, 200},
225 { {202, 36, 672, 70}, 0x04, 66},
227 { {0, 0, 672, 34}, 34, 1, {34, }, 5, {
228 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
229 { {559, 0, 759, 34}, 0x08, 200}, { {584, 0, 627, 34}, 0x00, 200},
230 { {629, 0, 672, 34}, 0x04, 66},
232 { {0, 0, 672, 34}, 34, 1, {34, }, 4, {
233 { { 0, 0, 167, 34}, 0x00, 200}, { {169, 0, 582, 34}, 0x00, 200},
234 { {584, 0, 627, 34}, 0x00, 200}, { {629, 0, 672, 34}, 0x04, 66},
236 { {0, 0, 672, 34}, 34, 1, {34, }, 3, {
237 { { 0, 0, 413, 34}, 0x00, 200}, { {415, 0, 615, 34}, 0x00, 200},
238 { {617, 0, 672, 34}, 0x04, 66},
240 { {0, 0, 672, 34}, 34, 1, {34, }, 2, {
241 { { 0, 0, 604, 34}, 0x00, 200}, { {606, 0, 672, 34}, 0x04, 66},
243 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
244 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 184, 20}, 0x00, 70},
245 { {184, 0, 424, 20}, 0x00, 240}, { {424, 0, 672, 20}, 0x00, 60},
246 { { 0, 20, 672, 40}, 0x00, 200},
248 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
249 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 227, 20}, 0x00, 113},
250 { {227, 0, 424, 20}, 0x00, 197}, { {424, 0, 672, 20}, 0x00, 60},
251 { { 0, 20, 672, 40}, 0x00, 200},
253 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
254 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
255 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
256 { { 0, 20, 672, 40}, 0x00, 200},
258 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
259 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 167, 20}, 0x00, 53},
260 { {167, 0, 511, 20}, 0x00, 344}, { {511, 0, 672, 20}, 0x00, 161},
261 { { 0, 20, 672, 40}, 0x00, 200},
263 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
264 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
265 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
266 { { 0, 20, 672, 40}, 0x00, 200},
268 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
269 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
270 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
271 { { 0, 20, 672, 40}, 0x00, 200},
273 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
274 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
275 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
276 { { 0, 28, 672, 56}, 0x00, 200},
278 { {0, 0, 672, 40}, 40, 2, {20, 20, }, 5, {
279 { { 0, 0, 114, 20}, 0x00, 40}, { {114, 0, 328, 20}, 0x00, 214},
280 { {328, 0, 511, 20}, 0x00, 183}, { {511, 0, 672, 20}, 0x00, 161},
281 { { 0, 20, 672, 40}, 0x00, 200},
283 { {0, 0, 672, 56}, 56, 2, {28, 28, }, 5, {
284 { { 0, 0, 114, 28}, 0x00, 40}, { {114, 0, 328, 28}, 0x00, 214},
285 { {328, 0, 511, 28}, 0x00, 183}, { {511, 0, 672, 28}, 0x00, 161},
286 { { 0, 28, 672, 56}, 0x00, 200},
288 { {0, 0, 672, 0}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
290 { {0, 0, 672, 65}, 65, 1, {65, }, 3, {
291 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 180, 65}, 0x40, 90},
292 { {180, 0, 672, 65}, 0x40, 90},
294 { {0, 0, 0, 226}, 0, 0, {0, }, 0, {{{0, 0, 0, 0}, 0, 0},
296 { {0, 0, 65, 226}, 65, 1, {65, }, 1, {
297 { { 0, 0, 226, 65}, 0x40, 90},
299 { {0, 0, 65, 226}, 65, 1, {65, }, 2, {
300 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 226, 65}, 0x40, 90},
302 { {0, 0, 65, 226}, 65, 1, {65, }, 3, {
303 { { 0, 0, 90, 65}, 0x40, 90}, { { 90, 0, 163, 65}, 0x40, 90},
304 { {163, 0, 226, 65}, 0x40, 90},
308 static int rbsize_numtests
= 0;
310 #define check_sizes_todo(todomask) { \
313 int count, i/*, mask=(todomask)*/; \
314 const rbsize_result_t *res = &rbsize_results[rbsize_numtests]; \
315 assert(rbsize_numtests < sizeof(rbsize_results)/sizeof(rbsize_results[0])); \
316 GetClientRect(hRebar, &rc); \
317 check_rect("client", rc, res->rcClient); \
318 count = SendMessage(hRebar, RB_GETROWCOUNT, 0, 0); \
319 compare(count, res->nRows, "%d"); \
320 for (i=0; i<min(count, res->nRows); i++) { \
321 int height = SendMessageA(hRebar, RB_GETROWHEIGHT, 0, 0);\
322 ok(height == res->cyRowHeights[i], "Height mismatch for row %d - %d vs %d\n", i, res->cyRowHeights[i], height); \
324 count = SendMessage(hRebar, RB_GETBANDCOUNT, 0, 0); \
325 compare(count, res->nBands, "%d"); \
326 for (i=0; i<min(count, res->nBands); i++) { \
327 ok(SendMessageA(hRebar, RB_GETRECT, i, (LPARAM)&rc) == 1, "RB_GETRECT\n"); \
328 if (!(res->bands[i].fStyle & RBBS_HIDDEN)) \
329 check_rect("band", rc, res->bands[i].rc); \
330 rbi.cbSize = REBARBANDINFOA_V6_SIZE; \
331 rbi.fMask = RBBIM_STYLE | RBBIM_SIZE; \
332 ok(SendMessageA(hRebar, RB_GETBANDINFO, i, (LPARAM)&rbi) == 1, "RB_GETBANDINFO\n"); \
333 compare(rbi.fStyle, res->bands[i].fStyle, "%x"); \
334 compare(rbi.cx, res->bands[i].cx, "%d"); \
339 #define check_sizes() check_sizes_todo(0)
343 static void add_band_w(HWND hRebar
, LPCSTR lpszText
, int cxMinChild
, int cx
, int cxIdeal
)
345 CHAR buffer
[MAX_PATH
];
348 if (lpszText
!= NULL
)
349 strcpy(buffer
, lpszText
);
350 rbi
.cbSize
= REBARBANDINFOA_V6_SIZE
;
351 rbi
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_CHILD
| RBBIM_IDEALSIZE
| RBBIM_TEXT
;
353 rbi
.cxMinChild
= cxMinChild
;
354 rbi
.cxIdeal
= cxIdeal
;
356 rbi
.hwndChild
= build_toolbar(1, hRebar
);
357 rbi
.lpText
= (lpszText
? buffer
: NULL
);
358 SendMessage(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
361 static void test_layout(void)
368 hRebar
= create_rebar_control();
370 rbi
.cbSize
= REBARBANDINFOA_V6_SIZE
;
371 rbi
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_CHILD
;
373 rbi
.cxMinChild
= 100;
375 rbi
.hwndChild
= NULL
;
376 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
379 rbi
.fMask
|= RBBIM_STYLE
;
380 rbi
.fStyle
= RBBS_CHILDEDGE
;
381 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
388 rbi
.hwndChild
= build_toolbar(0, hRebar
);
389 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
392 rbi
.fStyle
= RBBS_CHILDEDGE
;
394 rbi
.hwndChild
= build_toolbar(0, hRebar
);
395 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
398 SetWindowLong(hRebar
, GWL_STYLE
, GetWindowLong(hRebar
, GWL_STYLE
) | RBS_BANDBORDERS
);
399 check_sizes(); /* a style change won't start a relayout */
400 rbi
.fMask
= RBBIM_SIZE
;
402 SendMessageA(hRebar
, RB_SETBANDINFO
, 3, (LPARAM
)&rbi
);
403 check_sizes(); /* here it will be relayouted */
405 /* this will force a new row */
406 rbi
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_CHILD
;
408 rbi
.cxMinChild
= 400;
410 rbi
.hwndChild
= build_toolbar(0, hRebar
);
411 SendMessageA(hRebar
, RB_INSERTBAND
, 1, (LPARAM
)&rbi
);
414 rbi
.fMask
= RBBIM_STYLE
;
415 rbi
.fStyle
= RBBS_HIDDEN
;
416 SendMessageA(hRebar
, RB_SETBANDINFO
, 2, (LPARAM
)&rbi
);
419 SendMessageA(hRebar
, RB_DELETEBAND
, 2, 0);
421 SendMessageA(hRebar
, RB_DELETEBAND
, 0, 0);
423 SendMessageA(hRebar
, RB_DELETEBAND
, 1, 0);
426 DestroyWindow(hRebar
);
428 hRebar
= create_rebar_control();
429 add_band_w(hRebar
, "ABC", 70, 40, 100);
430 add_band_w(hRebar
, NULL
, 40, 70, 100);
431 add_band_w(hRebar
, NULL
, 170, 240, 100);
432 add_band_w(hRebar
, "MMMMMMM", 60, 60, 100);
433 add_band_w(hRebar
, NULL
, 200, 200, 100);
435 SendMessageA(hRebar
, RB_MAXIMIZEBAND
, 1, TRUE
);
437 SendMessageA(hRebar
, RB_MAXIMIZEBAND
, 1, TRUE
);
439 SendMessageA(hRebar
, RB_MAXIMIZEBAND
, 2, FALSE
);
441 SendMessageA(hRebar
, RB_MINIMIZEBAND
, 2, 0);
443 SendMessageA(hRebar
, RB_MINIMIZEBAND
, 0, 0);
446 /* an image will increase the band height */
447 himl
= ImageList_LoadImage(LoadLibrary("comctl32"), MAKEINTRESOURCE(121), 24, 2, CLR_NONE
, IMAGE_BITMAP
, LR_DEFAULTCOLOR
);
448 ri
.cbSize
= sizeof(ri
);
449 ri
.fMask
= RBIM_IMAGELIST
;
451 ok(SendMessage(hRebar
, RB_SETBARINFO
, 0, (LPARAM
)&ri
), "RB_SETBARINFO failed\n");
452 rbi
.fMask
= RBBIM_IMAGE
;
454 SendMessage(hRebar
, RB_SETBANDINFO
, 1, (LPARAM
)&rbi
);
457 /* after removing it everything is back to normal*/
459 SendMessage(hRebar
, RB_SETBANDINFO
, 1, (LPARAM
)&rbi
);
462 /* Only -1 means that the image is not present. Other invalid values increase the height */
464 SendMessage(hRebar
, RB_SETBANDINFO
, 1, (LPARAM
)&rbi
);
467 DestroyWindow(hRebar
);
469 /* VARHEIGHT resizing test on a horizontal rebar */
470 hRebar
= create_rebar_control();
471 SetWindowLong(hRebar
, GWL_STYLE
, GetWindowLong(hRebar
, GWL_STYLE
) | RBS_AUTOSIZE
);
473 rbi
.fMask
= RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_SIZE
| RBBIM_STYLE
;
474 rbi
.fStyle
= RBBS_VARIABLEHEIGHT
;
479 rbi
.cyMaxChild
= 200;
481 rbi
.hwndChild
= build_toolbar(0, hRebar
);
482 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
485 rbi
.hwndChild
= build_toolbar(0, hRebar
);
486 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
491 rbi
.hwndChild
= build_toolbar(0, hRebar
);
492 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
495 DestroyWindow(hRebar
);
497 /* VARHEIGHT resizing on a vertical rebar */
498 hRebar
= create_rebar_control();
499 SetWindowLong(hRebar
, GWL_STYLE
, GetWindowLong(hRebar
, GWL_STYLE
) | CCS_VERT
| RBS_AUTOSIZE
);
501 rbi
.fMask
= RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_SIZE
| RBBIM_STYLE
;
502 rbi
.fStyle
= RBBS_VARIABLEHEIGHT
;
509 rbi
.hwndChild
= build_toolbar(0, hRebar
);
510 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
514 rbi
.hwndChild
= build_toolbar(0, hRebar
);
515 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
521 rbi
.hwndChild
= build_toolbar(0, hRebar
);
522 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
525 DestroyWindow(hRebar
);
526 ImageList_Destroy(himl
);
529 #if 0 /* use this to generate more tests */
531 static void dump_client(HWND hRebar
)
535 GetWindowRect(hRebar
, &r
);
536 MapWindowPoints(HWND_DESKTOP
, hMainWnd
, &r
, 2);
537 if (height_change_notify_rect
.top
!= -1)
540 GetClientRect(hRebar
, &rcClient
);
541 assert(EqualRect(&rcClient
, &height_change_notify_rect
));
546 printf(" {{%d, %d, %d, %d}, %d, %s},\n", r
.left
, r
.top
, r
.right
, r
.bottom
, SendMessage(hRebar
, RB_GETROWCOUNT
, 0, 0),
547 notify
? "TRUE" : "FALSE");
548 SetRect(&height_change_notify_rect
, -1, -1, -1, -1);
551 #define comment(fmt, arg1) printf("/* " fmt " */\n", arg1);
552 #define check_client() dump_client(hRebar)
560 } rbresize_test_result_t
;
562 static const rbresize_test_result_t resize_results
[] = {
564 {{0, 2, 672, 2}, 0, FALSE
},
565 {{0, 2, 672, 22}, 1, TRUE
},
566 {{0, 2, 672, 22}, 1, FALSE
},
567 {{0, 2, 672, 22}, 1, FALSE
},
568 {{0, 2, 672, 22}, 1, FALSE
},
569 {{0, 2, 672, 22}, 0, FALSE
},
571 {{0, 0, 672, 0}, 0, FALSE
},
572 {{0, 0, 672, 20}, 1, TRUE
},
573 {{0, 0, 672, 20}, 1, FALSE
},
574 {{0, 0, 672, 20}, 1, FALSE
},
575 {{0, 0, 672, 20}, 1, FALSE
},
576 {{0, 0, 672, 20}, 0, FALSE
},
578 {{0, 226, 672, 226}, 0, FALSE
},
579 {{0, 206, 672, 226}, 1, TRUE
},
580 {{0, 206, 672, 226}, 1, FALSE
},
581 {{0, 206, 672, 226}, 1, FALSE
},
582 {{0, 206, 672, 226}, 1, FALSE
},
583 {{0, 206, 672, 226}, 0, FALSE
},
585 {{0, 226, 672, 226}, 0, FALSE
},
586 {{0, 206, 672, 226}, 1, TRUE
},
587 {{0, 206, 672, 226}, 1, FALSE
},
588 {{0, 206, 672, 226}, 1, FALSE
},
589 {{0, 206, 672, 226}, 1, FALSE
},
590 {{0, 206, 672, 226}, 0, FALSE
},
592 {{2, 0, 2, 226}, 0, FALSE
},
593 {{2, 0, 22, 226}, 1, TRUE
},
594 {{2, 0, 22, 226}, 1, FALSE
},
595 {{2, 0, 22, 226}, 1, FALSE
},
596 {{2, 0, 22, 226}, 1, FALSE
},
597 {{2, 0, 22, 226}, 0, FALSE
},
599 {{672, 0, 672, 226}, 0, FALSE
},
600 {{652, 0, 672, 226}, 1, TRUE
},
601 {{652, 0, 672, 226}, 1, FALSE
},
602 {{652, 0, 672, 226}, 1, FALSE
},
603 {{652, 0, 672, 226}, 1, FALSE
},
604 {{652, 0, 672, 226}, 0, FALSE
},
606 {{10, 11, 510, 11}, 0, FALSE
},
607 {{10, 15, 510, 35}, 1, TRUE
},
608 {{10, 17, 510, 37}, 1, FALSE
},
609 {{10, 14, 110, 54}, 2, TRUE
},
610 {{0, 4, 0, 44}, 2, FALSE
},
611 {{0, 6, 0, 46}, 2, FALSE
},
612 {{0, 8, 0, 48}, 2, FALSE
},
613 {{0, 12, 0, 32}, 1, TRUE
},
614 {{0, 4, 100, 24}, 0, FALSE
},
616 {{10, 5, 510, 5}, 0, FALSE
},
617 {{10, 5, 510, 25}, 1, TRUE
},
618 {{10, 5, 510, 25}, 1, FALSE
},
619 {{10, 10, 110, 50}, 2, TRUE
},
620 {{0, 0, 0, 40}, 2, FALSE
},
621 {{0, 0, 0, 40}, 2, FALSE
},
622 {{0, 0, 0, 40}, 2, FALSE
},
623 {{0, 0, 0, 20}, 1, TRUE
},
624 {{0, 0, 100, 20}, 0, FALSE
},
626 {{10, 5, 510, 20}, 0, FALSE
},
627 {{10, 5, 510, 20}, 1, TRUE
},
628 {{10, 10, 110, 110}, 2, TRUE
},
629 {{0, 0, 0, 0}, 2, FALSE
},
630 {{0, 0, 0, 0}, 2, FALSE
},
631 {{0, 0, 0, 0}, 2, FALSE
},
632 {{0, 0, 0, 0}, 1, TRUE
},
633 {{0, 0, 100, 100}, 0, FALSE
},
635 {{0, 5, 672, 5}, 0, FALSE
},
636 {{0, 5, 672, 25}, 1, TRUE
},
637 {{0, 10, 672, 30}, 1, FALSE
},
638 {{0, 0, 672, 20}, 1, FALSE
},
639 {{0, 0, 672, 20}, 1, FALSE
},
640 {{0, 0, 672, 20}, 0, FALSE
},
642 {{10, 0, 10, 226}, 0, FALSE
},
643 {{10, 0, 30, 226}, 1, TRUE
},
644 {{10, 0, 30, 226}, 1, FALSE
},
645 {{0, 0, 20, 226}, 1, FALSE
},
646 {{0, 0, 20, 226}, 1, FALSE
},
647 {{0, 0, 20, 226}, 0, FALSE
},
649 {{-2, 0, 674, 4}, 0, FALSE
},
650 {{-2, 0, 674, 24}, 1, TRUE
},
651 {{-2, 0, 674, 24}, 1, FALSE
},
652 {{-2, 0, 674, 24}, 1, FALSE
},
653 {{-2, 0, 674, 24}, 1, FALSE
},
654 {{-2, 0, 674, 24}, 0, FALSE
},
656 {{10, 5, 510, 9}, 0, FALSE
},
657 {{10, 5, 510, 29}, 1, TRUE
},
658 {{10, 5, 510, 29}, 1, FALSE
},
659 {{10, 10, 110, 54}, 2, TRUE
},
660 {{0, 0, 0, 44}, 2, FALSE
},
661 {{0, 0, 0, 44}, 2, FALSE
},
662 {{0, 0, 0, 44}, 2, FALSE
},
663 {{0, 0, 0, 24}, 1, TRUE
},
664 {{0, 0, 100, 24}, 0, FALSE
},
666 {{10, 5, 510, 20}, 0, FALSE
},
667 {{10, 5, 510, 20}, 1, TRUE
},
668 {{10, 10, 110, 110}, 2, TRUE
},
669 {{0, 0, 0, 0}, 2, FALSE
},
670 {{0, 0, 0, 0}, 2, FALSE
},
671 {{0, 0, 0, 0}, 2, FALSE
},
672 {{0, 0, 0, 0}, 1, TRUE
},
673 {{0, 0, 100, 100}, 0, FALSE
},
675 {{-2, 5, 674, 9}, 0, FALSE
},
676 {{-2, 5, 674, 29}, 1, TRUE
},
677 {{-2, 10, 674, 34}, 1, FALSE
},
678 {{-2, 0, 674, 24}, 1, FALSE
},
679 {{-2, 0, 674, 24}, 1, FALSE
},
680 {{-2, 0, 674, 24}, 0, FALSE
},
683 static int resize_numtests
= 0;
685 #define comment(fmt, arg1)
686 #define check_client() { \
688 const rbresize_test_result_t *res = &resize_results[resize_numtests++]; \
689 assert(resize_numtests <= sizeof(resize_results)/sizeof(resize_results[0])); \
690 GetWindowRect(hRebar, &r); \
691 MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); \
692 if ((dwStyles[i] & (CCS_NOPARENTALIGN|CCS_NODIVIDER)) == CCS_NOPARENTALIGN) {\
693 check_rect_no_top("client", r, res->rc); /* the top coordinate changes after every layout and is very implementation-dependent */ \
695 check_rect("client", r, res->rc); \
697 expect_eq((int)SendMessage(hRebar, RB_GETROWCOUNT, 0, 0), res->iNumRows, int, "%d"); \
698 if (res->heightNotify) { \
700 GetClientRect(hRebar, &rcClient); \
701 check_rect("notify", height_change_notify_rect, rcClient); \
702 } else ok(height_change_notify_rect.top == -1, "Unexpected RBN_HEIGHTCHANGE received\n"); \
703 SetRect(&height_change_notify_rect, -1, -1, -1, -1); \
708 static void test_resize(void)
710 DWORD dwStyles
[] = {CCS_TOP
, CCS_TOP
| CCS_NODIVIDER
, CCS_BOTTOM
, CCS_BOTTOM
| CCS_NODIVIDER
, CCS_VERT
, CCS_RIGHT
,
711 CCS_NOPARENTALIGN
, CCS_NOPARENTALIGN
| CCS_NODIVIDER
, CCS_NORESIZE
, CCS_NOMOVEY
, CCS_NOMOVEY
| CCS_VERT
,
712 CCS_TOP
| WS_BORDER
, CCS_NOPARENTALIGN
| CCS_NODIVIDER
| WS_BORDER
, CCS_NORESIZE
| WS_BORDER
,
713 CCS_NOMOVEY
| WS_BORDER
};
715 const int styles_count
= sizeof(dwStyles
) / sizeof(dwStyles
[0]);
718 for (i
= 0; i
< styles_count
; i
++)
722 comment("style %08x", dwStyles
[i
]);
723 SetRect(&height_change_notify_rect
, -1, -1, -1, -1);
724 hRebar
= CreateWindow(REBARCLASSNAME
, "A", dwStyles
[i
] | WS_CHILD
| WS_VISIBLE
, 10, 5, 500, 15, hMainWnd
, NULL
, GetModuleHandle(NULL
), 0);
726 add_band_w(hRebar
, NULL
, 70, 100, 0);
727 if (dwStyles
[i
] & CCS_NOPARENTALIGN
) /* the window drifts downward for CCS_NOPARENTALIGN without CCS_NODIVIDER */
729 add_band_w(hRebar
, NULL
, 70, 100, 0);
731 MoveWindow(hRebar
, 10, 10, 100, 100, TRUE
);
733 MoveWindow(hRebar
, 0, 0, 0, 0, TRUE
);
735 /* try to fool the rebar by sending invalid width/height - won't work */
736 if (dwStyles
[i
] & (CCS_NORESIZE
| CCS_NOPARENTALIGN
))
740 pos
.hwndInsertAfter
= NULL
;
746 SendMessage(hRebar
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)&pos
);
747 SendMessage(hRebar
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&pos
);
749 SendMessage(hRebar
, WM_SIZE
, SIZE_RESTORED
, MAKELONG(500, 500));
752 SendMessage(hRebar
, RB_DELETEBAND
, 0, 0);
754 SendMessage(hRebar
, RB_DELETEBAND
, 0, 0);
755 MoveWindow(hRebar
, 0, 0, 100, 100, TRUE
);
757 DestroyWindow(hRebar
);
761 static void expect_band_content(HWND hRebar
, UINT uBand
, INT fStyle
, COLORREF clrFore
,
762 COLORREF clrBack
, LPCSTR lpText
, int iImage
, HWND hwndChild
,
763 INT cxMinChild
, INT cyMinChild
, INT cx
, HBITMAP hbmBack
, INT wID
,
764 INT cyChild
, INT cyMaxChild
, INT cyIntegral
, INT cxIdeal
, LPARAM lParam
,
765 INT cxHeader
, INT cxHeader_broken
)
767 CHAR buf
[MAX_PATH
] = "abc";
770 memset(&rb
, 0xdd, sizeof(rb
));
771 rb
.cbSize
= REBARBANDINFOA_V6_SIZE
;
772 rb
.fMask
= RBBIM_BACKGROUND
| RBBIM_CHILD
| RBBIM_CHILDSIZE
| RBBIM_COLORS
773 | RBBIM_HEADERSIZE
| RBBIM_ID
| RBBIM_IDEALSIZE
| RBBIM_IMAGE
| RBBIM_LPARAM
774 | RBBIM_SIZE
| RBBIM_STYLE
| RBBIM_TEXT
;
777 ok(SendMessageA(hRebar
, RB_GETBANDINFOA
, uBand
, (LPARAM
)&rb
), "RB_GETBANDINFO failed\n");
778 expect_eq(rb
.fStyle
, fStyle
, int, "%x");
779 expect_eq(rb
.clrFore
, clrFore
, COLORREF
, "%x");
780 expect_eq(rb
.clrBack
, clrBack
, COLORREF
, "%x");
781 expect_eq(strcmp(rb
.lpText
, lpText
), 0, int, "%d");
782 expect_eq(rb
.iImage
, iImage
, int, "%x");
783 expect_eq(rb
.hwndChild
, hwndChild
, HWND
, "%p");
784 expect_eq(rb
.cxMinChild
, cxMinChild
, int, "%d");
785 expect_eq(rb
.cyMinChild
, cyMinChild
, int, "%d");
786 expect_eq(rb
.cx
, cx
, int, "%d");
787 expect_eq(rb
.hbmBack
, hbmBack
, HBITMAP
, "%p");
788 expect_eq(rb
.wID
, wID
, int, "%d");
789 /* the values of cyChild, cyMaxChild and cyIntegral can't be read unless the band is RBBS_VARIABLEHEIGHT */
790 expect_eq(rb
.cyChild
, cyChild
, int, "%x");
791 expect_eq(rb
.cyMaxChild
, cyMaxChild
, int, "%x");
792 expect_eq(rb
.cyIntegral
, cyIntegral
, int, "%x");
793 expect_eq(rb
.cxIdeal
, cxIdeal
, int, "%d");
794 expect_eq(rb
.lParam
, lParam
, LPARAM
, "%ld");
795 ok( rb
.cxHeader
== cxHeader
|| broken(rb
.cxHeader
== cxHeader_broken
),
796 "expected %d for %d\n", cxHeader
, rb
.cxHeader
);
799 static void test_bandinfo(void)
802 CHAR szABC
[] = "ABC";
803 CHAR szABCD
[] = "ABCD";
806 hRebar
= create_rebar_control();
807 rb
.cbSize
= REBARBANDINFOA_V6_SIZE
;
809 if (!SendMessageA(hRebar
, RB_INSERTBANDA
, 0, (LPARAM
)&rb
))
811 win_skip( "V6 info not supported\n" );
812 DestroyWindow(hRebar
);
815 expect_band_content(hRebar
, 0, 0, 0, GetSysColor(COLOR_3DFACE
), "", -1, NULL
, 0, 0, 0, NULL
, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
817 rb
.fMask
= RBBIM_CHILDSIZE
;
823 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
824 expect_band_content(hRebar
, 0, 0, 0, GetSysColor(COLOR_3DFACE
), "", -1, NULL
, 15, 20, 0, NULL
, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 0, -1);
826 rb
.fMask
= RBBIM_TEXT
;
828 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
829 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);
831 rb
.cbSize
= REBARBANDINFOA_V6_SIZE
;
833 ok(SendMessageA(hRebar
, RB_INSERTBANDA
, 1, (LPARAM
)&rb
), "RB_INSERTBAND failed\n");
834 expect_band_content(hRebar
, 1, 0, 0, GetSysColor(COLOR_3DFACE
), "", -1, NULL
, 0, 0, 0, NULL
, 0, 0xdddddddd, 0xdddddddd, 0xdddddddd, 0, 0, 9, -1);
835 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);
837 rb
.fMask
= RBBIM_HEADERSIZE
;
839 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
840 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);
843 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
844 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);
846 rb
.fMask
= RBBIM_TEXT
;
848 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
849 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);
850 rb
.fMask
= RBBIM_STYLE
| RBBIM_TEXT
;
851 rb
.fStyle
= RBBS_VARIABLEHEIGHT
;
853 ok(SendMessageA(hRebar
, RB_SETBANDINFOA
, 0, (LPARAM
)&rb
), "RB_SETBANDINFO failed\n");
854 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);
856 DestroyWindow(hRebar
);
859 static void test_colors(void)
867 hRebar
= create_rebar_control();
869 /* test default colors */
870 clr
= SendMessage(hRebar
, RB_GETTEXTCOLOR
, 0, 0);
871 compare(clr
, CLR_NONE
, "%x");
872 clr
= SendMessage(hRebar
, RB_GETBKCOLOR
, 0, 0);
873 compare(clr
, CLR_NONE
, "%x");
875 scheme
.dwSize
= sizeof(scheme
);
876 scheme
.clrBtnHighlight
= 0;
877 scheme
.clrBtnShadow
= 0;
878 ret
= SendMessage(hRebar
, RB_GETCOLORSCHEME
, 0, (LPARAM
)&scheme
);
881 compare(scheme
.clrBtnHighlight
, CLR_DEFAULT
, "%x");
882 compare(scheme
.clrBtnShadow
, CLR_DEFAULT
, "%x");
885 skip("RB_GETCOLORSCHEME not supported\n");
887 /* check default band colors */
888 add_band_w(hRebar
, "", 0, 10, 10);
889 bi
.cbSize
= REBARBANDINFOA_V6_SIZE
;
890 bi
.fMask
= RBBIM_COLORS
;
891 bi
.clrFore
= bi
.clrBack
= 0xc0ffe;
892 ret
= SendMessage(hRebar
, RB_GETBANDINFO
, 0, (LPARAM
)&bi
);
893 ok(ret
, "RB_GETBANDINFO failed\n");
894 compare(bi
.clrFore
, RGB(0, 0, 0), "%x");
895 compare(bi
.clrBack
, GetSysColor(COLOR_3DFACE
), "%x");
897 SendMessage(hRebar
, RB_SETTEXTCOLOR
, 0, RGB(255, 0, 0));
898 bi
.clrFore
= bi
.clrBack
= 0xc0ffe;
899 ret
= SendMessage(hRebar
, RB_GETBANDINFO
, 0, (LPARAM
)&bi
);
900 ok(ret
, "RB_GETBANDINFO failed\n");
901 compare(bi
.clrFore
, RGB(0, 0, 0), "%x");
903 DestroyWindow(hRebar
);
907 static BOOL
register_parent_wnd_class(void)
911 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
914 wc
.hInstance
= GetModuleHandleA(NULL
);
916 wc
.hCursor
= LoadCursorA(NULL
, IDC_IBEAM
);
917 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
918 wc
.lpszMenuName
= NULL
;
919 wc
.lpszClassName
= "MyTestWnd";
920 wc
.lpfnWndProc
= MyWndProc
;
922 return RegisterClassA(&wc
);
925 static HWND
create_parent_window(void)
929 if (!register_parent_wnd_class()) return NULL
;
931 hwnd
= CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW
,
932 CW_USEDEFAULT
, CW_USEDEFAULT
, 672+2*GetSystemMetrics(SM_CXSIZEFRAME
),
933 226+GetSystemMetrics(SM_CYCAPTION
)+2*GetSystemMetrics(SM_CYSIZEFRAME
),
934 NULL
, NULL
, GetModuleHandleA(NULL
), 0);
936 ShowWindow(hwnd
, SW_SHOW
);
940 static void test_showband(void)
946 hRebar
= create_rebar_control();
949 ret
= SendMessageA(hRebar
, RB_SHOWBAND
, 0, TRUE
);
950 ok(ret
== FALSE
, "got %d\n", ret
);
952 rbi
.cbSize
= REBARBANDINFOA_V6_SIZE
;
953 rbi
.fMask
= RBBIM_SIZE
| RBBIM_CHILDSIZE
| RBBIM_CHILD
;
955 rbi
.cxMinChild
= 100;
957 rbi
.hwndChild
= NULL
;
958 SendMessageA(hRebar
, RB_INSERTBAND
, -1, (LPARAM
)&rbi
);
960 /* index out of range */
961 ret
= SendMessageA(hRebar
, RB_SHOWBAND
, 1, TRUE
);
962 ok(ret
== FALSE
, "got %d\n", ret
);
964 ret
= SendMessageA(hRebar
, RB_SHOWBAND
, 0, TRUE
);
965 ok(ret
== TRUE
, "got %d\n", ret
);
967 DestroyWindow(hRebar
);
973 BOOL (WINAPI
*pInitCommonControlsEx
)(const INITCOMMONCONTROLSEX
*);
974 INITCOMMONCONTROLSEX iccex
;
977 init_system_font_height();
979 /* LoadLibrary is needed. This file has no references to functions in comctl32 */
980 hComctl32
= LoadLibraryA("comctl32.dll");
981 pInitCommonControlsEx
= (void*)GetProcAddress(hComctl32
, "InitCommonControlsEx");
982 if (!pInitCommonControlsEx
)
984 win_skip("InitCommonControlsEx() is missing. Skipping the tests\n");
987 iccex
.dwSize
= sizeof(iccex
);
988 iccex
.dwICC
= ICC_COOL_CLASSES
;
989 pInitCommonControlsEx(&iccex
);
991 hMainWnd
= create_parent_window();
997 if(!is_font_installed("System") || !is_font_installed("Tahoma"))
999 skip("Missing System or Tahoma font\n");
1008 while(GetMessageA(&msg
,0,0,0)) {
1009 TranslateMessage(&msg
);
1010 DispatchMessageA(&msg
);
1012 DestroyWindow(hMainWnd
);
1014 FreeLibrary(hComctl32
);