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 <windows.h>
22 #include <commctrl.h>
23 #include <stdio.h>
24 
25 #include "wine/test.h"
26 #include "msg.h"
27 
28 #define DEFAULT_MIN_TAB_WIDTH 54
29 #define TAB_PADDING_X 6
30 #define EXTRA_ICON_PADDING 3
31 #define MAX_TABLEN 32
32 
33 #define NUM_MSG_SEQUENCES  2
34 #define PARENT_SEQ_INDEX   0
35 #define TAB_SEQ_INDEX      1
36 
37 #define expect(expected, got) ok ( expected == got, "Expected %d, got %d\n", expected, got)
38 #define expect_str(expected, got)\
39  ok ( strcmp(expected, got) == 0, "Expected '%s', got '%s'\n", expected, got)
40 
41 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
42 
43 static HIMAGELIST (WINAPI *pImageList_Create)(INT,INT,UINT,INT,INT);
44 static BOOL (WINAPI *pImageList_Destroy)(HIMAGELIST);
45 static INT (WINAPI *pImageList_GetImageCount)(HIMAGELIST);
46 static INT (WINAPI *pImageList_ReplaceIcon)(HIMAGELIST,INT,HICON);
47 
CheckSize(HWND hwnd,INT width,INT height,const char * msg,int line)48 static void CheckSize(HWND hwnd, INT width, INT height, const char *msg, int line)
49 {
50     RECT r;
51 
52     SendMessageA(hwnd, TCM_GETITEMRECT, 0, (LPARAM)&r);
53     if (width >= 0 && height < 0)
54         ok_(__FILE__,line) (width == r.right - r.left, "%s: Expected width [%d] got [%d]\n",
55             msg, width, r.right - r.left);
56     else if (height >= 0 && width < 0)
57         ok_(__FILE__,line) (height == r.bottom - r.top,  "%s: Expected height [%d] got [%d]\n",
58             msg, height, r.bottom - r.top);
59     else
60         ok_(__FILE__,line) ((width  == r.right  - r.left) && (height == r.bottom - r.top ),
61 	    "%s: Expected [%d,%d] got [%d,%d]\n", msg, width, height,
62             r.right - r.left, r.bottom - r.top);
63 }
64 
65 #define CHECKSIZE(hwnd,width,height,msg) CheckSize(hwnd,width,height,msg,__LINE__)
66 
TabCheckSetSize(HWND hwnd,INT set_width,INT set_height,INT exp_width,INT exp_height,const char * msg,int line)67 static void TabCheckSetSize(HWND hwnd, INT set_width, INT set_height, INT exp_width,
68     INT exp_height, const char *msg, int line)
69 {
70     SendMessageA(hwnd, TCM_SETITEMSIZE, 0,
71             MAKELPARAM((set_width >= 0) ? set_width : 0, (set_height >= 0) ? set_height : 0));
72     if (winetest_interactive) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW);
73     CheckSize(hwnd, exp_width, exp_height, msg, line);
74 }
75 
76 #define TABCHECKSETSIZE(hwnd,set_width,set_height,exp_width,exp_height,msg) \
77     TabCheckSetSize(hwnd,set_width,set_height,exp_width,exp_height,msg,__LINE__)
78 
79 static HFONT hFont;
80 static DRAWITEMSTRUCT g_drawitem;
81 static HWND parent_wnd;
82 static LRESULT tcn_selchanging_result;
83 
84 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
85 
86 static const struct message empty_sequence[] = {
87     { 0 }
88 };
89 
90 static const struct message get_row_count_seq[] = {
91     { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
92     { 0 }
93 };
94 
95 static const struct message getset_cur_focus_seq[] = {
96     { TCM_SETCURFOCUS, sent|lparam, 0 },
97     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
98     { TCM_SETCURFOCUS, sent|lparam, 0 },
99     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
100     { TCM_SETCURSEL, sent|lparam, 0 },
101     { TCM_SETCURFOCUS, sent|lparam, 0 },
102     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
103     { 0 }
104 };
105 
106 static const struct message getset_cur_sel_seq[] = {
107     { TCM_SETCURSEL, sent|lparam, 0 },
108     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
109     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
110     { TCM_SETCURSEL, sent|lparam, 0 },
111     { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
112     { TCM_SETCURSEL, sent|lparam, 0 },
113     { TCM_SETCURSEL, sent|lparam, 0 },
114     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
115     { 0 }
116 };
117 
118 static const struct message getset_extended_style_seq[] = {
119     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
120     { TCM_SETEXTENDEDSTYLE, sent },
121     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
122     { TCM_SETEXTENDEDSTYLE, sent },
123     { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
124     { 0 }
125 };
126 
127 static const struct message getset_unicode_format_seq[] = {
128     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
129     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
130     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
131     { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
132     { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
133     { 0 }
134 };
135 
136 static const struct message getset_item_seq[] = {
137     { TCM_SETITEMA, sent },
138     { TCM_GETITEMA, sent },
139     { TCM_GETITEMA, sent },
140     { 0 }
141 };
142 
143 static const struct message getset_tooltip_seq[] = {
144     { WM_NOTIFYFORMAT, sent|optional },
145     { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
146     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
147     { WM_NOTIFYFORMAT, sent|optional },
148     { TCM_SETTOOLTIPS, sent|lparam, 0 },
149     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
150     { TCM_SETTOOLTIPS, sent|lparam, 0 },
151     { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
152     { 0 }
153 };
154 
155 static const struct message getset_tooltip_parent_seq[] = {
156     { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
157     { 0 }
158 };
159 
160 static const struct message insert_focus_seq[] = {
161     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
162     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
163     { TCM_INSERTITEMA, sent|wparam, 1 },
164     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
165     { WM_QUERYUISTATE, sent|defwinproc|optional },
166     { WM_PARENTNOTIFY, sent|defwinproc|optional },
167     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
168     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
169     { TCM_INSERTITEMA, sent|wparam, 2 },
170     { WM_NOTIFYFORMAT, sent|defwinproc|optional },
171     { WM_QUERYUISTATE, sent|defwinproc|optional, },
172     { WM_PARENTNOTIFY, sent|defwinproc|optional },
173     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
174     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
175     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
176     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
177     { TCM_INSERTITEMA, sent|wparam, 3 },
178     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
179     { 0 }
180 };
181 
182 static const struct message delete_focus_seq[] = {
183     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
184     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
185     { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
186     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
187     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
188     { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
189     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
190     { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
191     { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
192     { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
193     { 0 }
194 };
195 
196 static const struct message rbuttonup_seq[] = {
197     { WM_RBUTTONUP, sent|wparam|lparam, 0, 0 },
198     { WM_CONTEXTMENU, sent|defwinproc },
199     { 0 }
200 };
201 
202 static const struct message full_selchange_parent_seq[] = {
203     { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGING },
204     { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGE },
205     { 0 }
206 };
207 
208 static const struct message selchanging_parent_seq[] = {
209     { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGING },
210     { 0 }
211 };
212 
213 static const struct message selchange_parent_seq[] = {
214     { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGE },
215     { 0 }
216 };
217 
218 static const struct message setfocus_parent_seq[] = {
219     { WM_NOTIFY, sent|id, 0, 0, TCN_FOCUSCHANGE },
220     { 0 }
221 };
222 
223 static HWND
create_tabcontrol(DWORD style,DWORD mask)224 create_tabcontrol (DWORD style, DWORD mask)
225 {
226     HWND handle;
227     TCITEMA tcNewTab;
228     static char text1[] = "Tab 1",
229     text2[] = "Wide Tab 2",
230     text3[] = "T 3";
231 
232     handle = CreateWindowA(WC_TABCONTROLA, "TestTab",
233             WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, 10, 10, 300, 100, NULL,
234             NULL, NULL, 0);
235     ok(handle != NULL, "failed to create tab wnd\n");
236 
237     SetWindowLongA(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
238     SendMessageA(handle, WM_SETFONT, 0, (LPARAM)hFont);
239 
240     tcNewTab.mask = mask;
241     tcNewTab.pszText = text1;
242     tcNewTab.iImage = 0;
243     SendMessageA(handle, TCM_INSERTITEMA, 0, (LPARAM)&tcNewTab);
244     tcNewTab.pszText = text2;
245     tcNewTab.iImage = 1;
246     SendMessageA(handle, TCM_INSERTITEMA, 1, (LPARAM)&tcNewTab);
247     tcNewTab.pszText = text3;
248     tcNewTab.iImage = 2;
249     SendMessageA(handle, TCM_INSERTITEMA, 2, (LPARAM)&tcNewTab);
250 
251     if (winetest_interactive)
252     {
253         ShowWindow (handle, SW_SHOW);
254         RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
255         Sleep (1000);
256     }
257 
258     return handle;
259 }
260 
parent_wnd_proc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)261 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
262 {
263     static LONG defwndproc_counter = 0;
264     struct message msg = { 0 };
265     LRESULT ret;
266 
267     /* do not log painting messages */
268     if (message != WM_PAINT &&
269         message != WM_ERASEBKGND &&
270         message != WM_NCPAINT &&
271         message != WM_NCHITTEST &&
272         message != WM_GETTEXT &&
273         message != WM_GETICON &&
274         message != WM_DEVICECHANGE)
275     {
276         msg.message = message;
277         msg.flags = sent|wparam|lparam;
278         if (defwndproc_counter) msg.flags |= defwinproc;
279         msg.wParam = wParam;
280         msg.lParam = lParam;
281         if (message == WM_NOTIFY && lParam)
282             msg.id = ((NMHDR*)lParam)->code;
283         add_message(sequences, PARENT_SEQ_INDEX, &msg);
284     }
285 
286     /* dump sent structure data */
287     if (message == WM_DRAWITEM)
288         g_drawitem = *(DRAWITEMSTRUCT*)lParam;
289 
290     if (message == WM_NOTIFY)
291     {
292         NMHDR *nmhdr = (NMHDR *)lParam;
293         if (nmhdr && nmhdr->code == TCN_SELCHANGING)
294             return tcn_selchanging_result;
295     }
296 
297     defwndproc_counter++;
298     ret = DefWindowProcA(hwnd, message, wParam, lParam);
299     defwndproc_counter--;
300 
301     return ret;
302 }
303 
registerParentWindowClass(void)304 static BOOL registerParentWindowClass(void)
305 {
306     WNDCLASSA cls;
307 
308     cls.style = 0;
309     cls.lpfnWndProc = parent_wnd_proc;
310     cls.cbClsExtra = 0;
311     cls.cbWndExtra = 0;
312     cls.hInstance = GetModuleHandleA(NULL);
313     cls.hIcon = 0;
314     cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
315     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
316     cls.lpszMenuName = NULL;
317     cls.lpszClassName = "Tab test parent class";
318     return RegisterClassA(&cls);
319 }
320 
createParentWindow(void)321 static HWND createParentWindow(void)
322 {
323     if (!registerParentWindowClass())
324         return NULL;
325 
326     return CreateWindowExA(0, "Tab test parent class", "Tab test parent window",
327             WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE, 0, 0, 100, 100,
328             GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
329 }
330 
tab_subclass_proc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)331 static LRESULT WINAPI tab_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
332 {
333     WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
334     static LONG defwndproc_counter = 0;
335     struct message msg = { 0 };
336     LRESULT ret;
337 
338     /* do not log painting messages */
339     if (message != WM_PAINT &&
340         message != WM_ERASEBKGND &&
341         message != WM_NCPAINT &&
342         message != WM_NCHITTEST &&
343         message != WM_GETTEXT &&
344         message != WM_GETICON &&
345         message != WM_DEVICECHANGE)
346     {
347         msg.message = message;
348         msg.flags = sent|wparam|lparam;
349         if (defwndproc_counter) msg.flags |= defwinproc;
350         msg.wParam = wParam;
351         msg.lParam = lParam;
352         add_message(sequences, TAB_SEQ_INDEX, &msg);
353     }
354 
355     defwndproc_counter++;
356     ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
357     defwndproc_counter--;
358 
359     return ret;
360 }
361 
createFilledTabControl(HWND parent_wnd,DWORD style,DWORD mask,INT nTabs)362 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
363 {
364     HWND tabHandle;
365     TCITEMA tcNewTab;
366     WNDPROC oldproc;
367     RECT rect;
368     INT i;
369 
370     GetClientRect(parent_wnd, &rect);
371 
372     tabHandle = CreateWindowA(WC_TABCONTROLA, "TestTab",
373             WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, 0, 0, rect.right,
374             rect.bottom, parent_wnd, NULL, NULL, 0);
375     ok(tabHandle != NULL, "failed to create tab wnd\n");
376 
377     oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tab_subclass_proc);
378     SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
379 
380     tcNewTab.mask = mask;
381 
382     for (i = 0; i < nTabs; i++)
383     {
384         char tabName[MAX_TABLEN];
385 
386         sprintf(tabName, "Tab %d", i+1);
387         tcNewTab.pszText = tabName;
388         tcNewTab.iImage = i;
389         SendMessageA(tabHandle, TCM_INSERTITEMA, i, (LPARAM)&tcNewTab);
390     }
391 
392     if (winetest_interactive)
393     {
394         ShowWindow (tabHandle, SW_SHOW);
395         RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
396         Sleep (1000);
397     }
398 
399     return tabHandle;
400 }
401 
create_tooltip(HWND hTab,char toolTipText[])402 static HWND create_tooltip (HWND hTab, char toolTipText[])
403 {
404     HWND hwndTT;
405 
406     TTTOOLINFOA ti;
407     LPSTR lptstr = toolTipText;
408     RECT rect;
409 
410     /* Creating a tooltip window*/
411     hwndTT = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL,
412             WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
413             CW_USEDEFAULT, hTab, NULL, 0, NULL);
414 
415     SetWindowPos(
416         hwndTT,
417         HWND_TOPMOST,
418         0, 0, 0, 0,
419         SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
420 
421     GetClientRect (hTab, &rect);
422 
423     /* Initialize members of toolinfo*/
424     ti.cbSize = sizeof(TTTOOLINFOA);
425     ti.uFlags = TTF_SUBCLASS;
426     ti.hwnd = hTab;
427     ti.hinst = 0;
428     ti.uId = 0;
429     ti.lpszText = lptstr;
430 
431     ti.rect = rect;
432 
433     /* Add toolinfo structure to the tooltip control */
434     SendMessageA(hwndTT, TTM_ADDTOOLA, 0, (LPARAM)&ti);
435 
436     return hwndTT;
437 }
438 
test_tab(INT nMinTabWidth)439 static void test_tab(INT nMinTabWidth)
440 {
441     HWND hwTab;
442     RECT rTab;
443     HIMAGELIST himl = pImageList_Create(21, 21, ILC_COLOR, 3, 4);
444     SIZE size;
445     HDC hdc;
446     HFONT hOldFont;
447     INT i, dpi, exp;
448 
449     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
450     SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
451     /* Get System default MinTabWidth */
452     if (nMinTabWidth < 0)
453         nMinTabWidth = SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
454 
455     hdc = GetDC(hwTab);
456     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
457     hOldFont = SelectObject(hdc, (HFONT)SendMessageA(hwTab, WM_GETFONT, 0, 0));
458     GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
459     trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
460     SelectObject(hdc, hOldFont);
461     ReleaseDC(hwTab, hdc);
462 
463     trace ("  TCS_FIXEDWIDTH tabs no icon...\n");
464     CHECKSIZE(hwTab, dpi, -1, "default width");
465     TABCHECKSETSIZE(hwTab, 50, 20, 50, 20, "set size");
466     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size");
467 
468     SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
469 
470     trace ("  TCS_FIXEDWIDTH tabs with icon...\n");
471     TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "set size > icon");
472     TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "set size < icon");
473     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "min size");
474 
475     DestroyWindow (hwTab);
476 
477     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
478     SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
479 
480     hdc = GetDC(hwTab);
481     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
482     ReleaseDC(hwTab, hdc);
483     trace ("  TCS_FIXEDWIDTH buttons no icon...\n");
484     CHECKSIZE(hwTab, dpi, -1, "default width");
485     TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "set size 1");
486     TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "set size 2");
487     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "min size");
488 
489     SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
490 
491     trace ("  TCS_FIXEDWIDTH buttons with icon...\n");
492     TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "set size > icon");
493     TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "set size < icon");
494     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "min size");
495     SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4, 4));
496     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size");
497 
498     DestroyWindow (hwTab);
499 
500     hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
501     SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
502 
503     hdc = GetDC(hwTab);
504     dpi = GetDeviceCaps(hdc, LOGPIXELSX);
505     ReleaseDC(hwTab, hdc);
506     trace ("  TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
507     CHECKSIZE(hwTab, dpi, -1, "no icon, default width");
508 
509     TABCHECKSETSIZE(hwTab, 20, 20, 20, 20, "no icon, set size 1");
510     TABCHECKSETSIZE(hwTab, 10, 50, 10, 50, "no icon, set size 2");
511     TABCHECKSETSIZE(hwTab, 0, 1, 0, 1, "no icon, min size");
512 
513     SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
514 
515     TABCHECKSETSIZE(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
516     TABCHECKSETSIZE(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
517     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "with icon, min size");
518     SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4, 4));
519     TABCHECKSETSIZE(hwTab, 0, 1, 25, 1, "set padding, min size");
520 
521     DestroyWindow (hwTab);
522 
523     hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
524     SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
525 
526     trace ("  non fixed width, with text...\n");
527     exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
528     SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
529     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
530         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
531 
532     for (i=0; i<8; i++)
533     {
534         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
535 
536         SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0);
537         SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i));
538 
539         TABCHECKSETSIZE(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
540         TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
541 
542         SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
543         nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
544 
545         TABCHECKSETSIZE(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
546         TABCHECKSETSIZE(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
547         TABCHECKSETSIZE(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
548     }
549     DestroyWindow (hwTab);
550 
551     hwTab = create_tabcontrol(0, TCIF_IMAGE);
552     SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
553 
554     trace ("  non fixed width, no text...\n");
555     exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
556     SendMessageA( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
557     ok( rTab.right  - rTab.left == exp || broken(rTab.right  - rTab.left == DEFAULT_MIN_TAB_WIDTH),
558         "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
559 
560     for (i=0; i<8; i++)
561     {
562         INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
563 
564         SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0);
565         SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i));
566 
567         TABCHECKSETSIZE(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
568         TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
569 
570         SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
571         if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
572             nTabWidth += EXTRA_ICON_PADDING *(i-1);
573 
574         TABCHECKSETSIZE(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
575         TABCHECKSETSIZE(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
576         TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
577     }
578 
579     DestroyWindow (hwTab);
580 
581     pImageList_Destroy(himl);
582 }
583 
test_width(void)584 static void test_width(void)
585 {
586     trace ("Testing with default MinWidth\n");
587     test_tab(-1);
588     trace ("Testing with MinWidth set to -3\n");
589     test_tab(-3);
590     trace ("Testing with MinWidth set to 24\n");
591     test_tab(24);
592     trace ("Testing with MinWidth set to 54\n");
593     test_tab(54);
594     trace ("Testing with MinWidth set to 94\n");
595     test_tab(94);
596 }
597 
test_curfocus(void)598 static void test_curfocus(void)
599 {
600     const INT nTabs = 5;
601     INT ret;
602     HWND hTab;
603 
604     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
605     ok(hTab != NULL, "Failed to create tab control\n");
606 
607     flush_sequences(sequences, NUM_MSG_SEQUENCES);
608 
609     /* Testing CurFocus with largest appropriate value */
610     ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs - 1, 0);
611     ok(ret == 0, "Unexpected ret value %d.\n", ret);
612     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
613     ok(ret == nTabs - 1, "Unexpected focus index %d.\n", ret);
614 
615     /* Testing CurFocus with negative value */
616     ret = SendMessageA(hTab, TCM_SETCURFOCUS, -10, 0);
617     ok(ret == 0, "Unexpected ret value %d.\n", ret);
618     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
619     ok(ret == -1, "Unexpected focus index %d.\n", ret);
620 
621     /* Testing CurFocus with value larger than number of tabs */
622     ret = SendMessageA(hTab, TCM_SETCURSEL, 1, 0);
623     ok(ret == -1, "Unexpected focus index %d.\n", ret);
624 
625     ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs + 1, 0);
626     ok(ret == 0, "Unexpected ret value %d.\n", ret);
627     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
628     ok(ret == 1, "Unexpected focus index %d.\n", ret);
629 
630     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Set focused tab sequence", FALSE);
631     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set focused tab parent sequence", TRUE);
632 
633     DestroyWindow(hTab);
634 
635     /* TCS_BUTTONS */
636     hTab = createFilledTabControl(parent_wnd, TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE, nTabs);
637     ok(hTab != NULL, "Failed to create tab control\n");
638 
639     flush_sequences(sequences, NUM_MSG_SEQUENCES);
640 
641     /* Testing CurFocus with largest appropriate value */
642     ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs - 1, 0);
643     ok(ret == 0, "Unexpected ret value %d.\n", ret);
644     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
645     ok(ret == nTabs - 1, "Unexpected focus index %d.\n", ret);
646 
647     /* Testing CurFocus with negative value */
648     ret = SendMessageA(hTab, TCM_SETCURFOCUS, -10, 0);
649     ok(ret == 0, "Unexpected ret value %d.\n", ret);
650     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
651 todo_wine
652     ok(ret == nTabs - 1, "Unexpected focus index %d.\n", ret);
653 
654     /* Testing CurFocus with value larger than number of tabs */
655     ret = SendMessageA(hTab, TCM_SETCURSEL, 1, 0);
656 todo_wine
657     ok(ret == 0, "Unexpected focus index %d.\n", ret);
658 
659     ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs + 1, 0);
660     ok(ret == 0, "Unexpected ret value %d.\n", ret);
661     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
662 todo_wine
663     ok(ret == nTabs - 1, "Unexpected focus index %d.\n", ret);
664 
665     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "TCS_BUTTONS: set focused tab sequence", FALSE);
666     ok_sequence(sequences, PARENT_SEQ_INDEX, setfocus_parent_seq, "TCS_BUTTONS: set focused tab parent sequence", TRUE);
667 
668     DestroyWindow(hTab);
669 }
670 
test_cursel(void)671 static void test_cursel(void)
672 {
673     const INT nTabs = 5;
674     INT selectionIndex;
675     INT focusIndex;
676     TCITEMA tcItem;
677     HWND hTab;
678 
679     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
680     ok(hTab != NULL, "Failed to create tab control\n");
681 
682     flush_sequences(sequences, NUM_MSG_SEQUENCES);
683 
684     /* Testing CurSel with largest appropriate value */
685     selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, nTabs - 1, 0);
686     expect(0, selectionIndex);
687     selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
688     expect(nTabs-1, selectionIndex);
689 
690     /* Focus should switch with selection */
691     focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
692     expect(nTabs-1, focusIndex);
693 
694     /* Testing CurSel with negative value */
695     SendMessageA(hTab, TCM_SETCURSEL, -10, 0);
696     selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
697     expect(-1, selectionIndex);
698 
699     /* Testing CurSel with value larger than number of tabs */
700     selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, 1, 0);
701     expect(-1, selectionIndex);
702 
703     selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, nTabs + 1, 0);
704     expect(-1, selectionIndex);
705     selectionIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
706     expect(1, selectionIndex);
707 
708     ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
709     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
710 
711     /* selected item should have TCIS_BUTTONPRESSED state
712        It doesn't depend on button state */
713     memset(&tcItem, 0, sizeof(TCITEMA));
714     tcItem.mask = TCIF_STATE;
715     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
716     selectionIndex = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
717     SendMessageA(hTab, TCM_GETITEMA, selectionIndex, (LPARAM)&tcItem);
718     ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
719         "Selected item should have TCIS_BUTTONPRESSED\n");
720 
721     /* now deselect all and check previously selected item state */
722     focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
723     ok(focusIndex == 1, "got %d\n", focusIndex);
724 
725     selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, -1, 0);
726     ok(selectionIndex == 1, "got %d\n", selectionIndex);
727 
728     memset(&tcItem, 0, sizeof(TCITEMA));
729 
730     /* focus is reset too */
731     focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
732     ok(focusIndex == -1, "got %d\n", focusIndex);
733 
734     tcItem.mask = TCIF_STATE;
735     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
736     SendMessageA(hTab, TCM_GETITEMA, selectionIndex, (LPARAM)&tcItem);
737     ok(tcItem.dwState == 0, "got state %d\n", tcItem.dwState);
738 
739     DestroyWindow(hTab);
740 }
741 
test_extendedstyle(void)742 static void test_extendedstyle(void)
743 {
744     const INT nTabs = 5;
745     DWORD prevExtendedStyle;
746     DWORD extendedStyle;
747     HWND hTab;
748 
749     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
750     ok(hTab != NULL, "Failed to create tab control\n");
751 
752     flush_sequences(sequences, NUM_MSG_SEQUENCES);
753 
754     /* Testing Flat Separators */
755     extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
756     prevExtendedStyle = SendMessageA(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
757     expect(extendedStyle, prevExtendedStyle);
758 
759     extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
760     expect(TCS_EX_FLATSEPARATORS, extendedStyle);
761 
762     /* Testing Register Drop */
763     prevExtendedStyle = SendMessageA(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
764     expect(extendedStyle, prevExtendedStyle);
765 
766     extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
767     todo_wine{
768         expect(TCS_EX_REGISTERDROP, extendedStyle);
769     }
770 
771     ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
772     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
773 
774     DestroyWindow(hTab);
775 }
776 
test_unicodeformat(void)777 static void test_unicodeformat(void)
778 {
779     const INT nTabs = 5;
780     INT unicodeFormat;
781     HWND hTab;
782 
783     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
784     ok(hTab != NULL, "Failed to create tab control\n");
785 
786     flush_sequences(sequences, NUM_MSG_SEQUENCES);
787 
788     unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
789     todo_wine{
790         expect(0, unicodeFormat);
791     }
792     unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0);
793     expect(1, unicodeFormat);
794 
795     unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
796     expect(1, unicodeFormat);
797     unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0);
798     expect(0, unicodeFormat);
799 
800     unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
801     expect(0, unicodeFormat);
802 
803     ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
804     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
805 
806     DestroyWindow(hTab);
807 }
808 
test_getset_item(void)809 static void test_getset_item(void)
810 {
811     char szText[32] = "New Label";
812     const INT nTabs = 5;
813     TCITEMA tcItem;
814     LPARAM lparam;
815     DWORD ret;
816     HWND hTab;
817 
818     hTab = CreateWindowA(
819 	WC_TABCONTROLA,
820 	"TestTab",
821 	WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
822         10, 10, 300, 100,
823         parent_wnd, NULL, NULL, 0);
824 
825     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
826 
827     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
828     ok(ret == TRUE, "got %d\n", ret);
829 
830     /* set some item data */
831     tcItem.lParam = ~0;
832     tcItem.mask = TCIF_PARAM;
833 
834     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&tcItem);
835     ok(ret == 0, "got %d\n", ret);
836 
837     /* all sizeof(LPARAM) returned anyway when using sizeof(LPARAM)-1 size */
838     memset(&lparam, 0xaa, sizeof(lparam));
839     tcItem.lParam = lparam;
840     tcItem.mask = TCIF_PARAM;
841     ret = SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem);
842     expect(TRUE, ret);
843     /* everything higher specified size is preserved */
844     memset(&lparam, 0xff, sizeof(lparam)-1);
845     ok(tcItem.lParam == lparam, "Expected 0x%lx, got 0x%lx\n", lparam, tcItem.lParam);
846 
847     DestroyWindow(hTab);
848 
849     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
850     ok(hTab != NULL, "Failed to create tab control\n");
851 
852     /* passing invalid index should result in initialization to zero
853        for members mentioned in mask requested */
854 
855     /* valid range here is [0,4] */
856     memset(&tcItem, 0xcc, sizeof(tcItem));
857     tcItem.mask = TCIF_PARAM;
858     ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem);
859     expect(FALSE, ret);
860     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
861 
862     memset(&tcItem, 0xcc, sizeof(tcItem));
863     tcItem.mask = TCIF_IMAGE;
864     ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem);
865     expect(FALSE, ret);
866     expect(0, tcItem.iImage);
867 
868     memset(&tcItem, 0xcc, sizeof(tcItem));
869     tcItem.mask = TCIF_TEXT;
870     tcItem.pszText = szText;
871     szText[0] = 'a';
872     ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem);
873     expect(FALSE, ret);
874     expect('a', szText[0]);
875 
876     memset(&tcItem, 0xcc, sizeof(tcItem));
877     tcItem.mask = TCIF_STATE;
878     tcItem.dwStateMask = 0;
879     tcItem.dwState = TCIS_BUTTONPRESSED;
880     ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem);
881     expect(FALSE, ret);
882     ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
883 
884     memset(&tcItem, 0xcc, sizeof(tcItem));
885     tcItem.mask = TCIF_STATE;
886     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
887     tcItem.dwState = TCIS_BUTTONPRESSED;
888     ret = SendMessageA(hTab, TCM_GETITEMA, 5, (LPARAM)&tcItem);
889     expect(FALSE, ret);
890     ok(tcItem.dwState == 0, "Expected zero dwState\n");
891 
892     /* check with negative index to be sure */
893     memset(&tcItem, 0xcc, sizeof(tcItem));
894     tcItem.mask = TCIF_PARAM;
895     ret = SendMessageA(hTab, TCM_GETITEMA, -1, (LPARAM)&tcItem);
896     expect(FALSE, ret);
897     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
898 
899     memset(&tcItem, 0xcc, sizeof(tcItem));
900     tcItem.mask = TCIF_PARAM;
901     ret = SendMessageA(hTab, TCM_GETITEMA, -2, (LPARAM)&tcItem);
902     expect(FALSE, ret);
903     ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
904 
905     flush_sequences(sequences, NUM_MSG_SEQUENCES);
906 
907     tcItem.mask = TCIF_TEXT;
908     tcItem.pszText = &szText[0];
909     tcItem.cchTextMax = sizeof(szText);
910 
911     strcpy(szText, "New Label");
912     ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n");
913     ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n");
914     expect_str("New Label", tcItem.pszText);
915 
916     ok(SendMessageA(hTab, TCM_GETITEMA, 1, (LPARAM)&tcItem), "Getting item failed.\n");
917     expect_str("Tab 2", tcItem.pszText);
918 
919     ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
920     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
921 
922     /* TCIS_BUTTONPRESSED doesn't depend on tab style */
923     memset(&tcItem, 0, sizeof(tcItem));
924     tcItem.mask = TCIF_STATE;
925     tcItem.dwStateMask = TCIS_BUTTONPRESSED;
926     tcItem.dwState = TCIS_BUTTONPRESSED;
927     ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n");
928     tcItem.dwState = 0;
929     ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n");
930     if (tcItem.dwState)
931     {
932         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
933         /* next highlight item, test that dwStateMask actually masks */
934         tcItem.mask = TCIF_STATE;
935         tcItem.dwStateMask = TCIS_HIGHLIGHTED;
936         tcItem.dwState = TCIS_HIGHLIGHTED;
937         ok(SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&tcItem), "Setting new item failed.\n");
938         tcItem.dwState = 0;
939         ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n");
940         ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
941         tcItem.mask = TCIF_STATE;
942         tcItem.dwStateMask = TCIS_BUTTONPRESSED;
943         tcItem.dwState = 0;
944         ok(SendMessageA(hTab, TCM_GETITEMA, 0, (LPARAM)&tcItem), "Getting item failed.\n");
945         ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
946     }
947     else win_skip( "Item state mask not supported\n" );
948 
949     DestroyWindow(hTab);
950 }
951 
test_getset_tooltips(void)952 static void test_getset_tooltips(void)
953 {
954     char toolTipText[32] = "ToolTip Text Test";
955     HWND hTab, toolTip, hwnd;
956     const INT nTabs = 5;
957     int ret;
958 
959     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
960     ok(hTab != NULL, "Failed to create tab control\n");
961 
962     flush_sequences(sequences, NUM_MSG_SEQUENCES);
963 
964     toolTip = create_tooltip(hTab, toolTipText);
965     ret = SendMessageA(hTab, TCM_SETTOOLTIPS, (WPARAM)toolTip, 0);
966     ok(ret == 0, "Unexpected ret value %d.\n", ret);
967     hwnd = (HWND)SendMessageA(hTab, TCM_GETTOOLTIPS, 0, 0);
968     ok(toolTip == hwnd, "Unexpected tooltip window.\n");
969 
970     ret = SendMessageA(hTab, TCM_SETTOOLTIPS, 0, 0);
971     ok(ret == 0, "Unexpected ret value %d.\n", ret);
972     hwnd = (HWND)SendMessageA(hTab, TCM_GETTOOLTIPS, 0, 0);
973     ok(hwnd == NULL, "Unexpected tooltip window.\n");
974     ok(IsWindow(toolTip), "Expected tooltip window to be alive.\n");
975 
976     ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
977     ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
978 
979     DestroyWindow(hTab);
980     DestroyWindow(toolTip);
981 }
982 
test_adjustrect(void)983 static void test_adjustrect(void)
984 {
985     HWND hTab;
986     INT r;
987 
988     ok(parent_wnd != NULL, "no parent window!\n");
989 
990     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
991     ok(hTab != NULL, "Failed to create tab control\n");
992 
993     r = SendMessageA(hTab, TCM_ADJUSTRECT, FALSE, 0);
994     expect(-1, r);
995 
996     r = SendMessageA(hTab, TCM_ADJUSTRECT, TRUE, 0);
997     expect(-1, r);
998 }
999 
test_insert_focus(void)1000 static void test_insert_focus(void)
1001 {
1002     HWND hTab;
1003     INT nTabsRetrieved;
1004     INT r;
1005     TCITEMA tcNewTab;
1006     DWORD mask = TCIF_TEXT|TCIF_IMAGE;
1007     static char tabName[] = "TAB";
1008     tcNewTab.mask = mask;
1009     tcNewTab.pszText = tabName;
1010 
1011     ok(parent_wnd != NULL, "no parent window!\n");
1012 
1013     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
1014     ok(hTab != NULL, "Failed to create tab control\n");
1015 
1016     r = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1017     expect(-1, r);
1018 
1019     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1020 
1021     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1022     expect(0, nTabsRetrieved);
1023 
1024     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1025     expect(-1, r);
1026 
1027     tcNewTab.iImage = 1;
1028     r = SendMessageA(hTab, TCM_INSERTITEMA, 1, (LPARAM)&tcNewTab);
1029     expect(0, r);
1030 
1031     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1032     expect(1, nTabsRetrieved);
1033 
1034     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1035     expect(0, r);
1036 
1037     tcNewTab.iImage = 2;
1038     r = SendMessageA(hTab, TCM_INSERTITEMA, 2, (LPARAM)&tcNewTab);
1039     expect(1, r);
1040 
1041     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1042     expect(2, nTabsRetrieved);
1043 
1044     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1045     expect(0, r);
1046 
1047     r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1048     expect(0, r);
1049 
1050     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1051     expect(-1, r);
1052 
1053     tcNewTab.iImage = 3;
1054     r = SendMessageA(hTab, TCM_INSERTITEMA, 3, (LPARAM)&tcNewTab);
1055     expect(2, r);
1056 
1057     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1058     expect(2, r);
1059 
1060     ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
1061     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE);
1062 
1063     DestroyWindow(hTab);
1064 }
1065 
test_delete_focus(void)1066 static void test_delete_focus(void)
1067 {
1068     HWND hTab;
1069     INT nTabsRetrieved;
1070     INT r;
1071 
1072     ok(parent_wnd != NULL, "no parent window!\n");
1073 
1074     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1075     ok(hTab != NULL, "Failed to create tab control\n");
1076 
1077     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1078 
1079     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1080     expect(2, nTabsRetrieved);
1081 
1082     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1083     expect(0, r);
1084 
1085     r = SendMessageA(hTab, TCM_DELETEITEM, 1, 0);
1086     expect(1, r);
1087 
1088     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1089     expect(1, nTabsRetrieved);
1090 
1091     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1092     expect(0, r);
1093 
1094     r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1095     expect(0, r);
1096 
1097     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1098     expect(-1, r);
1099 
1100     r = SendMessageA(hTab, TCM_DELETEITEM, 0, 0);
1101     expect(1, r);
1102 
1103     nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1104     expect(0, nTabsRetrieved);
1105 
1106     r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1107     expect(-1, r);
1108 
1109     ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
1110     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE);
1111 
1112     DestroyWindow(hTab);
1113 }
1114 
test_removeimage(void)1115 static void test_removeimage(void)
1116 {
1117     static const BYTE bits[32];
1118     HWND hwTab;
1119     INT i;
1120     TCITEMA item;
1121     HICON hicon;
1122     HIMAGELIST himl = pImageList_Create(16, 16, ILC_COLOR, 3, 4);
1123 
1124     hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits);
1125     pImageList_ReplaceIcon(himl, -1, hicon);
1126     pImageList_ReplaceIcon(himl, -1, hicon);
1127     pImageList_ReplaceIcon(himl, -1, hicon);
1128 
1129     hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1130     SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1131 
1132     memset(&item, 0, sizeof(TCITEMA));
1133     item.mask = TCIF_IMAGE;
1134 
1135     for(i = 0; i < 3; i++) {
1136         SendMessageA(hwTab, TCM_GETITEMA, i, (LPARAM)&item);
1137         expect(i, item.iImage);
1138     }
1139 
1140     /* remove image middle image */
1141     SendMessageA(hwTab, TCM_REMOVEIMAGE, 1, 0);
1142     i = pImageList_GetImageCount(himl);
1143     ok(i == 2, "Unexpected image count %d.\n", i);
1144     item.iImage = -1;
1145     SendMessageA(hwTab, TCM_GETITEMA, 0, (LPARAM)&item);
1146     expect(0, item.iImage);
1147     item.iImage = 0;
1148     SendMessageA(hwTab, TCM_GETITEMA, 1, (LPARAM)&item);
1149     expect(-1, item.iImage);
1150     item.iImage = 0;
1151     SendMessageA(hwTab, TCM_GETITEMA, 2, (LPARAM)&item);
1152     expect(1, item.iImage);
1153     /* remove first image */
1154     SendMessageA(hwTab, TCM_REMOVEIMAGE, 0, 0);
1155     i = pImageList_GetImageCount(himl);
1156     ok(i == 1, "Unexpected image count %d.\n", i);
1157     item.iImage = 0;
1158     SendMessageA(hwTab, TCM_GETITEMA, 0, (LPARAM)&item);
1159     expect(-1, item.iImage);
1160     item.iImage = 0;
1161     SendMessageA(hwTab, TCM_GETITEMA, 1, (LPARAM)&item);
1162     expect(-1, item.iImage);
1163     item.iImage = -1;
1164     SendMessageA(hwTab, TCM_GETITEMA, 2, (LPARAM)&item);
1165     expect(0, item.iImage);
1166     /* remove the last one */
1167     SendMessageA(hwTab, TCM_REMOVEIMAGE, 0, 0);
1168     i = pImageList_GetImageCount(himl);
1169     ok(i == 0, "Unexpected image count %d.\n", i);
1170     for(i = 0; i < 3; i++) {
1171         item.iImage = 0;
1172         SendMessageA(hwTab, TCM_GETITEMA, i, (LPARAM)&item);
1173         expect(-1, item.iImage);
1174     }
1175 
1176     DestroyWindow(hwTab);
1177     pImageList_Destroy(himl);
1178     DestroyIcon(hicon);
1179 }
1180 
test_delete_selection(void)1181 static void test_delete_selection(void)
1182 {
1183     HWND hTab;
1184     INT ret;
1185 
1186     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1187     ok(hTab != NULL, "Failed to create tab control\n");
1188 
1189     ret = SendMessageA(hTab, TCM_SETCURSEL, 3, 0);
1190     expect(0, ret);
1191     ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1192     expect(3, ret);
1193     /* delete selected item - selection goes to -1 */
1194     ret = SendMessageA(hTab, TCM_DELETEITEM, 3, 0);
1195     expect(TRUE, ret);
1196 
1197     ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1198     expect(-1, ret);
1199 
1200     DestroyWindow(hTab);
1201 }
1202 
test_TCM_SETITEMEXTRA(void)1203 static void test_TCM_SETITEMEXTRA(void)
1204 {
1205     HWND hTab;
1206     DWORD ret;
1207 
1208     hTab = CreateWindowA(
1209 	WC_TABCONTROLA,
1210 	"TestTab",
1211 	WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH,
1212         10, 10, 300, 100,
1213         parent_wnd, NULL, NULL, 0);
1214 
1215     /* zero is valid size too */
1216     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 0, 0);
1217     if (ret == FALSE)
1218     {
1219         win_skip("TCM_SETITEMEXTRA not supported\n");
1220         DestroyWindow(hTab);
1221         return;
1222     }
1223 
1224     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, -1, 0);
1225     ok(ret == FALSE, "got %d\n", ret);
1226 
1227     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1228     ok(ret == TRUE, "got %d\n", ret);
1229     DestroyWindow(hTab);
1230 
1231     /* it's not possible to change extra data size for control with tabs */
1232     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1233     ok(hTab != NULL, "Failed to create tab control\n");
1234 
1235     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1236     ok(ret == FALSE, "got %d\n", ret);
1237     DestroyWindow(hTab);
1238 }
1239 
test_TCS_OWNERDRAWFIXED(void)1240 static void test_TCS_OWNERDRAWFIXED(void)
1241 {
1242     LPARAM lparam;
1243     ULONG_PTR itemdata, itemdata2;
1244     TCITEMA item;
1245     HWND hTab;
1246     BOOL ret;
1247 
1248     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH|TCS_OWNERDRAWFIXED, TCIF_TEXT|TCIF_IMAGE, 4);
1249     ok(hTab != NULL, "Failed to create tab control\n");
1250 
1251     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1252 
1253     /* set some item data */
1254     memset(&lparam, 0xde, sizeof(LPARAM));
1255 
1256     item.mask = TCIF_PARAM;
1257     item.lParam = lparam;
1258     ret = SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&item);
1259     ok(ret == TRUE, "got %d\n", ret);
1260 
1261     memset(&g_drawitem, 0, sizeof(g_drawitem));
1262 
1263     ShowWindow(hTab, SW_SHOW);
1264     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1265 
1266     itemdata = 0;
1267     memset(&itemdata, 0xde, 4);
1268     ok(g_drawitem.itemData == itemdata, "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata);
1269 
1270     DestroyWindow(hTab);
1271 
1272     /* now with custom extra data length */
1273     hTab = CreateWindowA(
1274 	WC_TABCONTROLA,
1275 	"TestTab",
1276 	WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1277         10, 10, 300, 100,
1278         parent_wnd, NULL, NULL, 0);
1279 
1280     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1281 
1282     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)+1, 0);
1283     ok(ret == TRUE, "got %d\n", ret);
1284 
1285     /* set some item data */
1286     memset(&lparam, 0xde, sizeof(LPARAM));
1287     item.mask = TCIF_PARAM;
1288     item.lParam = lparam;
1289 
1290     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1291     ok(ret == 0, "got %d\n", ret);
1292 
1293     memset(&g_drawitem, 0, sizeof(g_drawitem));
1294 
1295     ShowWindow(hTab, SW_SHOW);
1296     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1297 
1298     memset(&itemdata, 0xde, sizeof(ULONG_PTR));
1299     ok(*(ULONG_PTR*)g_drawitem.itemData == itemdata, "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata);
1300 
1301     DestroyWindow(hTab);
1302 
1303     /* same thing, but size smaller than default */
1304     hTab = CreateWindowA(
1305 	WC_TABCONTROLA,
1306 	"TestTab",
1307 	WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1308         10, 10, 300, 100,
1309         parent_wnd, NULL, NULL, 0);
1310 
1311     ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1312 
1313     ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
1314     ok(ret == TRUE, "got %d\n", ret);
1315 
1316     memset(&lparam, 0xde, sizeof(lparam));
1317     item.mask = TCIF_PARAM;
1318     item.lParam = lparam;
1319 
1320     ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1321     ok(ret == 0, "got %d\n", ret);
1322 
1323     memset(&g_drawitem, 0, sizeof(g_drawitem));
1324 
1325     ShowWindow(hTab, SW_SHOW);
1326     RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1327 
1328     itemdata = itemdata2 = 0;
1329     memset(&itemdata, 0xde, 4);
1330     memset(&itemdata2, 0xde, sizeof(LPARAM)-1);
1331     ok(g_drawitem.itemData == itemdata || broken(g_drawitem.itemData == itemdata2) /* win98 */,
1332         "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, itemdata);
1333 
1334     DestroyWindow(hTab);
1335 }
1336 
test_WM_CONTEXTMENU(void)1337 static void test_WM_CONTEXTMENU(void)
1338 {
1339     HWND hTab;
1340 
1341     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1342     ok(hTab != NULL, "Failed to create tab control\n");
1343 
1344     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1345 
1346     SendMessageA(hTab, WM_RBUTTONUP, 0, 0);
1347 
1348     ok_sequence(sequences, TAB_SEQ_INDEX, rbuttonup_seq, "WM_RBUTTONUP response sequence", FALSE);
1349 
1350     DestroyWindow(hTab);
1351 }
1352 
1353 struct tabcreate_style {
1354     DWORD style;
1355     DWORD act_style;
1356 };
1357 
1358 static const struct tabcreate_style create_styles[] =
1359 {
1360     { WS_CHILD|TCS_BOTTOM|TCS_VERTICAL, WS_CHILD|WS_CLIPSIBLINGS|TCS_BOTTOM|TCS_VERTICAL|TCS_MULTILINE },
1361     { WS_CHILD|TCS_VERTICAL,            WS_CHILD|WS_CLIPSIBLINGS|TCS_VERTICAL|TCS_MULTILINE },
1362     { 0 }
1363 };
1364 
test_create(void)1365 static void test_create(void)
1366 {
1367     const struct tabcreate_style *ptr = create_styles;
1368     DWORD style;
1369     HWND hTab;
1370 
1371     while (ptr->style)
1372     {
1373         hTab = CreateWindowA(WC_TABCONTROLA, "TestTab", ptr->style,
1374             10, 10, 300, 100, parent_wnd, NULL, NULL, 0);
1375         style = GetWindowLongA(hTab, GWL_STYLE);
1376         ok(style == ptr->act_style, "expected style 0x%08x, got style 0x%08x\n", ptr->act_style, style);
1377 
1378         DestroyWindow(hTab);
1379         ptr++;
1380     }
1381 }
1382 
init_functions(void)1383 static void init_functions(void)
1384 {
1385     HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
1386 
1387 #define X(f) p##f = (void*)GetProcAddress(hComCtl32, #f);
1388     X(ImageList_Create);
1389     X(ImageList_Destroy);
1390     X(ImageList_GetImageCount);
1391     X(ImageList_ReplaceIcon);
1392 #undef X
1393 }
1394 
test_TCN_SELCHANGING(void)1395 static void test_TCN_SELCHANGING(void)
1396 {
1397     const INT nTabs = 5;
1398     HWND hTab;
1399     INT ret;
1400 
1401     hTab = createFilledTabControl(parent_wnd, WS_CHILD|TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
1402     ok(hTab != NULL, "Failed to create tab control\n");
1403 
1404     /* Initially first tab is focused. */
1405     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1406     ok(ret == 0, "Unexpected tab focus %d.\n", ret);
1407 
1408     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1409 
1410     /* Setting focus to currently focused item should do nothing. */
1411     ret = SendMessageA(hTab, TCM_SETCURFOCUS, 0, 0);
1412     ok(ret == 0, "Unexpected ret value %d.\n", ret);
1413 
1414     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set focus to focused tab sequence", FALSE);
1415 
1416     /* Allow selection change. */
1417     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1418 
1419     tcn_selchanging_result = 0;
1420     ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs - 1, 0);
1421     ok(ret == 0, "Unexpected ret value %d.\n", ret);
1422 
1423     ok_sequence(sequences, PARENT_SEQ_INDEX, full_selchange_parent_seq, "Focus change allowed sequence", FALSE);
1424 
1425     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1426     ok(ret == nTabs - 1, "Unexpected focused tab %d.\n", ret);
1427     ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1428     ok(ret == nTabs - 1, "Unexpected selected tab %d.\n", ret);
1429 
1430     /* Forbid selection change. */
1431     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1432 
1433     tcn_selchanging_result = 1;
1434     ret = SendMessageA(hTab, TCM_SETCURFOCUS, 0, 0);
1435     ok(ret == 0, "Unexpected ret value %d.\n", ret);
1436 
1437     ok_sequence(sequences, PARENT_SEQ_INDEX, selchanging_parent_seq, "Focus change disallowed sequence", FALSE);
1438 
1439     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1440 todo_wine
1441     ok(ret == nTabs - 1, "Unexpected focused tab %d.\n", ret);
1442     ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1443 todo_wine
1444     ok(ret == nTabs - 1, "Unexpected selected tab %d.\n", ret);
1445 
1446     /* Removing focus sends only TCN_SELCHANGE */
1447     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1448 
1449     ret = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1450     ok(ret == 0, "Unexpected ret value %d.\n", ret);
1451 
1452     ok_sequence(sequences, PARENT_SEQ_INDEX, selchange_parent_seq, "Remove focus sequence", FALSE);
1453 
1454     ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1455     ok(ret == -1, "Unexpected focused tab %d.\n", ret);
1456 
1457     tcn_selchanging_result = 0;
1458 
1459     DestroyWindow(hTab);
1460 }
1461 
test_TCM_GETROWCOUNT(void)1462 static void test_TCM_GETROWCOUNT(void)
1463 {
1464     const INT nTabs = 5;
1465     HWND hTab;
1466     INT count;
1467 
1468     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1469 
1470     hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
1471     ok(hTab != NULL, "Failed to create tab control\n");
1472 
1473     flush_sequences(sequences, NUM_MSG_SEQUENCES);
1474 
1475     count = SendMessageA(hTab, TCM_GETROWCOUNT, 0, 0);
1476     ok(count == 1, "Unexpected row count %d.\n", count);
1477 
1478     ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
1479     ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
1480 
1481     DestroyWindow(hTab);
1482 }
1483 
START_TEST(tab)1484 START_TEST(tab)
1485 {
1486     LOGFONTA logfont;
1487 
1488     lstrcpyA(logfont.lfFaceName, "Arial");
1489     memset(&logfont, 0, sizeof(logfont));
1490     logfont.lfHeight = -12;
1491     logfont.lfWeight = FW_NORMAL;
1492     logfont.lfCharSet = ANSI_CHARSET;
1493     hFont = CreateFontIndirectA(&logfont);
1494 
1495     init_functions();
1496 
1497     init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1498 
1499     parent_wnd = createParentWindow();
1500     ok(parent_wnd != NULL, "Failed to create parent window!\n");
1501 
1502     test_width();
1503     test_curfocus();
1504     test_cursel();
1505     test_extendedstyle();
1506     test_unicodeformat();
1507     test_getset_item();
1508     test_getset_tooltips();
1509     test_adjustrect();
1510     test_insert_focus();
1511     test_delete_focus();
1512     test_delete_selection();
1513     test_removeimage();
1514     test_TCM_SETITEMEXTRA();
1515     test_TCS_OWNERDRAWFIXED();
1516     test_WM_CONTEXTMENU();
1517     test_create();
1518     test_TCN_SELCHANGING();
1519     test_TCM_GETROWCOUNT();
1520 
1521     DestroyWindow(parent_wnd);
1522 }
1523