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