urlmon: Don't create stgmed_obj for binding to object.
[wine] / dlls / comctl32 / tests / toolbar.c
1 /* Unit tests for treeview.
2  *
3  * Copyright 2005 Krzysztof Foltman
4  * Copyright 2007 Mikolaj Zalewski
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <assert.h>
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
29 #include "winreg.h"
30 #include "commctrl.h" 
31
32 #include "resources.h"
33
34 #include "wine/test.h"
35
36 static HWND hMainWnd;
37 static BOOL g_fBlockHotItemChange;
38 static BOOL g_fReceivedHotItemChange;
39 static BOOL g_fExpectedHotItemOld;
40 static BOOL g_fExpectedHotItemNew;
41 static DWORD g_dwExpectedDispInfoMask;
42
43 #define check_rect(name, val, exp) ok(val.top == exp.top && val.bottom == exp.bottom && \
44     val.left == exp.left && val.right == exp.right, "invalid rect (" name ") (%d,%d) (%d,%d) - expected (%d,%d) (%d,%d)\n", \
45     val.left, val.top, val.right, val.bottom, exp.left, exp.top, exp.right, exp.bottom);
46  
47 #define compare(val, exp, format) ok((val) == (exp), #val " value " format " expected " format "\n", (val), (exp));
48
49 static void MakeButton(TBBUTTON *p, int idCommand, int fsStyle, int nString) {
50   p->iBitmap = -2;
51   p->idCommand = idCommand;
52   p->fsState = TBSTATE_ENABLED;
53   p->fsStyle = fsStyle;
54   p->iString = nString;
55 }
56
57 static LRESULT MyWnd_Notify(LPARAM lParam)
58 {
59     NMHDR *hdr = (NMHDR *)lParam;
60     NMTBHOTITEM *nmhi;
61     NMTBDISPINFO *nmdisp;
62     switch (hdr->code)
63     {
64         case TBN_HOTITEMCHANGE:
65             nmhi = (NMTBHOTITEM *)lParam;
66             g_fReceivedHotItemChange = TRUE;
67             if (g_fExpectedHotItemOld != g_fExpectedHotItemNew)
68             {
69                 compare(nmhi->idOld, g_fExpectedHotItemOld, "%d");
70                 compare(nmhi->idNew, g_fExpectedHotItemNew, "%d");
71             }
72             if (g_fBlockHotItemChange)
73                 return 1;
74             break;
75
76         case TBN_GETDISPINFOA:
77             ok(FALSE, "TBN_GETDISPINFOA received\n");
78             break;
79
80         case TBN_GETDISPINFOW:
81             nmdisp = (NMTBDISPINFOA *)lParam;
82
83             compare(nmdisp->dwMask, g_dwExpectedDispInfoMask, "%x");
84             compare(nmdisp->iImage, -1, "%d");
85             ok(nmdisp->pszText == NULL, "pszText is not NULL\n");
86         break;
87     }
88     return 0;
89 }
90
91 static LRESULT CALLBACK MyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
92 {
93     switch (msg)
94     {
95         case WM_NOTIFY:
96             return MyWnd_Notify(lParam);
97     }
98     return DefWindowProcA(hWnd, msg, wParam, lParam);
99 }
100
101 static void basic_test(void)
102 {
103     TBBUTTON buttons[9];
104     HWND hToolbar;
105     int i;
106     for (i=0; i<9; i++)
107         MakeButton(buttons+i, 1000+i, TBSTYLE_CHECKGROUP, 0);
108     MakeButton(buttons+3, 1003, TBSTYLE_SEP|TBSTYLE_GROUP, 0);
109     MakeButton(buttons+6, 1006, TBSTYLE_SEP, 0);
110
111     hToolbar = CreateToolbarEx(hMainWnd,
112         WS_VISIBLE | WS_CLIPCHILDREN | CCS_TOP |
113         WS_CHILD | TBSTYLE_LIST,
114         100,
115         0, NULL, (UINT)0,
116         buttons, sizeof(buttons)/sizeof(buttons[0]),
117         0, 0, 20, 16, sizeof(TBBUTTON));
118     ok(hToolbar != NULL, "Toolbar creation\n");
119     SendMessage(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"test\000");
120
121     /* test for exclusion working inside a separator-separated :-) group */
122     SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 */
123     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
124     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1001, 0), "A2 not pressed\n");
125
126     SendMessage(hToolbar, TB_CHECKBUTTON, 1004, 1); /* press A5, release A1 */
127     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 pressed\n");
128     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 not pressed anymore\n");
129
130     SendMessage(hToolbar, TB_CHECKBUTTON, 1005, 1); /* press A6, release A5 */
131     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
132     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1004, 0), "A5 not pressed anymore\n");
133
134     /* test for inter-group crosstalk, ie. two radio groups interfering with each other */
135     SendMessage(hToolbar, TB_CHECKBUTTON, 1007, 1); /* press B2 */
136     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 still pressed, no inter-group crosstalk\n");
137     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 still not pressed\n");
138     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 pressed\n");
139
140     SendMessage(hToolbar, TB_CHECKBUTTON, 1000, 1); /* press A1 and ensure B group didn't suffer */
141     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 not pressed anymore\n");
142     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
143     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 still pressed\n");
144
145     SendMessage(hToolbar, TB_CHECKBUTTON, 1008, 1); /* press B3, and ensure A group didn't suffer */
146     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1005, 0), "A6 pressed\n");
147     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1000, 0), "A1 pressed\n");
148     ok(!SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1007, 0), "B2 not pressed\n");
149     ok(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 1008, 0), "B3 pressed\n");
150
151     /* tests with invalid index */
152     compare(SendMessage(hToolbar, TB_ISBUTTONCHECKED, 0xdeadbeef, 0), -1L, "%ld");
153     compare(SendMessage(hToolbar, TB_ISBUTTONPRESSED, 0xdeadbeef, 0), -1L, "%ld");
154     compare(SendMessage(hToolbar, TB_ISBUTTONENABLED, 0xdeadbeef, 0), -1L, "%ld");
155     compare(SendMessage(hToolbar, TB_ISBUTTONINDETERMINATE, 0xdeadbeef, 0), -1L, "%ld");
156     compare(SendMessage(hToolbar, TB_ISBUTTONHIGHLIGHTED, 0xdeadbeef, 0), -1L, "%ld");
157     compare(SendMessage(hToolbar, TB_ISBUTTONHIDDEN, 0xdeadbeef, 0), -1L, "%ld");
158
159     DestroyWindow(hToolbar);
160 }
161
162 static void rebuild_toolbar(HWND *hToolbar)
163 {
164     if (*hToolbar != NULL)
165         DestroyWindow(*hToolbar);
166     *hToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0,
167         hMainWnd, (HMENU)5, GetModuleHandle(NULL), NULL);
168     ok(*hToolbar != NULL, "Toolbar creation problem\n");
169     ok(SendMessage(*hToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0) == 0, "TB_BUTTONSTRUCTSIZE failed\n");
170     ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
171     ok(SendMessage(*hToolbar, WM_SETFONT, (WPARAM)GetStockObject(SYSTEM_FONT), 0)==1, "WM_SETFONT\n");
172 }
173
174 static void rebuild_toolbar_with_buttons(HWND *hToolbar)
175 {
176     TBBUTTON buttons[5];
177     rebuild_toolbar(hToolbar);
178     
179     ZeroMemory(&buttons, sizeof(buttons));
180     buttons[0].idCommand = 1;
181     buttons[0].fsStyle = BTNS_BUTTON;
182     buttons[0].fsState = TBSTATE_ENABLED;
183     buttons[0].iString = -1;
184     buttons[1].idCommand = 3;
185     buttons[1].fsStyle = BTNS_BUTTON;
186     buttons[1].fsState = TBSTATE_ENABLED;
187     buttons[1].iString = -1;
188     buttons[2].idCommand = 5;
189     buttons[2].fsStyle = BTNS_SEP;
190     buttons[2].fsState = TBSTATE_ENABLED;
191     buttons[2].iString = -1;
192     buttons[3].idCommand = 7;
193     buttons[3].fsStyle = BTNS_BUTTON;
194     buttons[3].fsState = TBSTATE_ENABLED;
195     buttons[3].iString = -1;
196     buttons[4].idCommand = 9;
197     buttons[4].fsStyle = BTNS_BUTTON;
198     buttons[4].fsState = 0;  /* disabled */
199     buttons[4].iString = -1;
200     ok(SendMessage(*hToolbar, TB_ADDBUTTONS, 5, (LPARAM)buttons) == 1, "TB_ADDBUTTONS failed\n");
201     ok(SendMessage(*hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
202 }
203
204
205 #define CHECK_IMAGELIST(count, dx, dy) { \
206     int cx, cy; \
207     HIMAGELIST himl = (HIMAGELIST)SendMessageA(hToolbar, TB_GETIMAGELIST, 0, 0); \
208     ok(himl != NULL, "No image list\n"); \
209     if (himl != NULL) {\
210         ok(ImageList_GetImageCount(himl) == count, "Images count mismatch - %d vs %d\n", count, ImageList_GetImageCount(himl)); \
211         ImageList_GetIconSize(himl, &cx, &cy); \
212         ok(cx == dx && cy == dy, "Icon size mismatch - %dx%d vs %dx%d\n", dx, dy, cx, cy); \
213     } \
214 }
215
216 static void test_add_bitmap(void)
217 {
218     HWND hToolbar = NULL;
219     TBADDBITMAP bmp128;
220     TBADDBITMAP bmp80;
221     TBADDBITMAP stdsmall;
222     TBADDBITMAP addbmp;
223     HIMAGELIST himl;
224     INT ret;
225
226     /* empty 128x15 bitmap */
227     bmp128.hInst = GetModuleHandle(NULL);
228     bmp128.nID = IDB_BITMAP_128x15;
229
230     /* empty 80x15 bitmap */
231     bmp80.hInst = GetModuleHandle(NULL);
232     bmp80.nID = IDB_BITMAP_80x15;
233
234     /* standard bitmap - 240x15 pixels */
235     stdsmall.hInst = HINST_COMMCTRL;
236     stdsmall.nID = IDB_STD_SMALL_COLOR;
237
238     rebuild_toolbar(&hToolbar);
239     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 8, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
240     CHECK_IMAGELIST(8, 16, 16);
241     
242     /* adding more bitmaps */
243     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80) == 8, "TB_ADDBITMAP - unexpected return\n");
244     CHECK_IMAGELIST(13, 16, 16);
245     /* adding the same bitmap will simply return the index of the already loaded block */
246     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 8, (LPARAM)&bmp128);
247     ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
248     CHECK_IMAGELIST(13, 16, 16);
249     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80);
250     ok(ret == 8, "TB_ADDBITMAP - unexpected return %d\n", ret);
251     CHECK_IMAGELIST(13, 16, 16);
252     /* even if we increase the wParam */
253     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 55, (LPARAM)&bmp80);
254     ok(ret == 8, "TB_ADDBITMAP - unexpected return %d\n", ret);
255     CHECK_IMAGELIST(13, 16, 16);
256
257     /* when the wParam is smaller than the bitmaps count but non-zero, all the bitmaps will be added*/
258     rebuild_toolbar(&hToolbar);
259     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 3, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
260     CHECK_IMAGELIST(8, 16, 16);
261     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80);
262     ok(ret == 3, "TB_ADDBITMAP - unexpected return %d\n", ret);
263     /* the returned value is misleading - id 8 is the id of the first icon from bmp80 */
264     CHECK_IMAGELIST(13, 16, 16);
265
266     /* the same for negative wParam */
267     rebuild_toolbar(&hToolbar);
268     ret = SendMessageA(hToolbar, TB_ADDBITMAP, -143, (LPARAM)&bmp128);
269     ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
270     CHECK_IMAGELIST(8, 16, 16);
271     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp80);
272     ok(ret == -143, "TB_ADDBITMAP - unexpected return %d\n", ret);
273     CHECK_IMAGELIST(13, 16, 16);
274
275     /* for zero only one bitmap will be added */
276     rebuild_toolbar(&hToolbar);
277     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&bmp80);
278     ok(ret == 0, "TB_ADDBITMAP - unexpected return %d\n", ret);
279     CHECK_IMAGELIST(1, 16, 16);
280
281     /* if wParam is larger than the amount of icons, the list is grown */
282     rebuild_toolbar(&hToolbar);
283     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp80) == 0, "TB_ADDBITMAP - unexpected return\n");
284     CHECK_IMAGELIST(100, 16, 16);
285     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp128);
286     ok(ret == 100, "TB_ADDBITMAP - unexpected return %d\n", ret);
287     CHECK_IMAGELIST(200, 16, 16);
288
289     /* adding built-in items - the wParam is ignored */
290     rebuild_toolbar(&hToolbar);
291     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp80) == 0, "TB_ADDBITMAP - unexpected return\n");
292     CHECK_IMAGELIST(5, 16, 16);
293     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&stdsmall) == 5, "TB_ADDBITMAP - unexpected return\n");
294     CHECK_IMAGELIST(20, 16, 16);
295     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp128) == 20, "TB_ADDBITMAP - unexpected return\n");
296     CHECK_IMAGELIST(28, 16, 16);
297
298     /* when we increase the bitmap size, less icons will be created */
299     rebuild_toolbar(&hToolbar);
300     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20)) == TRUE, "TB_SETBITMAPSIZE failed\n");
301     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
302     CHECK_IMAGELIST(6, 20, 20);
303     ret = SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp80);
304     ok(ret == 1, "TB_ADDBITMAP - unexpected return %d\n", ret);
305     CHECK_IMAGELIST(10, 20, 20);
306     /* the icons can be resized - an UpdateWindow is needed as this probably happens during WM_PAINT */
307     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
308     UpdateWindow(hToolbar);
309     CHECK_IMAGELIST(26, 8, 8);
310     /* loading a standard bitmaps automatically resizes the icons */
311     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&stdsmall) == 2, "TB_ADDBITMAP - unexpected return\n");
312     UpdateWindow(hToolbar);
313     CHECK_IMAGELIST(28, 16, 16);
314
315     /* two more SETBITMAPSIZE tests */
316     rebuild_toolbar(&hToolbar);
317     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
318     CHECK_IMAGELIST(100, 16, 16);
319     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 100, (LPARAM)&bmp80) == 100, "TB_ADDBITMAP - unexpected return\n");
320     CHECK_IMAGELIST(200, 16, 16);
321     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
322     UpdateWindow(hToolbar);
323     CHECK_IMAGELIST(200, 8, 8);
324     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(30, 30)) == TRUE, "TB_SETBITMAPSIZE failed\n");
325     UpdateWindow(hToolbar);
326     CHECK_IMAGELIST(200, 30, 30);
327     rebuild_toolbar(&hToolbar);
328     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 5, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
329     CHECK_IMAGELIST(8, 16, 16);
330     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 3, (LPARAM)&bmp80) == 5, "TB_ADDBITMAP - unexpected return\n");
331     CHECK_IMAGELIST(13, 16, 16);
332     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(30, 30)) == TRUE, "TB_SETBITMAPSIZE failed\n");
333     UpdateWindow(hToolbar);
334     CHECK_IMAGELIST(8, 30, 30);
335     /* when the width or height is zero, set it to 1 */
336     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(0, 0)) == TRUE, "TB_SETBITMAPSIZE failed\n");
337     UpdateWindow(hToolbar);
338     CHECK_IMAGELIST(208, 1, 1);
339     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(0, 5)) == TRUE, "TB_SETBITMAPSIZE failed\n");
340     UpdateWindow(hToolbar);
341     CHECK_IMAGELIST(208, 1, 5);
342     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(5, 0)) == TRUE, "TB_SETBITMAPSIZE failed\n");
343     UpdateWindow(hToolbar);
344     CHECK_IMAGELIST(41, 5, 1);
345
346     /* the control can add bitmaps to an existing image list */
347     rebuild_toolbar(&hToolbar);
348     himl = ImageList_LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_80x15), 20, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
349     ok(himl != NULL, "failed to create imagelist\n");
350     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
351     CHECK_IMAGELIST(4, 20, 15);
352     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&bmp128) == 0, "TB_ADDBITMAP - unexpected return\n");
353     CHECK_IMAGELIST(10, 20, 15);
354     /* however TB_SETBITMAPSIZE/add std bitmap won't change the image size (the button size does change) */
355     ok(SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(8, 8)) == TRUE, "TB_SETBITMAPSIZE failed\n");
356     UpdateWindow(hToolbar);
357     compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(15, 14), "%x");
358     CHECK_IMAGELIST(10, 20, 15);
359     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 0, (LPARAM)&stdsmall) == 1, "TB_SETBITMAPSIZE failed\n");
360     UpdateWindow(hToolbar);
361     compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(23, 22), "%x");
362     CHECK_IMAGELIST(22, 20, 15);
363
364     /* check standard bitmaps */
365     addbmp.hInst = HINST_COMMCTRL;
366     addbmp.nID = IDB_STD_SMALL_COLOR;
367     rebuild_toolbar(&hToolbar);
368     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
369     CHECK_IMAGELIST(15, 16, 16);
370     compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(23, 22), "%x");
371     addbmp.nID = IDB_STD_LARGE_COLOR;
372     rebuild_toolbar(&hToolbar);
373     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
374     CHECK_IMAGELIST(15, 24, 24);
375     compare((int)SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0), MAKELONG(31, 30), "%x");
376
377     addbmp.nID = IDB_VIEW_SMALL_COLOR;
378     rebuild_toolbar(&hToolbar);
379     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
380     CHECK_IMAGELIST(12, 16, 16);
381     addbmp.nID = IDB_VIEW_LARGE_COLOR;
382     rebuild_toolbar(&hToolbar);
383     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
384     CHECK_IMAGELIST(12, 24, 24);
385
386     addbmp.nID = IDB_HIST_SMALL_COLOR;
387     rebuild_toolbar(&hToolbar);
388     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
389     CHECK_IMAGELIST(5, 16, 16);
390     addbmp.nID = IDB_HIST_LARGE_COLOR;
391     rebuild_toolbar(&hToolbar);
392     ok(SendMessageA(hToolbar, TB_ADDBITMAP, 1, (LPARAM)&addbmp) == 0, "TB_ADDBITMAP - unexpected return\n");
393     CHECK_IMAGELIST(5, 24, 24);
394
395
396     DestroyWindow(hToolbar);
397 }
398
399 #define CHECK_STRING_TABLE(count, tab) { \
400         INT _i; \
401         CHAR _buf[260]; \
402         for (_i = 0; _i < (count); _i++) {\
403             ret = SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, _i), (LPARAM)_buf); \
404             ok(ret >= 0, "TB_GETSTRING - unexpected return %d while checking string %d\n", ret, _i); \
405             if (ret >= 0) \
406                 ok(strcmp(_buf, (tab)[_i]) == 0, "Invalid string #%d - '%s' vs '%s'\n", _i, (tab)[_i], _buf); \
407         } \
408         ok(SendMessageA(hToolbar, TB_GETSTRING, MAKEWPARAM(260, (count)), (LPARAM)_buf) == -1, \
409             "Too many string in table\n"); \
410     }
411
412 static void test_add_string(void)
413 {
414     LPCSTR test1 = "a\0b\0";
415     LPCSTR test2 = "|a|b||\0";
416     LPCSTR ret1[] = {"a", "b"};
417     LPCSTR ret2[] = {"a", "b", "|a|b||"};
418     LPCSTR ret3[] = {"a", "b", "|a|b||", "p", "q"};
419     LPCSTR ret4[] = {"a", "b", "|a|b||", "p", "q", "p"};
420     LPCSTR ret5[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q"};
421     LPCSTR ret6[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q"};
422     LPCSTR ret7[] = {"a", "b", "|a|b||", "p", "q", "p", "p", "q", "p", "", "q", "br", "c", "d"};
423     HWND hToolbar = NULL;
424     TBBUTTON button;
425     int ret;
426
427     rebuild_toolbar(&hToolbar);
428     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test1);
429     ok(ret == 0, "TB_ADDSTRINGA - unexpected return %d\n", ret);
430     CHECK_STRING_TABLE(2, ret1);
431     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)test2);
432     ok(ret == 2, "TB_ADDSTRINGA - unexpected return %d\n", ret);
433     CHECK_STRING_TABLE(3, ret2);
434
435     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD1);
436     ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
437     CHECK_STRING_TABLE(3, ret2);
438     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD2);
439     ok(ret == 3, "TB_ADDSTRINGA - unexpected return %d\n", ret);
440     CHECK_STRING_TABLE(5, ret3);
441     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD3);
442     ok(ret == 5, "TB_ADDSTRINGA - unexpected return %d\n", ret);
443     CHECK_STRING_TABLE(6, ret4);
444     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD4);
445     ok(ret == 6, "TB_ADDSTRINGA - unexpected return %d\n", ret);
446     CHECK_STRING_TABLE(8, ret5);
447     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD5);
448     ok(ret == 8, "TB_ADDSTRINGA - unexpected return %d\n", ret);
449     CHECK_STRING_TABLE(11, ret6);
450     ret = SendMessageA(hToolbar, TB_ADDSTRINGA, (WPARAM)GetModuleHandle(NULL), IDS_TBADD7);
451     ok(ret == 11, "TB_ADDSTRINGA - unexpected return %d\n", ret);
452     CHECK_STRING_TABLE(14, ret7);
453
454     ZeroMemory(&button, sizeof(button));
455     button.iString = (UINT_PTR)"Test";
456     SendMessageA(hToolbar, TB_INSERTBUTTONA, 0, (LPARAM)&button);
457     CHECK_STRING_TABLE(14, ret7);
458     SendMessageA(hToolbar, TB_ADDBUTTONSA, 1, (LPARAM)&button);
459     CHECK_STRING_TABLE(14, ret7);
460
461     DestroyWindow(hToolbar);
462 }
463
464 static void expect_hot_notify(int idold, int idnew)
465 {
466     g_fExpectedHotItemOld = idold;
467     g_fExpectedHotItemNew = idnew;
468     g_fReceivedHotItemChange = FALSE;
469 }
470
471 #define check_hot_notify() \
472     ok(g_fReceivedHotItemChange, "TBN_HOTITEMCHANGE not received\n"); \
473     g_fExpectedHotItemOld = g_fExpectedHotItemNew = 0;
474
475 static void test_hotitem(void)
476 {
477     HWND hToolbar = NULL;
478     TBBUTTONINFO tbinfo;
479     LRESULT ret;
480
481     g_fBlockHotItemChange = FALSE;
482
483     rebuild_toolbar_with_buttons(&hToolbar);
484     /* set TBSTYLE_FLAT. comctl5 allows hot items only for such toolbars.
485      * comctl6 doesn't have this requirement even when theme == NULL */
486     SetWindowLong(hToolbar, GWL_STYLE, TBSTYLE_FLAT | GetWindowLong(hToolbar, GWL_STYLE));
487     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
488     ok(ret == -1, "Hot item: %ld, expected -1\n", ret);
489     ret = SendMessage(hToolbar, TB_SETHOTITEM, 1, 0);
490     ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
491     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
492     ok(ret == 1, "Hot item: %ld, expected 1\n", ret);
493     ret = SendMessage(hToolbar, TB_SETHOTITEM, 2, 0);
494     ok(ret == 1, "TB_SETHOTITEM returned %ld, expected 1\n", ret);
495
496     ret = SendMessage(hToolbar, TB_SETHOTITEM, 0xbeef, 0);
497     ok(ret == 2, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
498     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
499     ok(ret == 2, "Hot item: %lx, expected 2\n", ret);
500     ret = SendMessage(hToolbar, TB_SETHOTITEM, -0xbeef, 0);
501     ok(ret == 2, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
502     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
503     ok(ret == -1, "Hot item: %lx, expected -1\n", ret);
504
505     expect_hot_notify(0, 7);
506     ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
507     ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
508     check_hot_notify();
509     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
510     ok(ret == 3, "Hot item: %lx, expected 3\n", ret);
511     g_fBlockHotItemChange = TRUE;
512     ret = SendMessage(hToolbar, TB_SETHOTITEM, 2, 0);
513     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 2\n", ret);
514     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
515     ok(ret == 3, "Hot item: %lx, expected 3\n", ret);
516     g_fBlockHotItemChange = FALSE;
517
518     g_fReceivedHotItemChange = FALSE;
519     ret = SendMessage(hToolbar, TB_SETHOTITEM, 0xbeaf, 0);
520     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
521     ok(g_fReceivedHotItemChange == FALSE, "TBN_HOTITEMCHANGE received for invalid parameter\n");
522
523     g_fReceivedHotItemChange = FALSE;
524     ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
525     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
526     ok(g_fReceivedHotItemChange == FALSE, "TBN_HOTITEMCHANGE received after a duplication\n");
527
528     expect_hot_notify(7, 0);
529     ret = SendMessage(hToolbar, TB_SETHOTITEM, -0xbeaf, 0);
530     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
531     check_hot_notify();
532     SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
533
534     /* setting disabled buttons will generate a notify with the button id but no button will be hot */
535     expect_hot_notify(7, 9);
536     ret = SendMessage(hToolbar, TB_SETHOTITEM, 4, 0);
537     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
538     check_hot_notify();
539     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
540     ok(ret == -1, "Hot item: %lx, expected -1\n", ret);
541     /* enabling the button won't change that */
542     SendMessage(hToolbar, TB_ENABLEBUTTON, 9, TRUE);
543     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
544     ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
545
546     /* disabling a hot button works */
547     ret = SendMessage(hToolbar, TB_SETHOTITEM, 3, 0);
548     ok(ret == -1, "TB_SETHOTITEM returned %ld, expected -1\n", ret);
549     g_fReceivedHotItemChange = FALSE;
550     SendMessage(hToolbar, TB_ENABLEBUTTON, 7, FALSE);
551     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
552     ok(ret == 3, "TB_SETHOTITEM returned %ld, expected 3\n", ret);
553     ok(g_fReceivedHotItemChange == FALSE, "Unexpected TBN_HOTITEMCHANGE\n");
554
555     SendMessage(hToolbar, TB_SETHOTITEM, 1, 0);
556     tbinfo.cbSize = sizeof(TBBUTTONINFO);
557     tbinfo.dwMask = TBIF_STATE;
558     tbinfo.fsState = 0;  /* disabled */
559     g_fReceivedHotItemChange = FALSE;
560     ok(SendMessage(hToolbar, TB_SETBUTTONINFO, 1, (LPARAM)&tbinfo) == TRUE, "TB_SETBUTTONINFO failed\n");
561     ret = SendMessage(hToolbar, TB_GETHOTITEM, 0, 0);
562     ok(ret == 1, "TB_SETHOTITEM returned %ld, expected 1\n", ret);
563     ok(g_fReceivedHotItemChange == FALSE, "Unexpected TBN_HOTITEMCHANGE\n");
564
565     DestroyWindow(hToolbar);
566 }
567
568 #if 0  /* use this to generate more tests*/
569
570 static void dump_sizes(HWND hToolbar)
571 {
572     SIZE sz;
573     RECT r;
574     int count = SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0);
575     int i;
576
577     GetClientRect(hToolbar, &r);
578     SendMessageA(hToolbar, TB_GETMAXSIZE, 0, &sz);
579     printf("  { {%d, %d, %d, %d}, {%d, %d}, %d, {", r.left, r.top, r.right, r.bottom,
580         sz.cx, sz.cy, count);
581     for (i=0; i<count; i++)
582     {
583         SendMessageA(hToolbar, TB_GETITEMRECT, i, &r);
584         printf("%s{%3d, %3d, %3d, %3d}, ", (i%3==0 ? "\n    " : ""), r.left, r.top, r.right, r.bottom);
585     }
586     printf("\n  }, }, \n");
587 }
588
589 #define check_sizes() dump_sizes(hToolbar);
590 #define check_sizes_todo(todomask) dump_sizes(hToolbar);
591
592 #else
593
594 typedef struct
595 {
596     RECT rcClient;
597     SIZE szMin;
598     INT nButtons;
599     RECT rcButtons[100];
600 } tbsize_result_t;
601
602 static tbsize_result_t tbsize_results[] =
603 {
604   { {0, 0, 672, 26}, {100, 22}, 5, {
605     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
606     { 54,   2,  77,  24}, { 77,   2, 100,  24},
607   }, },
608   { {0, 0, 672, 26}, {146, 22}, 7, {
609     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
610     { 54,   2,  77,  24}, { 77,   2, 100,  24}, {100,   2, 123,  24},
611     {  0,  24,  23,  46},
612   }, },
613   { {0, 0, 672, 48}, {146, 22}, 7, {
614     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
615     { 54,   2,  77,  24}, { 77,   2, 100,  24}, {100,   2, 123,  24},
616     {  0,  24,  23,  46},
617   }, },
618   { {0, 0, 672, 26}, {146, 22}, 7, {
619     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
620     { 54,   2,  77,  24}, { 77,   2, 100,  24}, {100,   2, 123,  24},
621     {123,   2, 146,  24},
622   }, },
623   { {0, 0, 672, 26}, {192, 22}, 9, {
624     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
625     { 54,   2,  77,  24}, { 77,   2, 100,  24}, {100,   2, 123,  24},
626     {123,   2, 146,  24}, {146,   2, 169,  24}, {169,   2, 192,  24},
627   }, },
628   { {0, 0, 672, 92}, {882, 22}, 39, {
629     {  0,   2,  23,  24}, { 23,   2,  46,  24}, {  0,   2,   8,  29},
630     {  0,  29,  23,  51}, { 23,  29,  46,  51}, { 46,  29,  69,  51},
631     { 69,  29,  92,  51}, { 92,  29, 115,  51}, {115,  29, 138,  51},
632     {138,  29, 161,  51}, {161,  29, 184,  51}, {184,  29, 207,  51},
633     {207,  29, 230,  51}, {230,  29, 253,  51}, {253,  29, 276,  51},
634     {276,  29, 299,  51}, {299,  29, 322,  51}, {322,  29, 345,  51},
635     {345,  29, 368,  51}, {368,  29, 391,  51}, {391,  29, 414,  51},
636     {414,  29, 437,  51}, {437,  29, 460,  51}, {460,  29, 483,  51},
637     {483,  29, 506,  51}, {506,  29, 529,  51}, {529,  29, 552,  51},
638     {552,  29, 575,  51}, {575,  29, 598,  51}, {598,  29, 621,  51},
639     {621,  29, 644,  51}, {644,  29, 667,  51}, {  0,  51,  23,  73},
640     { 23,  51,  46,  73}, { 46,  51,  69,  73}, { 69,  51,  92,  73},
641     { 92,  51, 115,  73}, {115,  51, 138,  73}, {138,  51, 161,  73},
642   }, },
643   { {0, 0, 48, 226}, {23, 140}, 7, {
644     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  94,  24},
645     { 94,   2, 117,  24}, {117,   2, 140,  24}, {140,   2, 163,  24},
646     {  0,  24,  23,  46},
647   }, },
648   { {0, 0, 92, 226}, {23, 140}, 7, {
649     {  0,   2,  23,  24}, { 23,   2,  46,  24}, {  0,  24,  92,  32},
650     {  0,  32,  23,  54}, { 23,  32,  46,  54}, { 46,  32,  69,  54},
651     { 69,  32,  92,  54},
652   }, },
653   { {0, 0, 672, 26}, {194, 30}, 7, {
654     {  0,   2,  31,  32}, { 31,   2,  62,  32}, { 62,   2,  70,  32},
655     { 70,   2, 101,  32}, {101,   2, 132,  32}, {132,   2, 163,  32},
656     {  0,  32,  31,  62},
657   }, },
658   { {0, 0, 672, 64}, {194, 30}, 7, {
659     {  0,   2,  31,  32}, { 31,   2,  62,  32}, { 62,   2,  70,  32},
660     { 70,   2, 101,  32}, {101,   2, 132,  32}, {132,   2, 163,  32},
661     {  0,  32,  31,  62},
662   }, },
663   { {0, 0, 672, 64}, {194, 30}, 7, {
664     {  0,   0,  31,  30}, { 31,   0,  62,  30}, { 62,   0,  70,  30},
665     { 70,   0, 101,  30}, {101,   0, 132,  30}, {132,   0, 163,  30},
666     {  0,  30,  31,  60},
667   }, },
668   { {0, 0, 124, 226}, {31, 188}, 7, {
669     {  0,   0,  31,  30}, { 31,   0,  62,  30}, {  0,  30, 124,  38},
670     {  0,  38,  31,  68}, { 31,  38,  62,  68}, { 62,  38,  93,  68},
671     { 93,  38, 124,  68},
672   }, },
673   { {0, 0, 672, 26}, {146, 22}, 7, {
674     {  0,   2,  23,  24}, { 23,   2,  46,  24}, { 46,   2,  54,  24},
675     { 54,   2,  77,  24}, { 77,   2, 100,  24}, {100,   2, 123,  24},
676     {123,   2, 146,  24},
677   }, },
678   { {0, 0, 672, 26}, {146, 100}, 7, {
679     {  0,   0,  23, 100}, { 23,   0,  46, 100}, { 46,   0,  54, 100},
680     { 54,   0,  77, 100}, { 77,   0, 100, 100}, {100,   0, 123, 100},
681     {123,   0, 146, 100},
682   }, },
683   { {0, 0, 672, 26}, {215, 100}, 10, {
684     {  0,   0,  23, 100}, { 23,   0,  46, 100}, { 46,   0,  54, 100},
685     { 54,   0,  77, 100}, { 77,   0, 100, 100}, {100,   0, 123, 100},
686     {123,   0, 146, 100}, {146,   0, 169, 100}, {169,   0, 192, 100},
687     {192,   0, 215, 100},
688   }, },
689   { {0, 0, 672, 26}, {238, 39}, 11, {
690     {  0,   0,  23,  39}, { 23,   0,  46,  39}, { 46,   0,  54,  39},
691     { 54,   0,  77,  39}, { 77,   0, 100,  39}, {100,   0, 123,  39},
692     {123,   0, 146,  39}, {146,   0, 169,  39}, {169,   0, 192,  39},
693     {192,   0, 215,  39}, {215,   0, 238,  39},
694   }, },
695   { {0, 0, 672, 26}, {238, 22}, 11, {
696     {  0,   0,  23,  22}, { 23,   0,  46,  22}, { 46,   0,  54,  22},
697     { 54,   0,  77,  22}, { 77,   0, 100,  22}, {100,   0, 123,  22},
698     {123,   0, 146,  22}, {146,   0, 169,  22}, {169,   0, 192,  22},
699     {192,   0, 215,  22}, {215,   0, 238,  22},
700   }, },
701   { {0, 0, 672, 26}, {489, 39}, 3, {
702     {  0,   2, 163,  41}, {163,   2, 330,  41}, {330,   2, 493,  41},
703   }, },
704   { {0, 0, 672, 104}, {978, 24}, 6, {
705     {  0,   2, 163,  26}, {163,   2, 326,  26}, {326,   2, 489,  26},
706     {489,   2, 652,  26}, {652,   2, 819,  26}, {819,   2, 850,  26},
707   }, },
708   { {0, 0, 672, 28}, {978, 38}, 6, {
709     {  0,   0, 163,  38}, {163,   0, 326,  38}, {326,   0, 489,  38},
710     {489,   0, 652,  38}, {652,   0, 819,  38}, {819,   0, 850,  38},
711   }, },
712 };
713
714 static int tbsize_numtests = 0;
715
716 #define check_sizes_todo(todomask) { \
717         RECT rc; \
718         int buttonCount, i, mask=(todomask); \
719         tbsize_result_t *res = &tbsize_results[tbsize_numtests]; \
720         assert(tbsize_numtests < sizeof(tbsize_results)/sizeof(tbsize_results[0])); \
721         GetClientRect(hToolbar, &rc); \
722         /*check_rect("client", rc, res->rcClient);*/ \
723         buttonCount = SendMessage(hToolbar, TB_BUTTONCOUNT, 0, 0); \
724         compare(buttonCount, res->nButtons, "%d"); \
725         for (i=0; i<min(buttonCount, res->nButtons); i++) { \
726             ok(SendMessageA(hToolbar, TB_GETITEMRECT, i, (LPARAM)&rc) == 1, "TB_GETITEMRECT\n"); \
727             if (!(mask&1)) { \
728                 check_rect("button", rc, res->rcButtons[i]); \
729             } else {\
730                 todo_wine { check_rect("button", rc, res->rcButtons[i]); } \
731             } \
732             mask >>= 1; \
733         } \
734         tbsize_numtests++; \
735     }
736
737 #define check_sizes() check_sizes_todo(0)
738
739 #endif
740
741 static TBBUTTON buttons1[] = {
742     {0, 10, TBSTATE_WRAP|TBSTATE_ENABLED, 0, {0, }, 0, -1},
743     {0, 11, 0, 0, {0, }, 0, -1},
744 };
745 static TBBUTTON buttons2[] = {
746     {0, 20, TBSTATE_ENABLED, 0, {0, }, 0, -1},
747     {0, 21, TBSTATE_ENABLED, 0, {0, }, 0, -1},
748 };
749 static TBBUTTON buttons3[] = {
750     {0, 30, TBSTATE_ENABLED, 0, {0, }, 0, 0},
751     {0, 31, TBSTATE_ENABLED, 0, {0, }, 0, 1},
752     {0, 32, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, 1},
753     {0, 33, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0, }, 0, (UINT_PTR)"Tst"}
754 };
755
756 static void test_sizes(void)
757 {
758     HWND hToolbar = NULL;
759     HIMAGELIST himl;
760     int style;
761     int i;
762
763     rebuild_toolbar_with_buttons(&hToolbar);
764     style = GetWindowLong(hToolbar, GWL_STYLE);
765     ok(style == (WS_CHILD|WS_VISIBLE|CCS_TOP), "Invalid style %x\n", style);
766     check_sizes();
767     /* the TBSTATE_WRAP makes a second row */
768     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
769     check_sizes();
770     SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
771     check_sizes();
772     /* after setting the TBSTYLE_WRAPABLE the TBSTATE_WRAP is ignored */
773     SetWindowLong(hToolbar, GWL_STYLE, style|TBSTYLE_WRAPABLE);
774     check_sizes();
775     /* adding new buttons with TBSTYLE_WRAPABLE doesn't add a new row */
776     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
777     check_sizes();
778     /* only after adding enough buttons the bar will be wrapped on a
779      * separator and then on the first button */
780     for (i=0; i<15; i++)
781         SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
782     check_sizes_todo(0x4);
783
784     rebuild_toolbar_with_buttons(&hToolbar);
785     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
786     /* setting the buttons vertical will only change the window client size */
787     SetWindowLong(hToolbar, GWL_STYLE, style | CCS_VERT);
788     SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
789     check_sizes_todo(0x3c);
790     /* with a TBSTYLE_WRAPABLE a wrapping will occur on the separator */
791     SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_WRAPABLE | CCS_VERT);
792     SendMessage(hToolbar, TB_AUTOSIZE, 0, 0);
793     check_sizes_todo(0x7c);
794
795     rebuild_toolbar_with_buttons(&hToolbar);
796     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons1);
797     /* a TB_SETBITMAPSIZE changes button sizes*/
798     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24));
799     check_sizes();
800
801     /* setting a TBSTYLE_FLAT doesn't change anything - even after a TB_AUTOSIZE */
802     SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT);
803     SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0);
804     check_sizes();
805     /* but after a TB_SETBITMAPSIZE the top margins is changed */
806     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(20, 20));
807     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(24, 24));
808     check_sizes();
809     /* some vertical toolbar sizes */
810     SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | CCS_VERT);
811     check_sizes_todo(0x7c);
812
813     rebuild_toolbar_with_buttons(&hToolbar);
814     SetWindowLong(hToolbar, GWL_STYLE, style | TBSTYLE_FLAT);
815     /* newly added buttons will be use the previous margin */
816     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons2);
817     check_sizes();
818     /* TB_SETBUTTONSIZE can't be used to reduce the size of a button below the default */
819     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
820     ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(22, 21))==1, "TB_SETBUTTONSIZE\n");
821     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
822     ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(5, 100))==1, "TB_SETBUTTONSIZE\n");
823     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 100), "Unexpected button size\n");
824     ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3))==1, "TB_SETBUTTONSIZE\n");
825     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
826     ok(SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(5, 100))==1, "TB_SETBUTTONSIZE\n");
827     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 100), "Unexpected button size\n");
828     check_sizes();
829     /* add some buttons with non-default sizes */
830     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons2);
831     SendMessageA(hToolbar, TB_INSERTBUTTON, -1, (LPARAM)&buttons2[0]);
832     check_sizes();
833     SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[0]);
834     /* TB_ADDSTRING resets the size */
835     SendMessageA(hToolbar, TB_ADDSTRING, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
836     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 39), "Unexpected button size\n");
837     check_sizes();
838     /* TB_SETBUTTONSIZE can be used to crop the text */
839     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
840     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
841     check_sizes();
842     /* the default size is bitmap size + padding */
843     SendMessageA(hToolbar, TB_SETPADDING, 0, MAKELONG(1, 1));
844     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
845     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(17, 17), "Unexpected button size\n");
846     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(3, 3));
847     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(3, 3));
848     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(4, 4), "Unexpected button size\n");
849
850     rebuild_toolbar(&hToolbar);
851     /* sending a TB_SETBITMAPSIZE with the same sizes is enough to make the button smaller */
852     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
853     SendMessageA(hToolbar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 15));
854     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 21), "Unexpected button size\n");
855
856     rebuild_toolbar(&hToolbar);
857     SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
858     /* the height is increased after a TB_ADDSTRING */
859     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 39), "Unexpected button size\n");
860     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
861     /* if a string is in the pool, even adding a button without a string resets the size */
862     SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons2[0]);
863     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
864     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
865     /* an BTNS_AUTOSIZE button is also considered when computing the new size */
866     SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[2]);
867     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 39), "Unexpected button size\n");
868     SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[0]);
869     check_sizes();
870     /* delete button doesn't change the buttons size */
871     SendMessageA(hToolbar, TB_DELETEBUTTON, 2, 0);
872     SendMessageA(hToolbar, TB_DELETEBUTTON, 1, 0);
873     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 39), "Unexpected button size\n");
874     /* TB_INSERTBUTTONS will */
875     SendMessageA(hToolbar, TB_INSERTBUTTON, 1, (LPARAM)&buttons2[0]);
876     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
877
878     /* TB_HIDEBUTTON and TB_MOVEBUTTON doesn't force a recalc */
879     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
880     ok(SendMessageA(hToolbar, TB_MOVEBUTTON, 0, 1), "TB_MOVEBUTTON failed\n");
881     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
882     ok(SendMessageA(hToolbar, TB_HIDEBUTTON, 20, TRUE), "TB_HIDEBUTTON failed\n");
883     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
884     /* however changing the hidden flag with TB_SETSTATE does */
885     ok(SendMessageA(hToolbar, TB_SETSTATE, 20, TBSTATE_ENABLED|TBSTATE_HIDDEN), "TB_SETSTATE failed\n");
886     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
887     ok(SendMessageA(hToolbar, TB_SETSTATE, 20, TBSTATE_ENABLED), "TB_SETSTATE failed\n");
888     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(23, 22), "Unexpected button size\n");
889
890     /* TB_SETIMAGELIST always changes the height but the width only if necessary */
891     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
892     himl = ImageList_LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP_80x15), 20, 2, CLR_NONE, IMAGE_BITMAP, LR_DEFAULTCOLOR);
893     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
894     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 21), "Unexpected button size\n");
895     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(100, 100));
896     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(100, 100), "Unexpected button size\n");
897     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(1, 1));
898     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 21), "Unexpected button size\n");
899     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, 0) == (LRESULT)himl, "TB_SETIMAGELIST failed\n");
900     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 7), "Unexpected button size\n");
901     SendMessageA(hToolbar, TB_SETBUTTONSIZE, 0, MAKELONG(1, 1));
902     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(8, 7), "Unexpected button size\n");
903     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
904     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 21), "Unexpected button size\n");
905     /* the text is taken into account */
906     SendMessageA(hToolbar, TB_ADDSTRINGA, 0, (LPARAM)"A\0MMMMMMMMMMMMM\0");
907     SendMessageA(hToolbar, TB_ADDBUTTONS, 4, (LPARAM)buttons3);
908     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 38), "Unexpected button size\n");
909     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, 0) == (LRESULT)himl, "TB_SETIMAGELIST failed\n");
910     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(163, 24), "Unexpected button size\n");
911     /* the style change also comes into effect */
912     check_sizes();
913     SetWindowLong(hToolbar, GWL_STYLE, GetWindowLong(hToolbar, GWL_STYLE) | TBSTYLE_FLAT);
914     ok(SendMessageA(hToolbar, TB_SETIMAGELIST, 0, (LPARAM)himl) == 0, "TB_SETIMAGELIST failed\n");
915     check_sizes_todo(0x30);     /* some small problems with BTNS_AUTOSIZE button sizes */
916
917     rebuild_toolbar(&hToolbar);
918     ImageList_Destroy(himl);
919
920     SendMessageA(hToolbar, TB_ADDBUTTONS, 1, (LPARAM)&buttons3[3]);
921     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
922     SendMessageA(hToolbar, TB_DELETEBUTTON, 0, 0);
923     ok(SendMessageA(hToolbar, TB_GETBUTTONSIZE, 0, 0) == MAKELONG(27, 39), "Unexpected button size\n");
924
925     DestroyWindow(hToolbar);
926 }
927
928 static void test_getbuttoninfo(void)
929 {
930     HWND hToolbar = NULL;
931     int i;
932
933     rebuild_toolbar_with_buttons(&hToolbar);
934     for (i = 0; i < 128; i++)
935     {
936         TBBUTTONINFO tbi;
937         int ret;
938
939         tbi.cbSize = i;
940         tbi.dwMask = TBIF_BYINDEX | TBIF_COMMAND;
941         ret = (int)SendMessage(hToolbar, TB_GETBUTTONINFO, 0, (LPARAM)&tbi);
942         if (i == sizeof(TBBUTTONINFO)) {
943             compare(ret, 0, "%d");
944         } else {
945             compare(ret, -1, "%d");
946         }
947     }
948     DestroyWindow(hToolbar);
949 }
950
951 static void test_createtoolbarex(void)
952 {
953     HWND hToolbar;
954     TBBUTTON btns[3];
955     ZeroMemory(&btns, sizeof(btns));
956
957     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
958         3, 20, 20, 16, 16, sizeof(TBBUTTON));
959     CHECK_IMAGELIST(16, 20, 20);
960     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x1a001b, "%x");
961     DestroyWindow(hToolbar);
962
963     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
964         3, 4, 4, 16, 16, sizeof(TBBUTTON));
965     CHECK_IMAGELIST(32, 4, 4);
966     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xa000b, "%x");
967     DestroyWindow(hToolbar);
968
969     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
970         3, 0, 8, 12, 12, sizeof(TBBUTTON));
971     CHECK_IMAGELIST(16, 12, 12);
972     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x120013, "%x");
973     DestroyWindow(hToolbar);
974
975     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
976         3, -1, 8, 12, 12, sizeof(TBBUTTON));
977     CHECK_IMAGELIST(16, 12, 8);
978     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xe0013, "%x");
979     DestroyWindow(hToolbar);
980
981     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
982         3, -1, 8, -1, 12, sizeof(TBBUTTON));
983     CHECK_IMAGELIST(16, 16, 8);
984     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0xe0017, "%x");
985     DestroyWindow(hToolbar);
986
987     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
988         3, 0, 0, 12, -1, sizeof(TBBUTTON));
989     CHECK_IMAGELIST(16, 12, 16);
990     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x160013, "%x");
991     DestroyWindow(hToolbar);
992
993     hToolbar = CreateToolbarEx(hMainWnd, WS_VISIBLE, 1, 16, GetModuleHandle(NULL), IDB_BITMAP_128x15, btns,
994         3, 0, 0, 0, 12, sizeof(TBBUTTON));
995     CHECK_IMAGELIST(16, 16, 16);
996     compare((int)SendMessage(hToolbar, TB_GETBUTTONSIZE, 0, 0), 0x160017, "%x");
997     DestroyWindow(hToolbar);
998 }
999
1000 static void test_dispinfo(void)
1001 {
1002     HWND hToolbar = NULL;
1003     const TBBUTTON buttons_disp[] = {
1004         {-1, 20, TBSTATE_ENABLED, 0, {0, }, 0, -1},
1005         {0,  21, TBSTATE_ENABLED, 0, {0, }, 0, -1},
1006     };
1007     BOOL ret;
1008
1009     rebuild_toolbar(&hToolbar);
1010     SendMessageA(hToolbar, TB_LOADIMAGES, IDB_HIST_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
1011     SendMessageA(hToolbar, TB_ADDBUTTONS, 2, (LPARAM)buttons_disp);
1012     g_dwExpectedDispInfoMask = 1;
1013     /* Some TBN_GETDISPINFO tests will be done in MyWnd_Notify function.
1014      * We will receive TBN_GETDISPINFOW even if the control is ANSI */
1015     compare((BOOL)SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 0, "%d");
1016     ShowWindow(hToolbar, SW_SHOW);
1017     UpdateWindow(hToolbar);
1018
1019     ret = (BOOL)SendMessageA(hToolbar, CCM_SETUNICODEFORMAT, TRUE, 0);
1020     compare(ret, FALSE, "%d");
1021     compare(SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 1L, "%ld");
1022     InvalidateRect(hToolbar, NULL, FALSE);
1023     UpdateWindow(hToolbar);
1024
1025     ret = (BOOL)SendMessageA(hToolbar, CCM_SETUNICODEFORMAT, FALSE, 0);
1026     compare(ret, TRUE, "%d");
1027     compare(SendMessageA(hToolbar, CCM_GETUNICODEFORMAT, 0, 0), 0L, "%ld");
1028     InvalidateRect(hToolbar, NULL, FALSE);
1029     UpdateWindow(hToolbar);
1030
1031     DestroyWindow(hToolbar);
1032     g_dwExpectedDispInfoMask = 0;
1033 }
1034
1035 typedef struct
1036 {
1037     int  nRows;
1038     BOOL bLarger;
1039     int  expectedRows;
1040 } tbrows_result_t;
1041
1042 static tbrows_result_t tbrows_results[] =
1043 {
1044     {1, TRUE,  1}, /* 0: Simple case 9 in a row */
1045     {2, TRUE,  2}, /* 1: Another simple case 5 on one row, 4 on another*/
1046     {3, FALSE, 3}, /* 2: 3 lines - should be 3 lines of 3 buttons */
1047     {8, FALSE, 5}, /* 3: 8 lines - should be 5 lines of 2 buttons */
1048     {8, TRUE,  9}, /* 4: 8 lines but grow - should be 9 lines */
1049     {1, TRUE,  1}  /* 5: Back to simple case */
1050 };
1051
1052 static void test_setrows(void)
1053 {
1054     TBBUTTON buttons[9];
1055     HWND hToolbar;
1056     int i;
1057
1058     for (i=0; i<9; i++)
1059         MakeButton(buttons+i, 1000+i, TBSTYLE_FLAT | TBSTYLE_CHECKGROUP, 0);
1060
1061     /* Test 1 - 9 buttons */
1062     hToolbar = CreateToolbarEx(hMainWnd,
1063         WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD | CCS_NORESIZE | CCS_NOPARENTALIGN
1064         | CCS_NOMOVEY | CCS_TOP,
1065         0,
1066         0, NULL, (UINT)0,
1067         buttons, sizeof(buttons)/sizeof(buttons[0]),
1068         20, 20, 0, 0, sizeof(TBBUTTON));
1069     ok(hToolbar != NULL, "Toolbar creation\n");
1070     ok(SendMessageA(hToolbar, TB_AUTOSIZE, 0, 0) == 0, "TB_AUTOSIZE failed\n");
1071
1072     /* test setting rows to each of 1-10 with bLarger true and false */
1073     for (i=0; i<(sizeof(tbrows_results) / sizeof(tbrows_result_t)); i++) {
1074         RECT rc;
1075         int rows;
1076
1077         memset(&rc, 0xCC, sizeof(rc));
1078         SendMessageA(hToolbar, TB_SETROWS,
1079                      MAKELONG(tbrows_results[i].nRows, tbrows_results[i].bLarger),
1080                      (LONG) &rc);
1081
1082         rows = SendMessageA(hToolbar, TB_GETROWS, MAKELONG(0,0), MAKELONG(0,0));
1083         ok(rows == tbrows_results[i].expectedRows,
1084                    "[%d] Unexpected number of rows %d (expected %d)\n", i, rows,
1085                    tbrows_results[i].expectedRows);
1086     }
1087
1088     DestroyWindow(hToolbar);
1089 }
1090
1091 START_TEST(toolbar)
1092 {
1093     WNDCLASSA wc;
1094     MSG msg;
1095     RECT rc;
1096   
1097     InitCommonControls();
1098   
1099     wc.style = CS_HREDRAW | CS_VREDRAW;
1100     wc.cbClsExtra = 0;
1101     wc.cbWndExtra = 0;
1102     wc.hInstance = GetModuleHandleA(NULL);
1103     wc.hIcon = NULL;
1104     wc.hCursor = LoadCursorA(NULL, IDC_IBEAM);
1105     wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
1106     wc.lpszMenuName = NULL;
1107     wc.lpszClassName = "MyTestWnd";
1108     wc.lpfnWndProc = MyWndProc;
1109     RegisterClassA(&wc);
1110     
1111     hMainWnd = CreateWindowExA(0, "MyTestWnd", "Blah", WS_OVERLAPPEDWINDOW, 
1112       CW_USEDEFAULT, CW_USEDEFAULT, 680, 260, NULL, NULL, GetModuleHandleA(NULL), 0);
1113     GetClientRect(hMainWnd, &rc);
1114     ShowWindow(hMainWnd, SW_SHOW);
1115
1116     basic_test();
1117     test_add_bitmap();
1118     test_add_string();
1119     test_hotitem();
1120     test_sizes();
1121     test_getbuttoninfo();
1122     test_createtoolbarex();
1123     test_dispinfo();
1124     test_setrows();
1125
1126     PostQuitMessage(0);
1127     while(GetMessageA(&msg,0,0,0)) {
1128         TranslateMessage(&msg);
1129         DispatchMessageA(&msg);
1130     }
1131     DestroyWindow(hMainWnd);
1132 }