1 /* Unit test suite for tab control.
3 * Copyright 2003 Vitaliy Margolen
4 * Copyright 2007 Hagop Hagopian
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.
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.
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
26 #include "wine/test.h"
29 #define DEFAULT_MIN_TAB_WIDTH 54
30 #define TAB_PADDING_X 6
31 #define EXTRA_ICON_PADDING 3
34 #define NUM_MSG_SEQUENCES 2
35 #define PARENT_SEQ_INDEX 0
36 #define TAB_SEQ_INDEX 1
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)
42 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
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);
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);\
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);
65 static DRAWITEMSTRUCT g_drawitem;
67 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
69 static const struct message create_parent_wnd_seq[] = {
70 { WM_GETMINMAXINFO, sent },
71 { WM_NCCREATE, sent },
72 { WM_NCCALCSIZE, sent|wparam, 0 },
74 { WM_SHOWWINDOW, sent|wparam, 1 },
75 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
76 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
77 { WM_ACTIVATEAPP, sent|wparam, 1 },
78 { WM_NCACTIVATE, sent|wparam, 1 },
79 { WM_ACTIVATE, sent|wparam, 1 },
80 { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
81 { WM_IME_NOTIFY, sent|defwinproc|optional },
82 { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
83 /* Win9x adds SWP_NOZORDER below */
84 { WM_WINDOWPOSCHANGED, sent},
85 { WM_NCCALCSIZE, sent|wparam|optional, 1 },
91 static const struct message add_tab_to_parent[] = {
92 { TCM_INSERTITEMA, sent },
93 { TCM_INSERTITEMA, sent|optional },
94 { WM_NOTIFYFORMAT, sent|defwinproc },
95 { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc|optional, 0, 0 },
96 { WM_PARENTNOTIFY, sent|defwinproc },
97 { TCM_INSERTITEMA, sent },
98 { TCM_INSERTITEMA, sent },
99 { TCM_INSERTITEMA, sent },
100 { TCM_INSERTITEMA, sent|optional },
104 static const struct message add_tab_to_parent_interactive[] = {
105 { TCM_INSERTITEMA, sent },
106 { TCM_INSERTITEMA, sent },
107 { WM_NOTIFYFORMAT, sent|defwinproc },
108 { WM_QUERYUISTATE, sent|wparam|lparam|defwinproc, 0, 0 },
109 { WM_PARENTNOTIFY, sent|defwinproc },
110 { TCM_INSERTITEMA, sent },
111 { TCM_INSERTITEMA, sent },
112 { TCM_INSERTITEMA, sent },
113 { WM_SHOWWINDOW, sent},
114 { WM_WINDOWPOSCHANGING, sent},
115 { WM_WINDOWPOSCHANGING, sent},
116 { WM_NCACTIVATE, sent},
117 { WM_ACTIVATE, sent},
118 { WM_IME_SETCONTEXT, sent|defwinproc|optional},
119 { WM_IME_NOTIFY, sent|defwinproc|optional},
120 { WM_SETFOCUS, sent|defwinproc},
121 { WM_WINDOWPOSCHANGED, sent},
127 static const struct message add_tab_control_parent_seq[] = {
128 { WM_NOTIFYFORMAT, sent },
129 { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
133 static const struct message add_tab_control_parent_seq_interactive[] = {
134 { WM_NOTIFYFORMAT, sent },
135 { WM_QUERYUISTATE, sent|wparam|lparam, 0, 0 },
136 { WM_WINDOWPOSCHANGING, sent|optional},
137 { WM_NCACTIVATE, sent},
138 { WM_ACTIVATE, sent},
139 { WM_WINDOWPOSCHANGING, sent|optional},
140 { WM_KILLFOCUS, sent},
141 { WM_IME_SETCONTEXT, sent|optional},
142 { WM_IME_NOTIFY, sent|optional},
146 static const struct message empty_sequence[] = {
150 static const struct message set_min_tab_width_seq[] = {
151 { TCM_SETMINTABWIDTH, sent|wparam, 0 },
152 { TCM_SETMINTABWIDTH, sent|wparam, 0 },
156 static const struct message get_item_count_seq[] = {
157 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
161 static const struct message get_row_count_seq[] = {
162 { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
166 static const struct message get_item_rect_seq[] = {
167 { TCM_GETITEMRECT, sent },
168 { TCM_GETITEMRECT, sent },
172 static const struct message getset_cur_focus_seq[] = {
173 { TCM_SETCURFOCUS, sent|lparam, 0 },
174 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
175 { TCM_SETCURFOCUS, sent|lparam, 0 },
176 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
177 { TCM_SETCURSEL, sent|lparam, 0 },
178 { TCM_SETCURFOCUS, sent|lparam, 0 },
179 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
183 static const struct message getset_cur_sel_seq[] = {
184 { TCM_SETCURSEL, sent|lparam, 0 },
185 { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
186 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
187 { TCM_SETCURSEL, sent|lparam, 0 },
188 { TCM_GETCURSEL, sent|wparam|lparam, 0, 0 },
189 { TCM_SETCURSEL, sent|lparam, 0 },
190 { TCM_SETCURSEL, sent|lparam, 0 },
191 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
195 static const struct message getset_extended_style_seq[] = {
196 { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
197 { TCM_SETEXTENDEDSTYLE, sent },
198 { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
199 { TCM_SETEXTENDEDSTYLE, sent },
200 { TCM_GETEXTENDEDSTYLE, sent|wparam|lparam, 0, 0 },
204 static const struct message getset_unicode_format_seq[] = {
205 { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
206 { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
207 { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
208 { CCM_GETUNICODEFORMAT, sent|wparam|lparam, 0, 0 },
209 { CCM_SETUNICODEFORMAT, sent|lparam, 0 },
213 static const struct message getset_item_seq[] = {
214 { TCM_SETITEMA, sent },
215 { TCM_GETITEMA, sent },
216 { TCM_GETITEMA, sent },
220 static const struct message getset_tooltip_seq[] = {
221 { WM_NOTIFYFORMAT, sent|optional },
222 { WM_QUERYUISTATE, sent|wparam|lparam|optional, 0, 0 },
223 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
224 { WM_NOTIFYFORMAT, sent|optional },
225 { TCM_SETTOOLTIPS, sent|lparam, 0 },
226 { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
227 { TCM_SETTOOLTIPS, sent|lparam, 0 },
228 { TCM_GETTOOLTIPS, sent|wparam|lparam, 0, 0 },
232 static const struct message getset_tooltip_parent_seq[] = {
233 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
237 static const struct message insert_focus_seq[] = {
238 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
239 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
240 { TCM_INSERTITEM, sent|wparam, 1 },
241 { WM_NOTIFYFORMAT, sent|defwinproc|optional },
242 { WM_QUERYUISTATE, sent|defwinproc|optional },
243 { WM_PARENTNOTIFY, sent|defwinproc|optional },
244 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
245 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
246 { TCM_INSERTITEM, sent|wparam, 2 },
247 { WM_NOTIFYFORMAT, sent|defwinproc|optional },
248 { WM_QUERYUISTATE, sent|defwinproc|optional, },
249 { WM_PARENTNOTIFY, sent|defwinproc|optional },
250 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
251 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
252 { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
253 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
254 { TCM_INSERTITEM, sent|wparam, 3 },
255 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
259 static const struct message delete_focus_seq[] = {
260 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
261 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
262 { TCM_DELETEITEM, sent|wparam|lparam, 1, 0 },
263 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
264 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
265 { TCM_SETCURFOCUS, sent|wparam|lparam, -1, 0 },
266 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
267 { TCM_DELETEITEM, sent|wparam|lparam, 0, 0 },
268 { TCM_GETITEMCOUNT, sent|wparam|lparam, 0, 0 },
269 { TCM_GETCURFOCUS, sent|wparam|lparam, 0, 0 },
275 create_tabcontrol (DWORD style, DWORD mask)
279 static char text1[] = "Tab 1",
280 text2[] = "Wide Tab 2",
283 handle = CreateWindow (
286 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
288 NULL, NULL, NULL, 0);
292 SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
293 SendMessage (handle, WM_SETFONT, 0, (LPARAM) hFont);
295 tcNewTab.mask = mask;
296 tcNewTab.pszText = text1;
298 SendMessage (handle, TCM_INSERTITEM, 0, (LPARAM) &tcNewTab);
299 tcNewTab.pszText = text2;
301 SendMessage (handle, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
302 tcNewTab.pszText = text3;
304 SendMessage (handle, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
306 if (winetest_interactive)
308 ShowWindow (handle, SW_SHOW);
309 RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
316 static LRESULT WINAPI parentWindowProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
318 static LONG defwndproc_counter = 0;
322 /* do not log painting messages */
323 if (message != WM_PAINT &&
324 message != WM_ERASEBKGND &&
325 message != WM_NCPAINT &&
326 message != WM_NCHITTEST &&
327 message != WM_GETTEXT &&
328 message != WM_GETICON &&
329 message != WM_DEVICECHANGE)
331 trace("parent: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
333 msg.message = message;
334 msg.flags = sent|wparam|lparam;
335 if (defwndproc_counter) msg.flags |= defwinproc;
338 add_message(sequences, PARENT_SEQ_INDEX, &msg);
341 /* dump sent structure data */
342 if (message == WM_DRAWITEM)
343 g_drawitem = *(DRAWITEMSTRUCT*)lParam;
345 defwndproc_counter++;
346 ret = DefWindowProcA(hwnd, message, wParam, lParam);
347 defwndproc_counter--;
352 static BOOL registerParentWindowClass(void)
357 cls.lpfnWndProc = parentWindowProcess;
360 cls.hInstance = GetModuleHandleA(NULL);
362 cls.hCursor = LoadCursorA(0, IDC_ARROW);
363 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
364 cls.lpszMenuName = NULL;
365 cls.lpszClassName = "Tab test parent class";
366 return RegisterClassA(&cls);
369 static HWND createParentWindow(void)
371 if (!registerParentWindowClass())
374 return CreateWindowEx(0, "Tab test parent class",
375 "Tab test parent window",
376 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
377 WS_MAXIMIZEBOX | WS_VISIBLE,
379 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
382 static LRESULT WINAPI tabSubclassProcess(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
384 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
385 static LONG defwndproc_counter = 0;
389 /* do not log painting messages */
390 if (message != WM_PAINT &&
391 message != WM_ERASEBKGND &&
392 message != WM_NCPAINT &&
393 message != WM_NCHITTEST &&
394 message != WM_GETTEXT &&
395 message != WM_GETICON &&
396 message != WM_DEVICECHANGE)
398 trace("tab: %p, %04x, %08lx, %08lx\n", hwnd, message, wParam, lParam);
400 msg.message = message;
401 msg.flags = sent|wparam|lparam;
402 if (defwndproc_counter) msg.flags |= defwinproc;
405 add_message(sequences, TAB_SEQ_INDEX, &msg);
408 defwndproc_counter++;
409 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
410 defwndproc_counter--;
415 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
423 GetClientRect(parent_wnd, &rect);
425 tabHandle = CreateWindow (
428 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style,
429 0, 0, rect.right, rect.bottom,
430 parent_wnd, NULL, NULL, 0);
434 oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tabSubclassProcess);
435 SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
437 tcNewTab.mask = mask;
439 for (i = 0; i < nTabs; i++)
441 char tabName[MAX_TABLEN];
443 sprintf(tabName, "Tab %d", i+1);
444 tcNewTab.pszText = tabName;
446 SendMessage (tabHandle, TCM_INSERTITEM, i, (LPARAM) &tcNewTab);
449 if (winetest_interactive)
451 ShowWindow (tabHandle, SW_SHOW);
452 RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
459 static HWND create_tooltip (HWND hTab, char toolTipText[])
464 LPTSTR lptstr = toolTipText;
467 /* Creating a tooltip window*/
468 hwndTT = CreateWindowEx(
472 WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
473 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
474 hTab, NULL, 0, NULL);
480 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
482 GetClientRect (hTab, &rect);
484 /* Initialize members of toolinfo*/
485 ti.cbSize = sizeof(TOOLINFO);
486 ti.uFlags = TTF_SUBCLASS;
490 ti.lpszText = lptstr;
494 /* Add toolinfo structure to the tooltip control */
495 SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) &ti);
500 static void test_tab(INT nMinTabWidth)
504 HIMAGELIST himl = ImageList_Create(21, 21, ILC_COLOR, 3, 4);
510 hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
511 SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
512 /* Get System default MinTabWidth */
513 if (nMinTabWidth < 0)
514 nMinTabWidth = SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
517 dpi = GetDeviceCaps(hdc, LOGPIXELSX);
518 hOldFont = SelectObject(hdc, (HFONT)SendMessage(hwTab, WM_GETFONT, 0, 0));
519 GetTextExtentPoint32A(hdc, "Tab 1", strlen("Tab 1"), &size);
520 trace("Tab1 text size: size.cx=%d size.cy=%d\n", size.cx, size.cy);
521 SelectObject(hdc, hOldFont);
522 ReleaseDC(hwTab, hdc);
524 trace (" TCS_FIXEDWIDTH tabs no icon...\n");
525 CheckSize(hwTab, dpi, -1, "default width");
526 TabCheckSetSize(hwTab, 50, 20, 50, 20, "set size");
527 TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
529 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
531 trace (" TCS_FIXEDWIDTH tabs with icon...\n");
532 TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
533 TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
534 TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
536 DestroyWindow (hwTab);
538 hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
539 SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
542 dpi = GetDeviceCaps(hdc, LOGPIXELSX);
543 ReleaseDC(hwTab, hdc);
544 trace (" TCS_FIXEDWIDTH buttons no icon...\n");
545 CheckSize(hwTab, dpi, -1, "default width");
546 TabCheckSetSize(hwTab, 20, 20, 20, 20, "set size 1");
547 TabCheckSetSize(hwTab, 10, 50, 10, 50, "set size 2");
548 TabCheckSetSize(hwTab, 0, 1, 0, 1, "min size");
550 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
552 trace (" TCS_FIXEDWIDTH buttons with icon...\n");
553 TabCheckSetSize(hwTab, 50, 30, 50, 30, "set size > icon");
554 TabCheckSetSize(hwTab, 20, 20, 25, 20, "set size < icon");
555 TabCheckSetSize(hwTab, 0, 1, 25, 1, "min size");
556 SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
557 TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
559 DestroyWindow (hwTab);
561 hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
562 SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
565 dpi = GetDeviceCaps(hdc, LOGPIXELSX);
566 ReleaseDC(hwTab, hdc);
567 trace (" TCS_FIXEDWIDTH | TCS_BOTTOM tabs...\n");
568 CheckSize(hwTab, dpi, -1, "no icon, default width");
570 TabCheckSetSize(hwTab, 20, 20, 20, 20, "no icon, set size 1");
571 TabCheckSetSize(hwTab, 10, 50, 10, 50, "no icon, set size 2");
572 TabCheckSetSize(hwTab, 0, 1, 0, 1, "no icon, min size");
574 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
576 TabCheckSetSize(hwTab, 50, 30, 50, 30, "with icon, set size > icon");
577 TabCheckSetSize(hwTab, 20, 20, 25, 20, "with icon, set size < icon");
578 TabCheckSetSize(hwTab, 0, 1, 25, 1, "with icon, min size");
579 SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4));
580 TabCheckSetSize(hwTab, 0, 1, 25, 1, "set padding, min size");
582 DestroyWindow (hwTab);
584 hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
585 SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
587 trace (" non fixed width, with text...\n");
588 exp = max(size.cx +TAB_PADDING_X*2, (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth);
589 SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
590 ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH),
591 "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
595 INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
597 SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
598 SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
600 TabCheckSetSize(hwTab, 50, 20, max(size.cx + i*2, nTabWidth), 20, "no icon, set size");
601 TabCheckSetSize(hwTab, 0, 1, max(size.cx + i*2, nTabWidth), 1, "no icon, min size");
603 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
604 nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
606 TabCheckSetSize(hwTab, 50, 30, max(size.cx + 21 + i*3, nTabWidth), 30, "with icon, set size > icon");
607 TabCheckSetSize(hwTab, 20, 20, max(size.cx + 21 + i*3, nTabWidth), 20, "with icon, set size < icon");
608 TabCheckSetSize(hwTab, 0, 1, max(size.cx + 21 + i*3, nTabWidth), 1, "with icon, min size");
610 DestroyWindow (hwTab);
612 hwTab = create_tabcontrol(0, TCIF_IMAGE);
613 SendMessage(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
615 trace (" non fixed width, no text...\n");
616 exp = (nMinTabWidth < 0) ? DEFAULT_MIN_TAB_WIDTH : nMinTabWidth;
617 SendMessage( hwTab, TCM_GETITEMRECT, 0, (LPARAM)&rTab );
618 ok( rTab.right - rTab.left == exp || broken(rTab.right - rTab.left == DEFAULT_MIN_TAB_WIDTH),
619 "no icon, default width: Expected width [%d] got [%d]\n", exp, rTab.right - rTab.left );
623 INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
625 SendMessage(hwTab, TCM_SETIMAGELIST, 0, 0);
626 SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i,i));
628 TabCheckSetSize(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
629 TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
631 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
632 if (i > 1 && nMinTabWidth > 0 && nMinTabWidth < DEFAULT_MIN_TAB_WIDTH)
633 nTabWidth += EXTRA_ICON_PADDING *(i-1);
635 TabCheckSetSize(hwTab, 50, 30, nTabWidth, 30, "with icon, set size > icon");
636 TabCheckSetSize(hwTab, 20, 20, nTabWidth, 20, "with icon, set size < icon");
637 TabCheckSetSize(hwTab, 0, 1, nTabWidth, 1, "with icon, min size");
640 DestroyWindow (hwTab);
642 ImageList_Destroy(himl);
646 static void test_curfocus(HWND parent_wnd, INT nTabs)
651 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
652 ok(hTab != NULL, "Failed to create tab control\n");
654 flush_sequences(sequences, NUM_MSG_SEQUENCES);
656 /* Testing CurFocus with largest appropriate value */
657 SendMessage(hTab, TCM_SETCURFOCUS, nTabs-1, 0);
658 focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
659 expect(nTabs-1, focusIndex);
661 /* Testing CurFocus with negative value */
662 SendMessage(hTab, TCM_SETCURFOCUS, -10, 0);
663 focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
664 expect(-1, focusIndex);
666 /* Testing CurFocus with value larger than number of tabs */
667 focusIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
668 expect(-1, focusIndex);
670 SendMessage(hTab, TCM_SETCURFOCUS, nTabs+1, 0);
671 focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
672 expect(1, focusIndex);
674 ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_focus_seq, "Getset curFoc test sequence", FALSE);
679 static void test_cursel(HWND parent_wnd, INT nTabs)
686 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
687 ok(hTab != NULL, "Failed to create tab control\n");
689 flush_sequences(sequences, NUM_MSG_SEQUENCES);
691 /* Testing CurSel with largest appropriate value */
692 selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs-1, 0);
693 expect(0, selectionIndex);
694 selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
695 expect(nTabs-1, selectionIndex);
697 /* Focus should switch with selection */
698 focusIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
699 expect(nTabs-1, focusIndex);
701 /* Testing CurSel with negative value */
702 SendMessage(hTab, TCM_SETCURSEL, -10, 0);
703 selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
704 expect(-1, selectionIndex);
706 /* Testing CurSel with value larger than number of tabs */
707 selectionIndex = SendMessage(hTab, TCM_SETCURSEL, 1, 0);
708 expect(-1, selectionIndex);
710 selectionIndex = SendMessage(hTab, TCM_SETCURSEL, nTabs+1, 0);
711 expect(-1, selectionIndex);
712 selectionIndex = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
713 expect(1, selectionIndex);
715 ok_sequence(sequences, TAB_SEQ_INDEX, getset_cur_sel_seq, "Getset curSel test sequence", FALSE);
716 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset curSel test parent sequence", FALSE);
718 /* selected item should have TCIS_BUTTONPRESSED state
719 It doesn't depend on button state */
720 memset(&tcItem, 0, sizeof(TCITEM));
721 tcItem.mask = TCIF_STATE;
722 tcItem.dwStateMask = TCIS_BUTTONPRESSED;
723 selectionIndex = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
724 SendMessage(hTab, TCM_GETITEM, selectionIndex, (LPARAM) &tcItem);
725 ok (tcItem.dwState & TCIS_BUTTONPRESSED || broken(tcItem.dwState == 0), /* older comctl32 */
726 "Selected item should have TCIS_BUTTONPRESSED\n");
731 static void test_extendedstyle(HWND parent_wnd, INT nTabs)
733 DWORD prevExtendedStyle;
737 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
738 ok(hTab != NULL, "Failed to create tab control\n");
740 flush_sequences(sequences, NUM_MSG_SEQUENCES);
742 /* Testing Flat Separators */
743 extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
744 prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_FLATSEPARATORS);
745 expect(extendedStyle, prevExtendedStyle);
747 extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
748 expect(TCS_EX_FLATSEPARATORS, extendedStyle);
750 /* Testing Register Drop */
751 prevExtendedStyle = SendMessage(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
752 expect(extendedStyle, prevExtendedStyle);
754 extendedStyle = SendMessage(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
756 expect(TCS_EX_REGISTERDROP, extendedStyle);
759 ok_sequence(sequences, TAB_SEQ_INDEX, getset_extended_style_seq, "Getset extendedStyle test sequence", FALSE);
760 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset extendedStyle test parent sequence", FALSE);
765 static void test_unicodeformat(HWND parent_wnd, INT nTabs)
770 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
771 ok(hTab != NULL, "Failed to create tab control\n");
773 flush_sequences(sequences, NUM_MSG_SEQUENCES);
775 unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
777 expect(0, unicodeFormat);
779 unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
780 expect(1, unicodeFormat);
782 unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
783 expect(1, unicodeFormat);
784 unicodeFormat = SendMessage(hTab, TCM_GETUNICODEFORMAT, 0, 0);
785 expect(0, unicodeFormat);
787 unicodeFormat = SendMessage(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
788 expect(0, unicodeFormat);
790 ok_sequence(sequences, TAB_SEQ_INDEX, getset_unicode_format_seq, "Getset unicodeFormat test sequence", FALSE);
791 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset unicodeFormat test parent sequence", FALSE);
796 static void test_getset_item(HWND parent_wnd, INT nTabs)
798 char szText[32] = "New Label";
804 hTab = CreateWindowA(
807 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
809 parent_wnd, NULL, NULL, 0);
811 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
813 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
814 ok(ret == TRUE, "got %d\n", ret);
816 /* set some item data */
818 tcItem.mask = TCIF_PARAM;
820 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&tcItem);
821 ok(ret == 0, "got %d\n", ret);
823 /* all sizeof(LPARAM) returned anyway when using sizeof(LPARAM)-1 size */
824 memset(&lparam, 0xaa, sizeof(lparam));
825 tcItem.lParam = lparam;
826 tcItem.mask = TCIF_PARAM;
827 ret = SendMessage(hTab, TCM_GETITEM, 0, (LPARAM)&tcItem);
829 /* everything higher specified size is preserved */
830 memset(&lparam, 0xff, sizeof(lparam)-1);
831 ok(tcItem.lParam == lparam, "Expected 0x%lx, got 0x%lx\n", lparam, tcItem.lParam);
835 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
836 ok(hTab != NULL, "Failed to create tab control\n");
838 /* passing invalid index should result in initialization to zero
839 for members mentioned in mask requested */
841 /* valid range here is [0,4] */
842 memset(&tcItem, 0xcc, sizeof(tcItem));
843 tcItem.mask = TCIF_PARAM;
844 ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
846 ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
848 memset(&tcItem, 0xcc, sizeof(tcItem));
849 tcItem.mask = TCIF_IMAGE;
850 ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
852 expect(0, tcItem.iImage);
854 memset(&tcItem, 0xcc, sizeof(tcItem));
855 tcItem.mask = TCIF_TEXT;
856 tcItem.pszText = szText;
858 ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
860 expect('a', szText[0]);
862 memset(&tcItem, 0xcc, sizeof(tcItem));
863 tcItem.mask = TCIF_STATE;
864 tcItem.dwStateMask = 0;
865 tcItem.dwState = TCIS_BUTTONPRESSED;
866 ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
868 ok(tcItem.dwState == 0, "Expected zero dwState, got %u\n", tcItem.dwState);
870 memset(&tcItem, 0xcc, sizeof(tcItem));
871 tcItem.mask = TCIF_STATE;
872 tcItem.dwStateMask = TCIS_BUTTONPRESSED;
873 tcItem.dwState = TCIS_BUTTONPRESSED;
874 ret = SendMessage(hTab, TCM_GETITEM, 5, (LPARAM)&tcItem);
876 ok(tcItem.dwState == 0, "Expected zero dwState\n");
878 /* check with negative index to be sure */
879 memset(&tcItem, 0xcc, sizeof(tcItem));
880 tcItem.mask = TCIF_PARAM;
881 ret = SendMessage(hTab, TCM_GETITEM, -1, (LPARAM)&tcItem);
883 ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
885 memset(&tcItem, 0xcc, sizeof(tcItem));
886 tcItem.mask = TCIF_PARAM;
887 ret = SendMessage(hTab, TCM_GETITEM, -2, (LPARAM)&tcItem);
889 ok(tcItem.lParam == 0, "Expected zero lParam, got %lu\n", tcItem.lParam);
891 flush_sequences(sequences, NUM_MSG_SEQUENCES);
893 tcItem.mask = TCIF_TEXT;
894 tcItem.pszText = &szText[0];
895 tcItem.cchTextMax = sizeof(szText);
897 strcpy(szText, "New Label");
898 ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
899 ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
900 expect_str("New Label", tcItem.pszText);
902 ok ( SendMessage(hTab, TCM_GETITEM, 1, (LPARAM) &tcItem), "Getting item failed.\n");
903 expect_str("Tab 2", tcItem.pszText);
905 ok_sequence(sequences, TAB_SEQ_INDEX, getset_item_seq, "Getset item test sequence", FALSE);
906 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset item test parent sequence", FALSE);
908 /* TCIS_BUTTONPRESSED doesn't depend on tab style */
909 memset(&tcItem, 0, sizeof(tcItem));
910 tcItem.mask = TCIF_STATE;
911 tcItem.dwStateMask = TCIS_BUTTONPRESSED;
912 tcItem.dwState = TCIS_BUTTONPRESSED;
913 ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
915 ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
918 ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
919 /* next highlight item, test that dwStateMask actually masks */
920 tcItem.mask = TCIF_STATE;
921 tcItem.dwStateMask = TCIS_HIGHLIGHTED;
922 tcItem.dwState = TCIS_HIGHLIGHTED;
923 ok ( SendMessage(hTab, TCM_SETITEM, 0, (LPARAM) &tcItem), "Setting new item failed.\n");
925 ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
926 ok (tcItem.dwState == TCIS_HIGHLIGHTED, "TCIS_HIGHLIGHTED should be set.\n");
927 tcItem.mask = TCIF_STATE;
928 tcItem.dwStateMask = TCIS_BUTTONPRESSED;
930 ok ( SendMessage(hTab, TCM_GETITEM, 0, (LPARAM) &tcItem), "Getting item failed.\n");
931 ok (tcItem.dwState == TCIS_BUTTONPRESSED, "TCIS_BUTTONPRESSED should be set.\n");
933 else win_skip( "Item state mask not supported\n" );
938 static void test_getset_tooltips(HWND parent_wnd, INT nTabs)
941 char toolTipText[32] = "ToolTip Text Test";
943 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
944 ok(hTab != NULL, "Failed to create tab control\n");
946 flush_sequences(sequences, NUM_MSG_SEQUENCES);
948 toolTip = create_tooltip(hTab, toolTipText);
949 SendMessage(hTab, TCM_SETTOOLTIPS, (LPARAM) toolTip, 0);
950 ok (toolTip == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
952 SendMessage(hTab, TCM_SETTOOLTIPS, 0, 0);
953 ok (NULL == (HWND) SendMessage(hTab,TCM_GETTOOLTIPS,0,0), "ToolTip was set incorrectly.\n");
955 ok_sequence(sequences, TAB_SEQ_INDEX, getset_tooltip_seq, "Getset tooltip test sequence", TRUE);
956 ok_sequence(sequences, PARENT_SEQ_INDEX, getset_tooltip_parent_seq, "Getset tooltip test parent sequence", TRUE);
961 static void test_misc(HWND parent_wnd, INT nTabs)
970 ok(parent_wnd != NULL, "no parent window!\n");
971 flush_sequences(sequences, NUM_MSG_SEQUENCES);
973 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
974 ok(hTab != NULL, "Failed to create tab control\n");
976 if(!winetest_interactive)
977 ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent,
978 "Tab sequence, after adding tab control to parent", TRUE);
980 ok_sequence(sequences, TAB_SEQ_INDEX, add_tab_to_parent_interactive,
981 "Tab sequence, after adding tab control to parent", TRUE);
983 if(!winetest_interactive)
984 ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq,
985 "Parent after sequence, adding tab control to parent", TRUE);
987 ok_sequence(sequences, PARENT_SEQ_INDEX, add_tab_control_parent_seq_interactive,
988 "Parent after sequence, adding tab control to parent", TRUE);
990 flush_sequences(sequences, NUM_MSG_SEQUENCES);
991 ok(SendMessage(hTab, TCM_SETMINTABWIDTH, 0, -1) > 0,"TCM_SETMINTABWIDTH returned < 0\n");
992 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set minTabWidth test parent sequence", FALSE);
994 /* Testing GetItemCount */
995 flush_sequences(sequences, NUM_MSG_SEQUENCES);
996 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
997 expect(nTabs, nTabsRetrieved);
998 ok_sequence(sequences, TAB_SEQ_INDEX, get_item_count_seq, "Get itemCount test sequence", FALSE);
999 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Getset itemCount test parent sequence", FALSE);
1001 /* Testing GetRowCount */
1002 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1003 rowCount = SendMessage(hTab, TCM_GETROWCOUNT, 0, 0);
1004 expect(1, rowCount);
1005 ok_sequence(sequences, TAB_SEQ_INDEX, get_row_count_seq, "Get rowCount test sequence", FALSE);
1006 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get rowCount test parent sequence", FALSE);
1008 /* Testing GetItemRect */
1009 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1010 ok(SendMessage(hTab, TCM_GETITEMRECT, 0, (LPARAM) &rTab), "GetItemRect failed.\n");
1013 dpi = GetDeviceCaps(hdc, LOGPIXELSX);
1014 ReleaseDC(hTab, hdc);
1015 CheckSize(hTab, dpi, -1 , "Default Width");
1016 ok_sequence(sequences, TAB_SEQ_INDEX, get_item_rect_seq, "Get itemRect test sequence", FALSE);
1017 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Get itemRect test parent sequence", FALSE);
1019 DestroyWindow(hTab);
1022 static void test_adjustrect(HWND parent_wnd)
1027 ok(parent_wnd != NULL, "no parent window!\n");
1029 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
1030 ok(hTab != NULL, "Failed to create tab control\n");
1032 r = SendMessage(hTab, TCM_ADJUSTRECT, FALSE, 0);
1035 r = SendMessage(hTab, TCM_ADJUSTRECT, TRUE, 0);
1039 static void test_insert_focus(HWND parent_wnd)
1045 DWORD mask = TCIF_TEXT|TCIF_IMAGE;
1046 static char tabName[] = "TAB";
1047 tcNewTab.mask = mask;
1048 tcNewTab.pszText = tabName;
1050 ok(parent_wnd != NULL, "no parent window!\n");
1052 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
1053 ok(hTab != NULL, "Failed to create tab control\n");
1055 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1057 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1058 expect(0, nTabsRetrieved);
1060 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1063 tcNewTab.iImage = 1;
1064 r = SendMessage(hTab, TCM_INSERTITEM, 1, (LPARAM) &tcNewTab);
1067 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1068 expect(1, nTabsRetrieved);
1070 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1073 tcNewTab.iImage = 2;
1074 r = SendMessage(hTab, TCM_INSERTITEM, 2, (LPARAM) &tcNewTab);
1077 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1078 expect(2, nTabsRetrieved);
1080 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1083 r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1086 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1089 tcNewTab.iImage = 3;
1090 r = SendMessage(hTab, TCM_INSERTITEM, 3, (LPARAM) &tcNewTab);
1093 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1096 ok_sequence(sequences, TAB_SEQ_INDEX, insert_focus_seq, "insert_focus test sequence", FALSE);
1097 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "insert_focus parent test sequence", TRUE);
1099 DestroyWindow(hTab);
1102 static void test_delete_focus(HWND parent_wnd)
1108 ok(parent_wnd != NULL, "no parent window!\n");
1110 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1111 ok(hTab != NULL, "Failed to create tab control\n");
1113 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1115 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1116 expect(2, nTabsRetrieved);
1118 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1121 r = SendMessage(hTab, TCM_DELETEITEM, 1, 0);
1124 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1125 expect(1, nTabsRetrieved);
1127 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1130 r = SendMessage(hTab, TCM_SETCURFOCUS, -1, 0);
1133 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1136 r = SendMessage(hTab, TCM_DELETEITEM, 0, 0);
1139 nTabsRetrieved = SendMessage(hTab, TCM_GETITEMCOUNT, 0, 0);
1140 expect(0, nTabsRetrieved);
1142 r = SendMessage(hTab, TCM_GETCURFOCUS, 0, 0);
1145 ok_sequence(sequences, TAB_SEQ_INDEX, delete_focus_seq, "delete_focus test sequence", FALSE);
1146 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "delete_focus parent test sequence", TRUE);
1148 DestroyWindow(hTab);
1151 static void test_removeimage(void)
1153 static const BYTE bits[32];
1158 HIMAGELIST himl = ImageList_Create(16, 16, ILC_COLOR, 3, 4);
1160 hicon = CreateIcon(NULL, 16, 16, 1, 1, bits, bits);
1161 ImageList_AddIcon(himl, hicon);
1162 ImageList_AddIcon(himl, hicon);
1163 ImageList_AddIcon(himl, hicon);
1165 hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1166 SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1168 memset(&item, 0, sizeof(TCITEM));
1169 item.mask = TCIF_IMAGE;
1171 for(i = 0; i < 3; i++) {
1172 SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1173 expect(i, item.iImage);
1176 /* remove image middle image */
1177 SendMessage(hwTab, TCM_REMOVEIMAGE, 1, 0);
1178 expect(2, ImageList_GetImageCount(himl));
1180 SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1181 expect(0, item.iImage);
1183 SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1184 expect(-1, item.iImage);
1186 SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1187 expect(1, item.iImage);
1188 /* remove first image */
1189 SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1190 expect(1, ImageList_GetImageCount(himl));
1192 SendMessage(hwTab, TCM_GETITEM, 0, (LPARAM)&item);
1193 expect(-1, item.iImage);
1195 SendMessage(hwTab, TCM_GETITEM, 1, (LPARAM)&item);
1196 expect(-1, item.iImage);
1198 SendMessage(hwTab, TCM_GETITEM, 2, (LPARAM)&item);
1199 expect(0, item.iImage);
1200 /* remove the last one */
1201 SendMessage(hwTab, TCM_REMOVEIMAGE, 0, 0);
1202 expect(0, ImageList_GetImageCount(himl));
1203 for(i = 0; i < 3; i++) {
1205 SendMessage(hwTab, TCM_GETITEM, i, (LPARAM)&item);
1206 expect(-1, item.iImage);
1209 DestroyWindow(hwTab);
1210 ImageList_Destroy(himl);
1214 static void test_delete_selection(HWND parent_wnd)
1219 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1220 ok(hTab != NULL, "Failed to create tab control\n");
1222 ret = SendMessage(hTab, TCM_SETCURSEL, 3, 0);
1224 ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1226 /* delete selected item - selection goes to -1 */
1227 ret = SendMessage(hTab, TCM_DELETEITEM, 3, 0);
1230 ret = SendMessage(hTab, TCM_GETCURSEL, 0, 0);
1233 DestroyWindow(hTab);
1236 static void test_TCM_SETITEMEXTRA(HWND parent_wnd)
1241 hTab = CreateWindowA(
1244 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH,
1246 parent_wnd, NULL, NULL, 0);
1248 /* zero is valid size too */
1249 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 0, 0);
1252 win_skip("TCM_SETITEMEXTRA not supported\n");
1253 DestroyWindow(hTab);
1257 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, -1, 0);
1258 ok(ret == FALSE, "got %d\n", ret);
1260 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1261 ok(ret == TRUE, "got %d\n", ret);
1262 DestroyWindow(hTab);
1264 /* it's not possible to change extra data size for control with tabs */
1265 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1266 ok(hTab != NULL, "Failed to create tab control\n");
1268 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1269 ok(ret == FALSE, "got %d\n", ret);
1270 DestroyWindow(hTab);
1273 static void test_TCS_OWNERDRAWFIXED(HWND parent_wnd)
1275 LPARAM lparam, lparam2;
1280 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH|TCS_OWNERDRAWFIXED, TCIF_TEXT|TCIF_IMAGE, 4);
1281 ok(hTab != NULL, "Failed to create tab control\n");
1283 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1285 /* set some item data */
1286 memset(&lparam, 0xde, sizeof(LPARAM));
1288 item.mask = TCIF_PARAM;
1289 item.lParam = lparam;
1290 ret = SendMessageA(hTab, TCM_SETITEMA, 0, (LPARAM)&item);
1291 ok(ret == TRUE, "got %d\n", ret);
1293 memset(&g_drawitem, 0, sizeof(g_drawitem));
1295 ShowWindow(hTab, SW_SHOW);
1296 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1299 memset(&lparam, 0xde, 4);
1300 ok(g_drawitem.itemData == lparam, "got %lx, expected %lx\n", g_drawitem.itemData, lparam);
1302 DestroyWindow(hTab);
1304 /* now with custom extra data length */
1305 hTab = CreateWindowA(
1308 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1310 parent_wnd, NULL, NULL, 0);
1312 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1314 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)+1, 0);
1315 ok(ret == TRUE, "got %d\n", ret);
1317 /* set some item data */
1318 memset(&lparam, 0xde, sizeof(LPARAM));
1319 item.mask = TCIF_PARAM;
1320 item.lParam = lparam;
1322 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1323 ok(ret == 0, "got %d\n", ret);
1325 memset(&g_drawitem, 0, sizeof(g_drawitem));
1327 ShowWindow(hTab, SW_SHOW);
1328 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1330 ok(*(ULONG_PTR*)g_drawitem.itemData == lparam, "got %lx, expected %lx\n", g_drawitem.itemData, lparam);
1332 DestroyWindow(hTab);
1334 /* same thing, but size smaller than default */
1335 hTab = CreateWindowA(
1338 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | TCS_FIXEDWIDTH | TCS_OWNERDRAWFIXED,
1340 parent_wnd, NULL, NULL, 0);
1342 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1344 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
1345 ok(ret == TRUE, "got %d\n", ret);
1347 memset(&lparam, 0xde, sizeof(lparam));
1348 item.mask = TCIF_PARAM;
1349 item.lParam = lparam;
1351 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1352 ok(ret == 0, "got %d\n", ret);
1354 memset(&g_drawitem, 0, sizeof(g_drawitem));
1356 ShowWindow(hTab, SW_SHOW);
1357 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
1360 memset(&lparam, 0xde, 4);
1361 memset(&lparam2, 0xde, sizeof(LPARAM)-1);
1362 ok(g_drawitem.itemData == lparam || broken(g_drawitem.itemData == lparam2) /* win98 */,
1363 "got 0x%lx, expected 0x%lx\n", g_drawitem.itemData, lparam);
1365 DestroyWindow(hTab);
1373 lstrcpyA(logfont.lfFaceName, "Arial");
1374 memset(&logfont, 0, sizeof(logfont));
1375 logfont.lfHeight = -12;
1376 logfont.lfWeight = FW_NORMAL;
1377 logfont.lfCharSet = ANSI_CHARSET;
1378 hFont = CreateFontIndirectA(&logfont);
1380 InitCommonControls();
1382 trace ("Testing with default MinWidth\n");
1384 trace ("Testing with MinWidth set to -3\n");
1386 trace ("Testing with MinWidth set to 24\n");
1388 trace ("Testing with MinWidth set to 54\n");
1390 trace ("Testing with MinWidth set to 94\n");
1393 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1395 parent_wnd = createParentWindow();
1396 ok(parent_wnd != NULL, "Failed to create parent window!\n");
1398 test_curfocus(parent_wnd, 5);
1399 test_cursel(parent_wnd, 5);
1400 test_extendedstyle(parent_wnd, 5);
1401 test_unicodeformat(parent_wnd, 5);
1402 test_getset_item(parent_wnd, 5);
1403 test_getset_tooltips(parent_wnd, 5);
1404 test_misc(parent_wnd, 5);
1406 test_adjustrect(parent_wnd);
1408 test_insert_focus(parent_wnd);
1409 test_delete_focus(parent_wnd);
1410 test_delete_selection(parent_wnd);
1412 test_TCM_SETITEMEXTRA(parent_wnd);
1413 test_TCS_OWNERDRAWFIXED(parent_wnd);
1415 DestroyWindow(parent_wnd);