comctl32: Listview should accept both unicode and ansi notifications.
[wine] / dlls / comctl32 / tests / tab.c
1 /* Unit test suite for tab control.
2  *
3  * Copyright 2003 Vitaliy Margolen
4  * Copyright 2007 Hagop Hagopian
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 <windows.h>
23 #include <commctrl.h>
24 #include <stdio.h>
25
26 #include "wine/test.h"
27 #include "msg.h"
28
29 #define DEFAULT_MIN_TAB_WIDTH 54
30 #define TAB_PADDING_X 6
31 #define EXTRA_ICON_PADDING 3
32 #define MAX_TABLEN 32
33
34 #define NUM_MSG_SEQUENCES  2
35 #define PARENT_SEQ_INDEX   0
36 #define TAB_SEQ_INDEX      1
37
38 #define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
39 #define expect_str(expected, got)\
40  ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
41
42 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
43
44 #define TabCheckSetSize(hwnd, SetWidth, SetHeight, ExpWidth, ExpHeight, Msg)\
45     SendMessage (hwnd, TCM_SETITEMSIZE, 0,\
46         (LPARAM) MAKELPARAM((SetWidth >= 0) ? SetWidth:0, (SetHeight >= 0) ? SetHeight:0));\
47     if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW);\
48     CheckSize(hwnd, ExpWidth, ExpHeight, Msg);
49
50 #define CheckSize(hwnd,width,height,msg)\
51     SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab);\
52     if ((width  >= 0) && (height < 0))\
53         ok (width  == rTab.right  - rTab.left, "%s: Expected width [%d] got [%d]\n",\
54         msg, (int)width,  rTab.right  - rTab.left);\
55     else if ((height >= 0) && (width  < 0))\
56         ok (height == rTab.bottom - rTab.top,  "%s: Expected height [%d] got [%d]\n",\
57         msg, (int)height, rTab.bottom - rTab.top);\
58     else\
59         ok ((width  == rTab.right  - rTab.left) &&\
60             (height == rTab.bottom - rTab.top ),\
61             "%s: Expected [%d,%d] got [%d,%d]\n", msg, (int)width, (int)height,\
62             rTab.right - rTab.left, rTab.bottom - rTab.top);
63
64 static HFONT hFont = 0;
65
66 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
67
68 static const struct message create_parent_wnd_seq[] = {
69     { WM_GETMINMAXINFO, sent },
70     { WM_NCCREATE, sent },
71     { WM_NCCALCSIZE, sent|wparam, 0 },
72     { WM_CREATE, sent },
73     { WM_SHOWWINDOW, sent|wparam, 1 },
74     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
75     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76     { WM_ACTIVATEAPP, sent|wparam, 1 },
77     { WM_NCACTIVATE, sent|wparam, 1 },
78     { WM_ACTIVATE, sent|wparam, 1 },
79     { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
80     { WM_IME_NOTIFY, sent|defwinproc|optional },
81     { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
82     /* Win9x adds SWP_NOZORDER below */
83     { WM_WINDOWPOSCHANGED, sent},
84     { WM_NCCALCSIZE, sent|wparam|optional, 1 },
85     { WM_SIZE, sent },
86     { WM_MOVE, sent },
87     { 0 }
88 };
89
90 static const struct message add_tab_to_parent[] = {
91     { TCM_INSERTITEMA, sent },
92     { TCM_INSERTITEMA, sent|optional },
93     { WM_NOTIFYFORMAT, sent|defwinproc },
94     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 },
95     { WM_PARENTNOTIFY, sent|defwinproc },
96     { TCM_INSERTITEMA, sent },
97     { TCM_INSERTITEMA, sent },
98     { TCM_INSERTITEMA, sent },
99     { TCM_INSERTITEMA, sent|optional },
100     { 0 }
101 };
102
103 static const struct message add_tab_to_parent_interactive[] = {
104     { TCM_INSERTITEMA, sent },
105     { TCM_INSERTITEMA, sent },
106     { WM_NOTIFYFORMAT, sent|defwinproc },
107     { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
108     { WM_PARENTNOTIFY, sent|defwinproc },
109     { TCM_INSERTITEMA, sent },
110     { TCM_INSERTITEMA, sent },
111     { TCM_INSERTITEMA, sent },
112     { WM_SHOWWINDOW, sent},
113     { WM_WINDOWPOSCHANGING, sent},
114     { WM_WINDOWPOSCHANGING, sent},
115     { WM_NCACTIVATE, sent},
116     { WM_ACTIVATE, sent},
117     { WM_IME_SETCONTEXT, sent|defwinproc|optional},
118     { WM_IME_NOTIFY, sent|defwinproc|optional},
119     { WM_SETFOCUS, sent|defwinproc},
120     { WM_WINDOWPOSCHANGED, sent},
121     { WM_SIZE, sent},
122     { WM_MOVE, sent},
123     { 0 }
124 };
125
126 static const struct message add_tab_control_parent_seq[] = {
127     { WM_NOTIFYFORMAT, sent },
128     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
129     { 0 }
130 };
131
132 static const struct message add_tab_control_parent_seq_interactive[] = {
133     { WM_NOTIFYFORMAT, sent },
134     { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
135     { WM_WINDOWPOSCHANGING, sent|optional},
136     { WM_NCACTIVATE, sent},
137     { WM_ACTIVATE, sent},
138     { WM_WINDOWPOSCHANGING, sent|optional},
139     { WM_KILLFOCUS, sent},
140     { WM_IME_SETCONTEXT, sent|optional},
141     { WM_IME_NOTIFY, sent|optional},
142     { 0 }
143 };
144
145 static const struct message empty_sequence[] = {
146     { 0 }
147 };
148
149 static const struct message set_min_tab_width_seq[] = {
150     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
151     { TCM_SETMINTABWIDTH, sent|wparam, 0 },
152     { 0 }
153 };
154
155 static const struct message get_item_count_seq[] = {
156     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
157     { 0 }
158 };
159
160 static const struct message get_row_count_seq[] = {
161     { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
162     { 0 }
163 };
164
165 static const struct message get_item_rect_seq[] = {
166     { TCM_GETITEMRECT, sent },
167     { TCM_GETITEMRECT, sent },
168     { 0 }
169 };
170
171 static const struct message getset_cur_focus_seq[] = {
172     { TCM_SETCURFOCUS, sent|lparam, 0 },
173     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
174     { TCM_SETCURFOCUS, sent|lparam, 0 },
175     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
176     { TCM_SETCURSEL, sent|lparam, 0 },
177     { TCM_SETCURFOCUS, sent|lparam, 0 },
178     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
179     { 0 }
180 };
181
182 static const struct message getset_cur_sel_seq[] = {
183     { TCM_SETCURSEL, sent|lparam, 0 },
184     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
185     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
186     { TCM_SETCURSEL, sent|lparam, 0 },
187     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
188     { TCM_SETCURSEL, sent|lparam, 0 },
189     { TCM_SETCURSEL, sent|lparam, 0 },
190     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
191     { 0 }
192 };
193
194 static const struct message getset_extended_style_seq[] = {
195     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
196     { TCM_SETEXTENDEDSTYLE, sent },
197     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
198     { TCM_SETEXTENDEDSTYLE, sent },
199     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
200     { 0 }
201 };
202
203 static const struct message getset_unicode_format_seq[] = {
204     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
205     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
206     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
207     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
208     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
209     { 0 }
210 };
211
212 static const struct message getset_item_seq[] = {
213     { TCM_SETITEMA, sent },
214     { TCM_GETITEMA, sent },
215     { TCM_GETITEMA, sent },
216     { 0 }
217 };
218
219 static const struct message getset_tooltip_seq[] = {
220     { WM_NOTIFYFORMAT, sent|optional },
221     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
222     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
223     { WM_NOTIFYFORMAT, sent|optional },
224     { TCM_SETTOOLTIPS, sent|lparam, 0 },
225     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
226     { TCM_SETTOOLTIPS, sent|lparam, 0 },
227     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
228     { 0 }
229 };
230
231 static const struct message getset_tooltip_parent_seq[] = {
232     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
233     { 0 }
234 };
235
236 static const struct message insert_focus_seq[] = {
237     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
238     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
239     { TCM_INSERTITEM, sent|wparam, 1 },
240     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
241     { WM_QUERYUISTATE, sent|defwinproc|optional },
242     { WM_PARENTNOTIFY, sent|defwinproc|optional },
243     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
244     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
245     { TCM_INSERTITEM, sent|wparam, 2 },
246     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
247     { WM_QUERYUISTATE, sent|defwinproc|optional, },
248     { WM_PARENTNOTIFY, sent|defwinproc|optional },
249     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
250     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
251     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
252     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
253     { TCM_INSERTITEM, sent|wparam, 3 },
254     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
255     { 0 }
256 };
257
258 static const struct message delete_focus_seq[] = {
259     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
260     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
261     { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
262     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
263     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
264     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
265     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
266     { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
267     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
268     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
269     { 0 }
270 };
271
272
273 static HWND
274 create_tabcontrol (DWORD style, DWORD mask)
275 {
276     HWND handle;
277     TCITEM tcNewTab;
278     static char text1[] = "Tab 1",
279     text2[] = "Wide Tab 2",
280     text3[] = "T 3";
281
282     handle = CreateWindow (
283         WC_TABCONTROLA,
284         "TestTab",
285         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
286         10, 10, 300, 100,
287         NULL, NULL, NULL, 0);
288
289     assert (handle);
290
291     SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
292     SendMessage (handle, WM_SETFONT, 0, (LPARAM) hFont);
293
294     tcNewTab.mask = mask;
295     tcNewTab.pszText = text1;
296     tcNewTab.iImage = 0;
297     SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
298     tcNewTab.pszText = text2;
299     tcNewTab.iImage = 1;
300     SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
301     tcNewTab.pszText = text3;
302     tcNewTab.iImage = 2;
303     SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
304
305     if (winetest_interactive)
306     {
307         ShowWindow (handle, SW_SHOW);
308         RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
309         Sleep (1000);
310     }
311
312     return handle;
313 }
314
315 static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
316 {
317     static LONG defwndproc_counter = 0;
318     LRESULT ret;
319     struct message msg;
320
321     /* do not log painting messages */
322     if (message != WM_PAINT &&
323         message != WM_ERASEBKGND &&
324         message != WM_NCPAINT &&
325         message != WM_NCHITTEST &&
326         message != WM_GETTEXT &&
327         message != WM_GETICON &&
328         message != WM_DEVICECHANGE)
329     {
330         trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
331
332         msg.message = message;
333         msg.flags = sent|wparam|lparam;
334         if (defwndproc_counter) msg.flags |= defwinproc;
335         msg.wParam = wParam;
336         msg.lParam = lParam;
337         add_message(sequences, PARENT_SEQ_INDEX, &msg);
338     }
339
340     defwndproc_counter++;
341     ret = DefWindowProcA(hwnd, message, wParam, lParam);
342     defwndproc_counter--;
343
344     return ret;
345 }
346
347 static BOOL registerParentWindowClass(void)
348 {
349     WNDCLASSA cls;
350
351     cls.style = 0;
352     cls.lpfnWndProc = parentWindowProcess;
353     cls.cbClsExtra = 0;
354     cls.cbWndExtra = 0;
355     cls.hInstance = GetModuleHandleA(NULL);
356     cls.hIcon = 0;
357     cls.hCursor = LoadCursorA(0, IDC_ARROW);
358     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
359     cls.lpszMenuName = NULL;
360     cls.lpszClassName = "Tab test parent class";
361     return RegisterClassA(&cls);
362 }
363
364 static HWND createParentWindow(void)
365 {
366     if (!registerParentWindowClass())
367         return NULL;
368
369     return CreateWindowEx(0, "Tab test parent class",
370                           "Tab test parent window",
371                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
372                           WS_MAXIMIZEBOX | WS_VISIBLE,
373                           0, 0, 100, 100,
374                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
375 }
376
377 static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
378 {
379     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
380     static LONG defwndproc_counter = 0;
381     LRESULT ret;
382     struct message msg;
383
384     /* do not log painting messages */
385     if (message != WM_PAINT &&
386         message != WM_ERASEBKGND &&
387         message != WM_NCPAINT &&
388         message != WM_NCHITTEST &&
389         message != WM_GETTEXT &&
390         message != WM_GETICON &&
391         message != WM_DEVICECHANGE)
392     {
393         trace("tab: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
394
395         msg.message = message;
396         msg.flags = sent|wparam|lparam;
397         if (defwndproc_counter) msg.flags |= defwinproc;
398         msg.wParam = wParam;
399         msg.lParam = lParam;
400         add_message(sequences, TAB_SEQ_INDEX, &msg);
401     }
402
403     defwndproc_counter++;
404     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
405     defwndproc_counter--;
406
407     return ret;
408 }
409
410 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
411 {
412     HWND tabHandle;
413     TCITEM tcNewTab;
414     WNDPROC oldproc;
415     RECT rect;
416     INT i;
417
418     GetClientRect(parent_wnd, &rect);
419
420     tabHandle = CreateWindow (
421         WC_TABCONTROLA,
422         "TestTab",
423         WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
424         0, 0, rect.right, rect.bottom,
425         parent_wnd, NULL, NULL, 0);
426
427     assert(tabHandle);
428
429     oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
430     SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
431
432     tcNewTab.mask = mask;
433
434     for (i = 0; i < nTabs; i++)
435     {
436         char tabName[MAX_TABLEN];
437
438         sprintf(tabName, "Tab %d", i+1);
439         tcNewTab.pszText = tabName;
440         tcNewTab.iImage = i;
441         SendMessage (tabHandle, TCM_INSERTITEM, i, (LPARAM) &tcNewTab);
442     }
443
444     if (winetest_interactive)
445     {
446         ShowWindow (tabHandle, SW_SHOW);
447         RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
448         Sleep (1000);
449     }
450
451     return tabHandle;
452 }
453
454 static HWND create_tooltip (HWND hTab, char toolTipText[])
455 {
456     HWND hwndTT;
457
458     TOOLINFO ti;
459     LPTSTR lptstr = toolTipText;
460     RECT rect;
461
462     /* Creating a tooltip window*/
463     hwndTT = CreateWindowEx(
464         WS_EX_TOPMOST,
465         TOOLTIPS_CLASS,
466         NULL,
467         WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
468         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
469         hTab, NULL, 0, NULL);
470
471     SetWindowPos(
472         hwndTT,
473         HWND_TOPMOST,
474         0, 0, 0, 0,
475         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
476
477     GetClientRect (hTab, &rect);
478
479     /* Initialize members of toolinfo*/
480     ti.cbSize = sizeof(TOOLINFO);
481     ti.uFlags = TTF_SUBCLASS;
482     ti.hwnd = hTab;
483     ti.hinst = 0;
484     ti.uId = 0;
485     ti.lpszText = lptstr;
486
487     ti.rect = rect;
488
489     /* Add toolinfo structure to the tooltip control */
490     SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
491
492     return hwndTT;
493 }
494
495 static void test_tab(INT nMinTabWidth)
496 {
497     HWND hwTab;
498     RECT rTab;
499     HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
500     SIZE size;
501     HDC hdc;
502     HFONT hOldFont;
503     INT i, dpi, exp;
504
505     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
506     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
507     /* Get System default MinTabWidth */
508     if (nMinTabWidth < 0)
509         nMinTabWidth = SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
510
511     hdc = GetDC(hwTab);
512     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
513     hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
514     GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
515     trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
516     SelectObject(hdc, hOldFont);
517     ReleaseDC(hwTab, hdc);
518
519     trace ("  TCS_FIXEDWIDTH tabs no icon...\n");
520     CheckSize(hwTab, dpi, -1, "default width");
521     TabCheckSetSize(hwTab, 50, 20, 50, 20, "set size");
522     TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
523
524     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
525
526     trace ("  TCS_FIXEDWIDTH tabs with icon...\n");
527     TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
528     TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
529     TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
530
531     DestroyWindow (hwTab);
532
533     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
534     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
535
536     hdc = GetDC(hwTab);
537     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
538     ReleaseDC(hwTab, hdc);
539     trace ("  TCS_FIXEDWIDTH buttons no icon...\n");
540     CheckSize(hwTab, dpi, -1, "default width");
541     TabCheckSetSize(hwTab, 20, 20, 20, 20, "set size 1");
542     TabCheckSetSize(hwTab, 10, 50, 10, 50, "set size 2");
543     TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
544
545     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
546
547     trace ("  TCS_FIXEDWIDTH buttons with icon...\n");
548     TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
549     TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
550     TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
551     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
552     TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
553
554     DestroyWindow (hwTab);
555
556     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
557     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
558
559     hdc = GetDC(hwTab);
560     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
561     ReleaseDC(hwTab, hdc);
562     trace ("  TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
563     CheckSize(hwTab, dpi, -1, "no icon, default width");
564
565     TabCheckSetSize(hwTab, 20, 20, 20, 20, "no icon, set size 1");
566     TabCheckSetSize(hwTab, 10, 50, 10, 50, "no icon, set size 2");
567     TabCheckSetSize(hwTab, 0, 1, 0, 1, "no icon, min size");
568
569     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
570
571     TabCheckSetSize(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
572     TabCheckSetSize(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
573     TabCheckSetSize(hwTab, 0, 1, 25, 1, "with icon, min size");
574     SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
575     TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
576
577     DestroyWindow (hwTab);
578
579     hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
580     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
581
582     trace ("  non fixed width, with text...\n");
583     exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
584     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
585     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
586         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
587
588     for (i=0; i<8; i++)
589     {
590         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
591
592         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
593         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
594
595         TabCheckSetSize(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
596         TabCheckSetSize(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
597
598         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
599         nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
600
601         TabCheckSetSize(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
602         TabCheckSetSize(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
603         TabCheckSetSize(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
604     }
605     DestroyWindow (hwTab);
606
607     hwTab = create_tabcontrol(0, TCIF_IMAGE);
608     SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
609
610     trace ("  non fixed width, no text...\n");
611     exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
612     SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
613     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
614         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
615
616     for (i=0; i<8; i++)
617     {
618         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
619
620         SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
621         SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
622
623         TabCheckSetSize(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
624         TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
625
626         SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
627         if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
628             nTabWidth += EXTRA_ICON_PADDING *(i-1);
629
630         TabCheckSetSize(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
631         TabCheckSetSize(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
632         TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
633     }
634
635     DestroyWindow (hwTab);
636
637     ImageList_Destroy(himl);
638     DeleteObject(hFont);
639 }
640
641 static void test_curfocus(HWND parent_wnd, INT nTabs)
642 {
643     INT focusIndex;
644     HWND hTab;
645
646     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
647     ok(hTab != NULL, "Failed to create tab control\n");
648
649     flush_sequences(sequences, NUM_MSG_SEQUENCES);
650
651     /* Testing CurFocus with largest appropriate value */
652     SendMessage(hTab, TCM_SETCURFOCUS, nTabs-1, 0);
653     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
654     expect(nTabs-1, focusIndex);
655
656     /* Testing CurFocus with negative value */
657     SendMessage(hTab, TCM_SETCURFOCUS, -10, 0);
658     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
659     expect(-1, focusIndex);
660
661     /* Testing CurFocus with value larger than number of tabs */
662     focusIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
663     expect(-1, focusIndex);
664
665     SendMessage(hTab, TCM_SETCURFOCUS, nTabs+1, 0);
666     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
667     expect(1, focusIndex);
668
669     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE);
670
671     DestroyWindow(hTab);
672 }
673
674 static void test_cursel(HWND parent_wnd, INT nTabs)
675 {
676     INT selectionIndex;
677     INT focusIndex;
678     TCITEM tcItem;
679     HWND hTab;
680
681     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
682     ok(hTab != NULL, "Failed to create tab control\n");
683
684     flush_sequences(sequences, NUM_MSG_SEQUENCES);
685
686     /* Testing CurSel with largest appropriate value */
687     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
688     expect(0, selectionIndex);
689     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
690     expect(nTabs-1, selectionIndex);
691
692     /* Focus should switch with selection */
693     focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
694     expect(nTabs-1, focusIndex);
695
696     /* Testing CurSel with negative value */
697     SendMessage(hTab, TCM_SETCURSEL, -10, 0);
698     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
699     expect(-1, selectionIndex);
700
701     /* Testing CurSel with value larger than number of tabs */
702     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
703     expect(-1, selectionIndex);
704
705     selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs+1, 0);
706     expect(-1, selectionIndex);
707     selectionIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
708     expect(1, selectionIndex);
709
710     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
711     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
712
713     /* selected item should have TCIS_BUTTONPRESSED state
714        It doesn't depend on button state */
715     memset(&tcItem, 0, sizeof(TCITEM));
716     tcItem.mask = TCIF_STATE;
717     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
718     selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
719     SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
720     ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
721         "Selected item should have TCIS_BUTTONPRESSED\n");
722
723     DestroyWindow(hTab);
724 }
725
726 static void test_extendedstyle(HWND parent_wnd, INT nTabs)
727 {
728     DWORD prevExtendedStyle;
729     DWORD extendedStyle;
730     HWND hTab;
731
732     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
733     ok(hTab != NULL, "Failed to create tab control\n");
734
735     flush_sequences(sequences, NUM_MSG_SEQUENCES);
736
737     /* Testing Flat Separators */
738     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
739     prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
740     expect(extendedStyle, prevExtendedStyle);
741
742     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
743     expect(TCS_EX_FLATSEPARATORS, extendedStyle);
744
745     /* Testing Register Drop */
746     prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
747     expect(extendedStyle, prevExtendedStyle);
748
749     extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
750     todo_wine{
751         expect(TCS_EX_REGISTERDROP, extendedStyle);
752     }
753
754     ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
755     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
756
757     DestroyWindow(hTab);
758 }
759
760 static void test_unicodeformat(HWND parent_wnd, INT nTabs)
761 {
762     INT unicodeFormat;
763     HWND hTab;
764
765     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
766     ok(hTab != NULL, "Failed to create tab control\n");
767
768     flush_sequences(sequences, NUM_MSG_SEQUENCES);
769
770     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
771     todo_wine{
772         expect(0, unicodeFormat);
773     }
774     unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
775     expect(1, unicodeFormat);
776
777     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
778     expect(1, unicodeFormat);
779     unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
780     expect(0, unicodeFormat);
781
782     unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
783     expect(0, unicodeFormat);
784
785     ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
786     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
787
788     DestroyWindow(hTab);
789 }
790
791 static void test_getset_item(HWND parent_wnd, INT nTabs)
792 {
793     TCITEM tcItem;
794     DWORD ret;
795     char szText[32] = "New Label";
796     HWND hTab;
797
798     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
799     ok(hTab != NULL, "Failed to create tab control\n");
800
801     /* passing invalid index should result in initialization to zero
802        for members mentioned in mask requested */
803
804     /* valid range here is [0,4] */
805     memset(&tcItem, 0xcc, sizeof(tcItem));
806     tcItem.mask = TCIF_PARAM;
807     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
808     expect(FALSE, ret);
809     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
810
811     memset(&tcItem, 0xcc, sizeof(tcItem));
812     tcItem.mask = TCIF_IMAGE;
813     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
814     expect(FALSE, ret);
815     expect(0, tcItem.iImage);
816
817     memset(&tcItem, 0xcc, sizeof(tcItem));
818     tcItem.mask = TCIF_TEXT;
819     tcItem.pszText = szText;
820     szText[0] = 'a';
821     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
822     expect(FALSE, ret);
823     expect('a', szText[0]);
824
825     memset(&tcItem, 0xcc, sizeof(tcItem));
826     tcItem.mask = TCIF_STATE;
827     tcItem.dwStateMask = 0;
828     tcItem.dwState = TCIS_BUTTONPRESSED;
829     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
830     expect(FALSE, ret);
831     ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
832
833     memset(&tcItem, 0xcc, sizeof(tcItem));
834     tcItem.mask = TCIF_STATE;
835     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
836     tcItem.dwState = TCIS_BUTTONPRESSED;
837     ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
838     expect(FALSE, ret);
839     ok(tcItem.dwState == 0, "Expected zero dwState\n");
840
841     /* check with negative index to be sure */
842     memset(&tcItem, 0xcc, sizeof(tcItem));
843     tcItem.mask = TCIF_PARAM;
844     ret = SendMessage(hTab, TCM_GETITEM, -1, (LPARAM)&tcItem);
845     expect(FALSE, ret);
846     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
847
848     memset(&tcItem, 0xcc, sizeof(tcItem));
849     tcItem.mask = TCIF_PARAM;
850     ret = SendMessage(hTab, TCM_GETITEM, -2, (LPARAM)&tcItem);
851     expect(FALSE, ret);
852     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
853
854     flush_sequences(sequences, NUM_MSG_SEQUENCES);
855
856     tcItem.mask = TCIF_TEXT;
857     tcItem.pszText = &szText[0];
858     tcItem.cchTextMax = sizeof(szText);
859
860     strcpy(szText, "New Label");
861     ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
862     ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
863     expect_str("New Label", tcItem.pszText);
864
865     ok ( SendMessage(hTab, TCM_GETITEM, 1, (LPARAM) &tcItem), "Getting item failed.\n");
866     expect_str("Tab 2", tcItem.pszText);
867
868     ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
869     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
870
871     /* TCIS_BUTTONPRESSED doesn't depend on tab style */
872     memset(&tcItem, 0, sizeof(tcItem));
873     tcItem.mask = TCIF_STATE;
874     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
875     tcItem.dwState = TCIS_BUTTONPRESSED;
876     ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
877     tcItem.dwState = 0;
878     ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
879     if (tcItem.dwState)
880     {
881         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
882         /* next highlight item, test that dwStateMask actually masks */
883         tcItem.mask = TCIF_STATE;
884         tcItem.dwStateMask = TCIS_HIGHLIGHTED;
885         tcItem.dwState = TCIS_HIGHLIGHTED;
886         ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
887         tcItem.dwState = 0;
888         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
889         ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
890         tcItem.mask = TCIF_STATE;
891         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
892         tcItem.dwState = 0;
893         ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
894         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
895     }
896     else win_skip( "Item state mask not supported\n" );
897
898     DestroyWindow(hTab);
899 }
900
901 static void test_getset_tooltips(HWND parent_wnd, INT nTabs)
902 {
903     HWND hTab, toolTip;
904     char toolTipText[32] = "ToolTip Text Test";
905
906     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
907     ok(hTab != NULL, "Failed to create tab control\n");
908
909     flush_sequences(sequences, NUM_MSG_SEQUENCES);
910
911     toolTip = create_tooltip(hTab, toolTipText);
912     SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) toolTip, 0);
913     ok (toolTip == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
914
915     SendMessage(hTab, TCM_SETTOOLTIPS, 0, 0);
916     ok (NULL  == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
917
918     ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
919     ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
920
921     DestroyWindow(hTab);
922 }
923
924 static void test_misc(HWND parent_wnd, INT nTabs)
925 {
926     HWND hTab;
927     RECT rTab;
928     INT nTabsRetrieved;
929     INT rowCount;
930     INT dpi;
931     HDC hdc;
932
933     ok(parent_wnd != NULL, "no parent window!\n");
934     flush_sequences(sequences, NUM_MSG_SEQUENCES);
935
936     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
937     ok(hTab != NULL, "Failed to create tab control\n");
938
939     if(!winetest_interactive)
940         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent,
941                     "Tab sequence, after adding tab control to parent", TRUE);
942     else
943         ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive,
944                     "Tab sequence, after adding tab control to parent", TRUE);
945
946     if(!winetest_interactive)
947         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq,
948                     "Parent after sequence, adding tab control to parent", TRUE);
949     else
950         ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive,
951                     "Parent after sequence, adding tab control to parent", TRUE);
952
953     flush_sequences(sequences, NUM_MSG_SEQUENCES);
954     ok(SendMessage(hTab, TCM_SETMINTABWIDTH, 0, -1) > 0,"TCM_SETMINTABWIDTH returned < 0\n");
955     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE);
956
957     /* Testing GetItemCount */
958     flush_sequences(sequences, NUM_MSG_SEQUENCES);
959     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
960     expect(nTabs, nTabsRetrieved);
961     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE);
962     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE);
963
964     /* Testing GetRowCount */
965     flush_sequences(sequences, NUM_MSG_SEQUENCES);
966     rowCount = SendMessage(hTab, TCM_GETROWCOUNT, 0, 0);
967     expect(1, rowCount);
968     ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
969     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
970
971     /* Testing GetItemRect */
972     flush_sequences(sequences, NUM_MSG_SEQUENCES);
973     ok(SendMessage(hTab, TCM_GETITEMRECT, 0, (LPARAM) &rTab), "GetItemRect failed.\n");
974
975     hdc = GetDC(hTab);
976     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
977     ReleaseDC(hTab, hdc);
978     CheckSize(hTab, dpi, -1 , "Default Width");
979     ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE);
980     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE);
981
982     DestroyWindow(hTab);
983 }
984
985 static void test_adjustrect(HWND parent_wnd)
986 {
987     HWND hTab;
988     INT r;
989
990     ok(parent_wnd != NULL, "no parent window!\n");
991
992     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
993     ok(hTab != NULL, "Failed to create tab control\n");
994
995     r = SendMessage(hTab, TCM_ADJUSTRECT, FALSE, 0);
996     expect(-1, r);
997
998     r = SendMessage(hTab, TCM_ADJUSTRECT, TRUE, 0);
999     expect(-1, r);
1000 }
1001
1002 static void test_insert_focus(HWND parent_wnd)
1003 {
1004     HWND hTab;
1005     INT nTabsRetrieved;
1006     INT r;
1007     TCITEM tcNewTab;
1008     DWORD mask = TCIF_TEXT|TCIF_IMAGE;
1009     static char tabName[] = "TAB";
1010     tcNewTab.mask = mask;
1011     tcNewTab.pszText = tabName;
1012
1013     ok(parent_wnd != NULL, "no parent window!\n");
1014
1015     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
1016     ok(hTab != NULL, "Failed to create tab control\n");
1017
1018     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1019
1020     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1021     expect(0, nTabsRetrieved);
1022
1023     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1024     expect(-1, r);
1025
1026     tcNewTab.iImage = 1;
1027     r = SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
1028     expect(0, r);
1029
1030     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1031     expect(1, nTabsRetrieved);
1032
1033     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1034     expect(0, r);
1035
1036     tcNewTab.iImage = 2;
1037     r = SendMessage(hTab, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
1038     expect(1, r);
1039
1040     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1041     expect(2, nTabsRetrieved);
1042
1043     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1044     expect(0, r);
1045
1046     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1047     expect(0, r);
1048
1049     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1050     expect(-1, r);
1051
1052     tcNewTab.iImage = 3;
1053     r = SendMessage(hTab, TCM_INSERTITEM, 3, (LPARAM) &tcNewTab);
1054     expect(2, r);
1055
1056     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1057     expect(2, r);
1058
1059     ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
1060     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE);
1061
1062     DestroyWindow(hTab);
1063 }
1064
1065 static void test_delete_focus(HWND parent_wnd)
1066 {
1067     HWND hTab;
1068     INT nTabsRetrieved;
1069     INT r;
1070
1071     ok(parent_wnd != NULL, "no parent window!\n");
1072
1073     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1074     ok(hTab != NULL, "Failed to create tab control\n");
1075
1076     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1077
1078     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1079     expect(2, nTabsRetrieved);
1080
1081     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1082     expect(0, r);
1083
1084     r = SendMessage(hTab, TCM_DELETEITEM, 1, 0);
1085     expect(1, r);
1086
1087     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1088     expect(1, nTabsRetrieved);
1089
1090     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1091     expect(0, r);
1092
1093     r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1094     expect(0, r);
1095
1096     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1097     expect(-1, r);
1098
1099     r = SendMessage(hTab, TCM_DELETEITEM, 0, 0);
1100     expect(1, r);
1101
1102     nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1103     expect(0, nTabsRetrieved);
1104
1105     r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1106     expect(-1, r);
1107
1108     ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
1109     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE);
1110
1111     DestroyWindow(hTab);
1112 }
1113
1114 static void test_removeimage(HWND parent_wnd)
1115 {
1116     static const BYTE bits[32];
1117     HWND hwTab;
1118     INT i;
1119     TCITEM item;
1120     HICON hicon;
1121     HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR, 3, 4);
1122
1123     hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits);
1124     ImageList_AddIcon(himl, hicon);
1125     ImageList_AddIcon(himl, hicon);
1126     ImageList_AddIcon(himl, hicon);
1127
1128     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1129     SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1130
1131     memset(&item, 0, sizeof(TCITEM));
1132     item.mask = TCIF_IMAGE;
1133
1134     for(i = 0; i < 3; i++) {
1135         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1136         expect(i, item.iImage);
1137     }
1138
1139     /* remove image middle image */
1140     SendMessage(hwTab, TCM_REMOVEIMAGE, 1, 0);
1141     expect(2, ImageList_GetImageCount(himl));
1142     item.iImage = -1;
1143     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1144     expect(0, item.iImage);
1145     item.iImage = 0;
1146     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1147     expect(-1, item.iImage);
1148     item.iImage = 0;
1149     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1150     expect(1, item.iImage);
1151     /* remove first image */
1152     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1153     expect(1, ImageList_GetImageCount(himl));
1154     item.iImage = 0;
1155     SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1156     expect(-1, item.iImage);
1157     item.iImage = 0;
1158     SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1159     expect(-1, item.iImage);
1160     item.iImage = -1;
1161     SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1162     expect(0, item.iImage);
1163     /* remove the last one */
1164     SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1165     expect(0, ImageList_GetImageCount(himl));
1166     for(i = 0; i < 3; i++) {
1167         item.iImage = 0;
1168         SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1169         expect(-1, item.iImage);
1170     }
1171
1172     DestroyWindow(hwTab);
1173     ImageList_Destroy(himl);
1174     DestroyIcon(hicon);
1175 }
1176
1177 static void test_delete_selection(HWND parent_wnd)
1178 {
1179     HWND hTab;
1180     DWORD ret;
1181
1182     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1183     ok(hTab != NULL, "Failed to create tab control\n");
1184
1185     ret = SendMessage(hTab, TCM_SETCURSEL, 3, 0);
1186     expect(0, ret);
1187     ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1188     expect(3, ret);
1189     /* delete selected item - selection goes to -1 */
1190     ret = SendMessage(hTab, TCM_DELETEITEM, 3, 0);
1191     expect(TRUE, ret);
1192
1193     ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1194     expect(-1, ret);
1195
1196     DestroyWindow(hTab);
1197 }
1198
1199 START_TEST(tab)
1200 {
1201     HWND parent_wnd;
1202     LOGFONTA logfont;
1203
1204     lstrcpyA(logfont.lfFaceName, "Arial");
1205     memset(&logfont, 0, sizeof(logfont));
1206     logfont.lfHeight = -12;
1207     logfont.lfWeight = FW_NORMAL;
1208     logfont.lfCharSet = ANSI_CHARSET;
1209     hFont = CreateFontIndirectA(&logfont);
1210
1211     InitCommonControls();
1212
1213     trace ("Testing with default MinWidth\n");
1214     test_tab(-1);
1215     trace ("Testing with MinWidth set to -3\n");
1216     test_tab(-3);
1217     trace ("Testing with MinWidth set to 24\n");
1218     test_tab(24);
1219     trace ("Testing with MinWidth set to 54\n");
1220     test_tab(54);
1221     trace ("Testing with MinWidth set to 94\n");
1222     test_tab(94);
1223
1224     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1225
1226     parent_wnd = createParentWindow();
1227     ok(parent_wnd != NULL, "Failed to create parent window!\n");
1228
1229     test_curfocus(parent_wnd, 5);
1230     test_cursel(parent_wnd, 5);
1231     test_extendedstyle(parent_wnd, 5);
1232     test_unicodeformat(parent_wnd, 5);
1233     test_getset_item(parent_wnd, 5);
1234     test_getset_tooltips(parent_wnd, 5);
1235     test_misc(parent_wnd, 5);
1236
1237     test_adjustrect(parent_wnd);
1238
1239     test_insert_focus(parent_wnd);
1240     test_delete_focus(parent_wnd);
1241     test_delete_selection(parent_wnd);
1242     test_removeimage(parent_wnd);
1243
1244     DestroyWindow(parent_wnd);
1245 }