wined3d: Pass a wined3d_device_context to wined3d_cs_emit_blt_sub_resource().
[wine/zf.git] / dlls / comctl32 / tests / tab.c
blobd3e0e0c6cf9574497b7dee03259f2fd0b0bf1091
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
21 #include <windows.h>
22 #include <commctrl.h>
23 #include <stdio.h>
25 #include "wine/test.h"
26 #include "msg.h"
28 #define DEFAULT_MIN_TAB_WIDTH 54
29 #define TAB_PADDING_X 6
30 #define EXTRA_ICON_PADDING 3
31 #define MAX_TABLEN 32
33 #define NUM_MSG_SEQUENCES 2
34 #define PARENT_SEQ_INDEX 0
35 #define TAB_SEQ_INDEX 1
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)
41 #define TabWidthPadded(padd_x, num) (DEFAULT_MIN_TAB_WIDTH - (TAB_PADDING_X - (padd_x)) * num)
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);
48 static void CheckSize(HWND hwnd, INT width, INT height, const char *msg, int line)
50 RECT r;
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);
65 #define CHECKSIZE(hwnd,width,height,msg) CheckSize(hwnd,width,height,msg,__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)
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);
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__)
79 static HFONT hFont;
80 static DRAWITEMSTRUCT g_drawitem;
81 static HWND parent_wnd;
82 static LRESULT tcn_selchanging_result;
84 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
86 static const struct message empty_sequence[] = {
87 { 0 }
90 static const struct message get_row_count_seq[] = {
91 { TCM_GETROWCOUNT, sent|wparam|lparam, 0, 0 },
92 { 0 }
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 }
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 }
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 }
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 }
136 static const struct message getset_item_seq[] = {
137 { TCM_SETITEMA, sent },
138 { TCM_GETITEMA, sent },
139 { TCM_GETITEMA, sent },
140 { 0 }
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 }
155 static const struct message getset_tooltip_parent_seq[] = {
156 { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
157 { 0 }
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 }
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 }
196 static const struct message rbuttonup_seq[] = {
197 { WM_RBUTTONUP, sent|wparam|lparam, 0, 0 },
198 { WM_CONTEXTMENU, sent|defwinproc },
199 { 0 }
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 }
208 static const struct message selchanging_parent_seq[] = {
209 { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGING },
210 { 0 }
213 static const struct message selchange_parent_seq[] = {
214 { WM_NOTIFY, sent|id, 0, 0, TCN_SELCHANGE },
215 { 0 }
218 static const struct message setfocus_parent_seq[] = {
219 { WM_NOTIFY, sent|id, 0, 0, TCN_FOCUSCHANGE },
220 { 0 }
223 static HWND
224 create_tabcontrol (DWORD style, DWORD mask)
226 HWND handle;
227 TCITEMA tcNewTab;
228 static char text1[] = "Tab 1",
229 text2[] = "Wide Tab 2",
230 text3[] = "T 3";
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");
237 SetWindowLongA(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style);
238 SendMessageA(handle, WM_SETFONT, 0, (LPARAM)hFont);
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);
251 if (winetest_interactive)
253 ShowWindow (handle, SW_SHOW);
254 RedrawWindow (handle, NULL, 0, RDW_UPDATENOW);
255 Sleep (1000);
258 return handle;
261 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
263 static LONG defwndproc_counter = 0;
264 struct message msg = { 0 };
265 LRESULT ret;
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)
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);
286 /* dump sent structure data */
287 if (message == WM_DRAWITEM)
288 g_drawitem = *(DRAWITEMSTRUCT*)lParam;
290 if (message == WM_NOTIFY)
292 NMHDR *nmhdr = (NMHDR *)lParam;
293 if (nmhdr && nmhdr->code == TCN_SELCHANGING)
294 return tcn_selchanging_result;
297 defwndproc_counter++;
298 ret = DefWindowProcA(hwnd, message, wParam, lParam);
299 defwndproc_counter--;
301 return ret;
304 static BOOL registerParentWindowClass(void)
306 WNDCLASSA cls;
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);
321 static HWND createParentWindow(void)
323 if (!registerParentWindowClass())
324 return NULL;
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);
331 static LRESULT WINAPI tab_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
333 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
334 static LONG defwndproc_counter = 0;
335 struct message msg = { 0 };
336 LRESULT ret;
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)
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);
355 defwndproc_counter++;
356 ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
357 defwndproc_counter--;
359 return ret;
362 static HWND createFilledTabControl(HWND parent_wnd, DWORD style, DWORD mask, INT nTabs)
364 HWND tabHandle;
365 TCITEMA tcNewTab;
366 WNDPROC oldproc;
367 RECT rect;
368 INT i;
370 GetClientRect(parent_wnd, &rect);
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");
377 oldproc = (WNDPROC)SetWindowLongPtrA(tabHandle, GWLP_WNDPROC, (LONG_PTR)tab_subclass_proc);
378 SetWindowLongPtrA(tabHandle, GWLP_USERDATA, (LONG_PTR)oldproc);
380 tcNewTab.mask = mask;
382 for (i = 0; i < nTabs; i++)
384 char tabName[MAX_TABLEN];
386 sprintf(tabName, "Tab %d", i+1);
387 tcNewTab.pszText = tabName;
388 tcNewTab.iImage = i;
389 SendMessageA(tabHandle, TCM_INSERTITEMA, i, (LPARAM)&tcNewTab);
392 if (winetest_interactive)
394 ShowWindow (tabHandle, SW_SHOW);
395 RedrawWindow (tabHandle, NULL, 0, RDW_UPDATENOW);
396 Sleep (1000);
399 return tabHandle;
402 static HWND create_tooltip (HWND hTab, char toolTipText[])
404 HWND hwndTT;
406 TTTOOLINFOA ti;
407 LPSTR lptstr = toolTipText;
408 RECT rect;
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);
415 SetWindowPos(
416 hwndTT,
417 HWND_TOPMOST,
418 0, 0, 0, 0,
419 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
421 GetClientRect (hTab, &rect);
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;
431 ti.rect = rect;
433 /* Add toolinfo structure to the tooltip control */
434 SendMessageA(hwndTT, TTM_ADDTOOLA, 0, (LPARAM)&ti);
436 return hwndTT;
439 static void test_tab(INT nMinTabWidth)
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;
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);
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);
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");
468 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
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");
475 DestroyWindow (hwTab);
477 hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS, TCIF_TEXT|TCIF_IMAGE);
478 SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
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");
489 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
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");
498 DestroyWindow (hwTab);
500 hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM, TCIF_TEXT|TCIF_IMAGE);
501 SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
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");
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");
513 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
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");
521 DestroyWindow (hwTab);
523 hwTab = create_tabcontrol(0, TCIF_TEXT|TCIF_IMAGE);
524 SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
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 );
532 for (i=0; i<8; i++)
534 INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
536 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0);
537 SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i));
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");
542 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
543 nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 3) : nMinTabWidth;
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");
549 DestroyWindow (hwTab);
551 hwTab = create_tabcontrol(0, TCIF_IMAGE);
552 SendMessageA(hwTab, TCM_SETMINTABWIDTH, 0, nMinTabWidth);
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 );
560 for (i=0; i<8; i++)
562 INT nTabWidth = (nMinTabWidth < 0) ? TabWidthPadded(i, 2) : nMinTabWidth;
564 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, 0);
565 SendMessageA(hwTab, TCM_SETPADDING, 0, MAKELPARAM(i, i));
567 TABCHECKSETSIZE(hwTab, 50, 20, nTabWidth, 20, "no icon, set size");
568 TABCHECKSETSIZE(hwTab, 0, 1, nTabWidth, 1, "no icon, min size");
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);
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");
579 DestroyWindow (hwTab);
581 pImageList_Destroy(himl);
584 static void test_width(void)
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);
598 static void test_curfocus(void)
600 const INT nTabs = 5;
601 INT ret;
602 HWND hTab;
604 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
605 ok(hTab != NULL, "Failed to create tab control\n");
607 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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);
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);
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);
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);
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);
633 DestroyWindow(hTab);
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");
639 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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);
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);
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);
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);
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);
668 DestroyWindow(hTab);
671 static void test_cursel(void)
673 const INT nTabs = 5;
674 INT selectionIndex;
675 INT focusIndex;
676 TCITEMA tcItem;
677 HWND hTab;
679 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
680 ok(hTab != NULL, "Failed to create tab control\n");
682 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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);
690 /* Focus should switch with selection */
691 focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
692 expect(nTabs-1, focusIndex);
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);
699 /* Testing CurSel with value larger than number of tabs */
700 selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, 1, 0);
701 expect(-1, selectionIndex);
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);
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);
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");
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);
725 selectionIndex = SendMessageA(hTab, TCM_SETCURSEL, -1, 0);
726 ok(selectionIndex == 1, "got %d\n", selectionIndex);
728 memset(&tcItem, 0, sizeof(TCITEMA));
730 /* focus is reset too */
731 focusIndex = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
732 ok(focusIndex == -1, "got %d\n", focusIndex);
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);
739 DestroyWindow(hTab);
742 static void test_extendedstyle(void)
744 const INT nTabs = 5;
745 DWORD prevExtendedStyle;
746 DWORD extendedStyle;
747 HWND hTab;
749 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
750 ok(hTab != NULL, "Failed to create tab control\n");
752 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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);
759 extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
760 expect(TCS_EX_FLATSEPARATORS, extendedStyle);
762 /* Testing Register Drop */
763 prevExtendedStyle = SendMessageA(hTab, TCM_SETEXTENDEDSTYLE, 0, TCS_EX_REGISTERDROP);
764 expect(extendedStyle, prevExtendedStyle);
766 extendedStyle = SendMessageA(hTab, TCM_GETEXTENDEDSTYLE, 0, 0);
767 todo_wine{
768 expect(TCS_EX_REGISTERDROP, extendedStyle);
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);
774 DestroyWindow(hTab);
777 static void test_unicodeformat(void)
779 const INT nTabs = 5;
780 INT unicodeFormat;
781 HWND hTab;
783 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
784 ok(hTab != NULL, "Failed to create tab control\n");
786 flush_sequences(sequences, NUM_MSG_SEQUENCES);
788 unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
789 todo_wine{
790 expect(0, unicodeFormat);
792 unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0);
793 expect(1, unicodeFormat);
795 unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, FALSE, 0);
796 expect(1, unicodeFormat);
797 unicodeFormat = SendMessageA(hTab, TCM_GETUNICODEFORMAT, 0, 0);
798 expect(0, unicodeFormat);
800 unicodeFormat = SendMessageA(hTab, TCM_SETUNICODEFORMAT, TRUE, 0);
801 expect(0, unicodeFormat);
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);
806 DestroyWindow(hTab);
809 static void test_getset_item(void)
811 char szText[32] = "New Label";
812 const INT nTabs = 5;
813 TCITEMA tcItem;
814 LPARAM lparam;
815 DWORD ret;
816 HWND hTab;
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);
825 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
827 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
828 ok(ret == TRUE, "got %d\n", ret);
830 /* set some item data */
831 tcItem.lParam = ~0;
832 tcItem.mask = TCIF_PARAM;
834 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&tcItem);
835 ok(ret == 0, "got %d\n", ret);
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);
847 DestroyWindow(hTab);
849 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
850 ok(hTab != NULL, "Failed to create tab control\n");
852 /* passing invalid index should result in initialization to zero
853 for members mentioned in mask requested */
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);
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);
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]);
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);
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");
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);
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);
905 flush_sequences(sequences, NUM_MSG_SEQUENCES);
907 tcItem.mask = TCIF_TEXT;
908 tcItem.pszText = &szText[0];
909 tcItem.cchTextMax = sizeof(szText);
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);
916 ok(SendMessageA(hTab, TCM_GETITEMA, 1, (LPARAM)&tcItem), "Getting item failed.\n");
917 expect_str("Tab 2", tcItem.pszText);
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);
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)
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");
947 else win_skip( "Item state mask not supported\n" );
949 DestroyWindow(hTab);
952 static void test_getset_tooltips(void)
954 char toolTipText[32] = "ToolTip Text Test";
955 HWND hTab, toolTip, hwnd;
956 const INT nTabs = 5;
957 int ret;
959 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
960 ok(hTab != NULL, "Failed to create tab control\n");
962 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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");
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");
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);
979 DestroyWindow(hTab);
980 DestroyWindow(toolTip);
983 static void test_adjustrect(void)
985 HWND hTab;
986 INT r;
988 ok(parent_wnd != NULL, "no parent window!\n");
990 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, 0, 0);
991 ok(hTab != NULL, "Failed to create tab control\n");
993 r = SendMessageA(hTab, TCM_ADJUSTRECT, FALSE, 0);
994 expect(-1, r);
996 r = SendMessageA(hTab, TCM_ADJUSTRECT, TRUE, 0);
997 expect(-1, r);
1000 static void test_insert_focus(void)
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;
1011 ok(parent_wnd != NULL, "no parent window!\n");
1013 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, mask, 0);
1014 ok(hTab != NULL, "Failed to create tab control\n");
1016 r = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1017 expect(-1, r);
1019 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1021 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1022 expect(0, nTabsRetrieved);
1024 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1025 expect(-1, r);
1027 tcNewTab.iImage = 1;
1028 r = SendMessageA(hTab, TCM_INSERTITEMA, 1, (LPARAM)&tcNewTab);
1029 expect(0, r);
1031 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1032 expect(1, nTabsRetrieved);
1034 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1035 expect(0, r);
1037 tcNewTab.iImage = 2;
1038 r = SendMessageA(hTab, TCM_INSERTITEMA, 2, (LPARAM)&tcNewTab);
1039 expect(1, r);
1041 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1042 expect(2, nTabsRetrieved);
1044 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1045 expect(0, r);
1047 r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1048 expect(0, r);
1050 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1051 expect(-1, r);
1053 tcNewTab.iImage = 3;
1054 r = SendMessageA(hTab, TCM_INSERTITEMA, 3, (LPARAM)&tcNewTab);
1055 expect(2, r);
1057 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1058 expect(2, r);
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);
1063 DestroyWindow(hTab);
1066 static void test_delete_focus(void)
1068 HWND hTab;
1069 INT nTabsRetrieved;
1070 INT r;
1072 ok(parent_wnd != NULL, "no parent window!\n");
1074 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 2);
1075 ok(hTab != NULL, "Failed to create tab control\n");
1077 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1079 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1080 expect(2, nTabsRetrieved);
1082 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1083 expect(0, r);
1085 r = SendMessageA(hTab, TCM_DELETEITEM, 1, 0);
1086 expect(1, r);
1088 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1089 expect(1, nTabsRetrieved);
1091 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1092 expect(0, r);
1094 r = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1095 expect(0, r);
1097 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1098 expect(-1, r);
1100 r = SendMessageA(hTab, TCM_DELETEITEM, 0, 0);
1101 expect(1, r);
1103 nTabsRetrieved = SendMessageA(hTab, TCM_GETITEMCOUNT, 0, 0);
1104 expect(0, nTabsRetrieved);
1106 r = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1107 expect(-1, r);
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);
1112 DestroyWindow(hTab);
1115 static void test_removeimage(void)
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);
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);
1129 hwTab = create_tabcontrol(TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE);
1130 SendMessageA(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl);
1132 memset(&item, 0, sizeof(TCITEMA));
1133 item.mask = TCIF_IMAGE;
1135 for(i = 0; i < 3; i++) {
1136 SendMessageA(hwTab, TCM_GETITEMA, i, (LPARAM)&item);
1137 expect(i, item.iImage);
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);
1176 DestroyWindow(hwTab);
1177 pImageList_Destroy(himl);
1178 DestroyIcon(hicon);
1181 static void test_delete_selection(void)
1183 HWND hTab;
1184 INT ret;
1186 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1187 ok(hTab != NULL, "Failed to create tab control\n");
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);
1197 ret = SendMessageA(hTab, TCM_GETCURSEL, 0, 0);
1198 expect(-1, ret);
1200 DestroyWindow(hTab);
1203 static void test_TCM_SETITEMEXTRA(void)
1205 HWND hTab;
1206 DWORD ret;
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);
1215 /* zero is valid size too */
1216 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 0, 0);
1217 if (ret == FALSE)
1219 win_skip("TCM_SETITEMEXTRA not supported\n");
1220 DestroyWindow(hTab);
1221 return;
1224 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, -1, 0);
1225 ok(ret == FALSE, "got %d\n", ret);
1227 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1228 ok(ret == TRUE, "got %d\n", ret);
1229 DestroyWindow(hTab);
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");
1235 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, 2, 0);
1236 ok(ret == FALSE, "got %d\n", ret);
1237 DestroyWindow(hTab);
1240 static void test_TCS_OWNERDRAWFIXED(void)
1242 LPARAM lparam;
1243 ULONG_PTR itemdata, itemdata2;
1244 TCITEMA item;
1245 HWND hTab;
1246 BOOL ret;
1248 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH|TCS_OWNERDRAWFIXED, TCIF_TEXT|TCIF_IMAGE, 4);
1249 ok(hTab != NULL, "Failed to create tab control\n");
1251 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1253 /* set some item data */
1254 memset(&lparam, 0xde, sizeof(LPARAM));
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);
1261 memset(&g_drawitem, 0, sizeof(g_drawitem));
1263 ShowWindow(hTab, SW_SHOW);
1264 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
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);
1270 DestroyWindow(hTab);
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);
1280 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1282 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)+1, 0);
1283 ok(ret == TRUE, "got %d\n", ret);
1285 /* set some item data */
1286 memset(&lparam, 0xde, sizeof(LPARAM));
1287 item.mask = TCIF_PARAM;
1288 item.lParam = lparam;
1290 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1291 ok(ret == 0, "got %d\n", ret);
1293 memset(&g_drawitem, 0, sizeof(g_drawitem));
1295 ShowWindow(hTab, SW_SHOW);
1296 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
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);
1301 DestroyWindow(hTab);
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);
1311 ok(GetParent(hTab) == NULL, "got %p, expected null parent\n", GetParent(hTab));
1313 ret = SendMessageA(hTab, TCM_SETITEMEXTRA, sizeof(LPARAM)-1, 0);
1314 ok(ret == TRUE, "got %d\n", ret);
1316 memset(&lparam, 0xde, sizeof(lparam));
1317 item.mask = TCIF_PARAM;
1318 item.lParam = lparam;
1320 ret = SendMessageA(hTab, TCM_INSERTITEMA, 0, (LPARAM)&item);
1321 ok(ret == 0, "got %d\n", ret);
1323 memset(&g_drawitem, 0, sizeof(g_drawitem));
1325 ShowWindow(hTab, SW_SHOW);
1326 RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW);
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);
1334 DestroyWindow(hTab);
1337 static void test_WM_CONTEXTMENU(void)
1339 HWND hTab;
1341 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, 4);
1342 ok(hTab != NULL, "Failed to create tab control\n");
1344 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1346 SendMessageA(hTab, WM_RBUTTONUP, 0, 0);
1348 ok_sequence(sequences, TAB_SEQ_INDEX, rbuttonup_seq, "WM_RBUTTONUP response sequence", FALSE);
1350 DestroyWindow(hTab);
1353 struct tabcreate_style {
1354 DWORD style;
1355 DWORD act_style;
1358 static const struct tabcreate_style create_styles[] =
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 }
1365 static void test_create(void)
1367 const struct tabcreate_style *ptr = create_styles;
1368 DWORD style;
1369 HWND hTab;
1371 while (ptr->style)
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);
1378 DestroyWindow(hTab);
1379 ptr++;
1383 static void init_functions(void)
1385 HMODULE hComCtl32 = LoadLibraryA("comctl32.dll");
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
1395 static void test_TCN_SELCHANGING(void)
1397 const INT nTabs = 5;
1398 HWND hTab;
1399 INT ret;
1401 hTab = createFilledTabControl(parent_wnd, WS_CHILD|TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
1402 ok(hTab != NULL, "Failed to create tab control\n");
1404 /* Initially first tab is focused. */
1405 ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1406 ok(ret == 0, "Unexpected tab focus %d.\n", ret);
1408 flush_sequences(sequences, NUM_MSG_SEQUENCES);
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);
1414 ok_sequence(sequences, PARENT_SEQ_INDEX, empty_sequence, "Set focus to focused tab sequence", FALSE);
1416 /* Allow selection change. */
1417 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1419 tcn_selchanging_result = 0;
1420 ret = SendMessageA(hTab, TCM_SETCURFOCUS, nTabs - 1, 0);
1421 ok(ret == 0, "Unexpected ret value %d.\n", ret);
1423 ok_sequence(sequences, PARENT_SEQ_INDEX, full_selchange_parent_seq, "Focus change allowed sequence", FALSE);
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);
1430 /* Forbid selection change. */
1431 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1433 tcn_selchanging_result = 1;
1434 ret = SendMessageA(hTab, TCM_SETCURFOCUS, 0, 0);
1435 ok(ret == 0, "Unexpected ret value %d.\n", ret);
1437 ok_sequence(sequences, PARENT_SEQ_INDEX, selchanging_parent_seq, "Focus change disallowed sequence", FALSE);
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);
1446 /* Removing focus sends only TCN_SELCHANGE */
1447 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1449 ret = SendMessageA(hTab, TCM_SETCURFOCUS, -1, 0);
1450 ok(ret == 0, "Unexpected ret value %d.\n", ret);
1452 ok_sequence(sequences, PARENT_SEQ_INDEX, selchange_parent_seq, "Remove focus sequence", FALSE);
1454 ret = SendMessageA(hTab, TCM_GETCURFOCUS, 0, 0);
1455 ok(ret == -1, "Unexpected focused tab %d.\n", ret);
1457 tcn_selchanging_result = 0;
1459 DestroyWindow(hTab);
1462 static void test_TCM_GETROWCOUNT(void)
1464 const INT nTabs = 5;
1465 HWND hTab;
1466 INT count;
1468 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1470 hTab = createFilledTabControl(parent_wnd, TCS_FIXEDWIDTH, TCIF_TEXT|TCIF_IMAGE, nTabs);
1471 ok(hTab != NULL, "Failed to create tab control\n");
1473 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1475 count = SendMessageA(hTab, TCM_GETROWCOUNT, 0, 0);
1476 ok(count == 1, "Unexpected row count %d.\n", count);
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);
1481 DestroyWindow(hTab);
1484 START_TEST(tab)
1486 LOGFONTA logfont;
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);
1495 init_functions();
1497 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1499 parent_wnd = createParentWindow();
1500 ok(parent_wnd != NULL, "Failed to create parent window!\n");
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();
1521 DestroyWindow(parent_wnd);