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