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