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