1 /* 2 * Copyright 2005 Dmitry Timoshkov 3 * Copyright 2008 Jason Edmeades 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "precomp.h" 21 22 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got) 23 24 static void test_create_tooltip(void) 25 { 26 HWND parent, hwnd; 27 DWORD style, exp_style; 28 29 parent = CreateWindowExA(0, "static", NULL, WS_POPUP, 30 0, 0, 0, 0, 31 NULL, NULL, NULL, 0); 32 ok(parent != NULL, "failed to create parent wnd\n"); 33 34 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0x7fffffff | WS_POPUP, 35 10, 10, 300, 100, 36 parent, NULL, NULL, 0); 37 ok(hwnd != NULL, "failed to create tooltip wnd\n"); 38 39 style = GetWindowLongA(hwnd, GWL_STYLE); 40 trace("style = %08x\n", style); 41 exp_style = 0x7fffffff | WS_POPUP; 42 exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME); 43 ok(style == exp_style || broken(style == (exp_style | WS_BORDER)), /* nt4 */ 44 "wrong style %08x/%08x\n", style, exp_style); 45 46 DestroyWindow(hwnd); 47 48 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 49 10, 10, 300, 100, 50 parent, NULL, NULL, 0); 51 ok(hwnd != NULL, "failed to create tooltip wnd\n"); 52 53 style = GetWindowLongA(hwnd, GWL_STYLE); 54 trace("style = %08x\n", style); 55 ok(style == (WS_POPUP | WS_CLIPSIBLINGS | WS_BORDER), 56 "wrong style %08x\n", style); 57 58 DestroyWindow(hwnd); 59 60 DestroyWindow(parent); 61 } 62 63 /* try to make sure pending X events have been processed before continuing */ 64 static void flush_events(int waitTime) 65 { 66 MSG msg; 67 int diff = waitTime; 68 DWORD time = GetTickCount() + waitTime; 69 70 while (diff > 0) 71 { 72 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min(100,diff), QS_ALLEVENTS) == WAIT_TIMEOUT) break; 73 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 74 diff = time - GetTickCount(); 75 } 76 } 77 78 static int CD_Stages; 79 static LRESULT CD_Result; 80 static HWND g_hwnd; 81 82 #define TEST_CDDS_PREPAINT 0x00000001 83 #define TEST_CDDS_POSTPAINT 0x00000002 84 #define TEST_CDDS_PREERASE 0x00000004 85 #define TEST_CDDS_POSTERASE 0x00000008 86 #define TEST_CDDS_ITEMPREPAINT 0x00000010 87 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020 88 #define TEST_CDDS_ITEMPREERASE 0x00000040 89 #define TEST_CDDS_ITEMPOSTERASE 0x00000080 90 #define TEST_CDDS_SUBITEM 0x00000100 91 92 static LRESULT CALLBACK custom_draw_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 93 { 94 switch(msg) { 95 96 case WM_DESTROY: 97 PostQuitMessage(0); 98 break; 99 100 case WM_NOTIFY: 101 if (((NMHDR *)lParam)->code == NM_CUSTOMDRAW) { 102 NMTTCUSTOMDRAW *ttcd = (NMTTCUSTOMDRAW*) lParam; 103 ok(ttcd->nmcd.hdr.hwndFrom == g_hwnd, "Unexpected hwnd source %p (%p)\n", 104 ttcd->nmcd.hdr.hwndFrom, g_hwnd); 105 ok(ttcd->nmcd.hdr.idFrom == 0x1234ABCD, "Unexpected id %x\n", (int)ttcd->nmcd.hdr.idFrom); 106 107 switch (ttcd->nmcd.dwDrawStage) { 108 case CDDS_PREPAINT : CD_Stages |= TEST_CDDS_PREPAINT; break; 109 case CDDS_POSTPAINT : CD_Stages |= TEST_CDDS_POSTPAINT; break; 110 case CDDS_PREERASE : CD_Stages |= TEST_CDDS_PREERASE; break; 111 case CDDS_POSTERASE : CD_Stages |= TEST_CDDS_POSTERASE; break; 112 case CDDS_ITEMPREPAINT : CD_Stages |= TEST_CDDS_ITEMPREPAINT; break; 113 case CDDS_ITEMPOSTPAINT: CD_Stages |= TEST_CDDS_ITEMPOSTPAINT; break; 114 case CDDS_ITEMPREERASE : CD_Stages |= TEST_CDDS_ITEMPREERASE; break; 115 case CDDS_ITEMPOSTERASE: CD_Stages |= TEST_CDDS_ITEMPOSTERASE; break; 116 case CDDS_SUBITEM : CD_Stages |= TEST_CDDS_SUBITEM; break; 117 default: CD_Stages = -1; 118 } 119 120 if (ttcd->nmcd.dwDrawStage == CDDS_PREPAINT) return CD_Result; 121 } 122 /* drop through */ 123 124 default: 125 return DefWindowProcA(hWnd, msg, wParam, lParam); 126 } 127 128 return 0L; 129 } 130 131 static void test_customdraw(void) { 132 static struct { 133 LRESULT FirstReturnValue; 134 int ExpectedCalls; 135 } expectedResults[] = { 136 /* Valid notification responses */ 137 {CDRF_DODEFAULT, TEST_CDDS_PREPAINT}, 138 {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT}, 139 {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT}, 140 141 /* Invalid notification responses */ 142 {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT}, 143 {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT}, 144 {CDRF_NEWFONT, TEST_CDDS_PREPAINT} 145 }; 146 147 DWORD iterationNumber; 148 WNDCLASSA wc; 149 LRESULT lResult; 150 POINT orig_pos; 151 152 /* Create a class to use the custom draw wndproc */ 153 wc.style = CS_HREDRAW | CS_VREDRAW; 154 wc.cbClsExtra = 0; 155 wc.cbWndExtra = 0; 156 wc.hInstance = GetModuleHandleA(NULL); 157 wc.hIcon = NULL; 158 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); 159 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); 160 wc.lpszMenuName = NULL; 161 wc.lpszClassName = "CustomDrawClass"; 162 wc.lpfnWndProc = custom_draw_wnd_proc; 163 RegisterClassA(&wc); 164 165 GetCursorPos(&orig_pos); 166 167 for (iterationNumber = 0; 168 iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]); 169 iterationNumber++) { 170 171 HWND parent, hwndTip; 172 RECT rect; 173 TTTOOLINFOA toolInfo = { 0 }; 174 175 /* Create a main window */ 176 parent = CreateWindowExA(0, "CustomDrawClass", NULL, 177 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 178 WS_MAXIMIZEBOX | WS_VISIBLE, 179 50, 50, 180 300, 300, 181 NULL, NULL, NULL, 0); 182 ok(parent != NULL, "Creation of main window failed\n"); 183 184 /* Make it show */ 185 ShowWindow(parent, SW_SHOWNORMAL); 186 flush_events(100); 187 188 /* Create Tooltip */ 189 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, 190 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, 191 CW_USEDEFAULT, CW_USEDEFAULT, 192 CW_USEDEFAULT, CW_USEDEFAULT, 193 parent, NULL, GetModuleHandleA(NULL), 0); 194 ok(hwndTip != NULL, "Creation of tooltip window failed\n"); 195 196 /* Set up parms for the wndproc to handle */ 197 CD_Stages = 0; 198 CD_Result = expectedResults[iterationNumber].FirstReturnValue; 199 g_hwnd = hwndTip; 200 201 /* Make it topmost, as per the MSDN */ 202 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0, 203 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 204 205 /* Create a tool */ 206 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; 207 toolInfo.hwnd = parent; 208 toolInfo.hinst = GetModuleHandleA(NULL); 209 toolInfo.uFlags = TTF_SUBCLASS; 210 toolInfo.uId = 0x1234ABCD; 211 toolInfo.lpszText = (LPSTR)"This is a test tooltip"; 212 toolInfo.lParam = 0xdeadbeef; 213 GetClientRect (parent, &toolInfo.rect); 214 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); 215 ok(lResult, "Adding the tool to the tooltip failed\n"); 216 217 /* Make tooltip appear quickly */ 218 SendMessageA(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0)); 219 220 /* Put cursor inside window, tooltip will appear immediately */ 221 GetWindowRect( parent, &rect ); 222 SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 ); 223 flush_events(200); 224 225 if (CD_Stages) 226 { 227 /* Check CustomDraw results */ 228 ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls || 229 broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */ 230 "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages, 231 expectedResults[iterationNumber].ExpectedCalls); 232 } 233 234 /* Clean up */ 235 DestroyWindow(hwndTip); 236 DestroyWindow(parent); 237 } 238 239 SetCursorPos(orig_pos.x, orig_pos.y); 240 } 241 242 static const CHAR testcallbackA[] = "callback"; 243 244 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 245 { 246 if (message == WM_NOTIFY && lParam) 247 { 248 NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam; 249 250 if (ttnmdi->hdr.code == TTN_GETDISPINFOA) 251 lstrcpyA(ttnmdi->lpszText, testcallbackA); 252 } 253 254 return DefWindowProcA(hwnd, message, wParam, lParam); 255 } 256 257 static BOOL register_parent_wnd_class(void) 258 { 259 WNDCLASSA cls; 260 261 cls.style = 0; 262 cls.lpfnWndProc = parent_wnd_proc; 263 cls.cbClsExtra = 0; 264 cls.cbWndExtra = 0; 265 cls.hInstance = GetModuleHandleA(NULL); 266 cls.hIcon = 0; 267 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 268 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 269 cls.lpszMenuName = NULL; 270 cls.lpszClassName = "Tooltips test parent class"; 271 return RegisterClassA(&cls); 272 } 273 274 static HWND create_parent_window(void) 275 { 276 if (!register_parent_wnd_class()) 277 return NULL; 278 279 return CreateWindowExA(0, "Tooltips test parent class", 280 "Tooltips test parent window", 281 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 282 WS_MAXIMIZEBOX | WS_VISIBLE, 283 0, 0, 100, 100, 284 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL); 285 } 286 287 static void test_gettext(void) 288 { 289 static const CHAR testtip2A[] = "testtip\ttest2"; 290 static const CHAR testtipA[] = "testtip"; 291 HWND hwnd, notify; 292 TTTOOLINFOA toolinfoA; 293 TTTOOLINFOW toolinfoW; 294 LRESULT r; 295 CHAR bufA[16] = ""; 296 WCHAR bufW[10] = { 0 }; 297 DWORD length, style; 298 299 notify = create_parent_window(); 300 ok(notify != NULL, "Expected notification window to be created\n"); 301 302 /* For bug 14790 - lpszText is NULL */ 303 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 304 10, 10, 300, 100, 305 NULL, NULL, NULL, 0); 306 ok(hwnd != NULL, "failed to create tooltip wnd\n"); 307 308 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */ 309 /* otherwise it crashes on the NULL lpszText */ 310 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 311 toolinfoA.hwnd = NULL; 312 toolinfoA.hinst = GetModuleHandleA(NULL); 313 toolinfoA.uFlags = 0; 314 toolinfoA.uId = 0x1234ABCD; 315 toolinfoA.lpszText = NULL; 316 toolinfoA.lParam = 0xdeadbeef; 317 GetClientRect(hwnd, &toolinfoA.rect); 318 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 319 ok(r, "got %ld\n", r); 320 321 toolinfoA.hwnd = NULL; 322 toolinfoA.uId = 0x1234abcd; 323 toolinfoA.lpszText = bufA; 324 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 325 ok(!r, "got %ld\n", r); 326 ok(!*toolinfoA.lpszText, "lpszText should be empty, got %s\n", toolinfoA.lpszText); 327 328 toolinfoA.lpszText = bufA; 329 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA); 330 todo_wine 331 ok(!r, "got %ld\n", r); 332 ok(toolinfoA.lpszText == NULL, "expected NULL, got %p\n", toolinfoA.lpszText); 333 334 /* NULL hinst, valid resource id for text */ 335 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 336 toolinfoA.hwnd = NULL; 337 toolinfoA.hinst = NULL; 338 toolinfoA.uFlags = 0; 339 toolinfoA.uId = 0x1233abcd; 340 toolinfoA.lpszText = MAKEINTRESOURCEA(IDS_TBADD1); 341 toolinfoA.lParam = 0xdeadbeef; 342 GetClientRect(hwnd, &toolinfoA.rect); 343 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 344 ok(r, "failed to add a tool\n"); 345 346 toolinfoA.hwnd = NULL; 347 toolinfoA.uId = 0x1233abcd; 348 toolinfoA.lpszText = bufA; 349 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 350 ok(!r, "got %ld\n", r); 351 ok(!strcmp(toolinfoA.lpszText, "abc"), "got wrong text, %s\n", toolinfoA.lpszText); 352 353 toolinfoA.hinst = (HINSTANCE)0xdeadbee; 354 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA); 355 todo_wine 356 ok(!r, "got %ld\n", r); 357 ok(toolinfoA.hinst == NULL, "expected NULL, got %p\n", toolinfoA.hinst); 358 359 r = SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&toolinfoA); 360 ok(!r, "got %ld\n", r); 361 362 /* add another tool with text */ 363 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 364 toolinfoA.hwnd = NULL; 365 toolinfoA.hinst = GetModuleHandleA(NULL); 366 toolinfoA.uFlags = 0; 367 toolinfoA.uId = 0x1235ABCD; 368 strcpy(bufA, testtipA); 369 toolinfoA.lpszText = bufA; 370 toolinfoA.lParam = 0xdeadbeef; 371 GetClientRect(hwnd, &toolinfoA.rect); 372 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 373 ok(r, "Adding the tool to the tooltip failed\n"); 374 375 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0); 376 ok(length == 0, "Expected 0, got %d\n", length); 377 378 toolinfoA.hwnd = NULL; 379 toolinfoA.uId = 0x1235abcd; 380 toolinfoA.lpszText = bufA; 381 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 382 ok(!r, "got %ld\n", r); 383 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText); 384 385 memset(bufA, 0x1f, sizeof(bufA)); 386 toolinfoA.lpszText = bufA; 387 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA); 388 todo_wine 389 ok(!r, "got %ld\n", r); 390 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText); 391 392 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0); 393 ok(length == 0, "Expected 0, got %d\n", length); 394 395 /* add another with callback text */ 396 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 397 toolinfoA.hwnd = notify; 398 toolinfoA.hinst = GetModuleHandleA(NULL); 399 toolinfoA.uFlags = 0; 400 toolinfoA.uId = 0x1236ABCD; 401 toolinfoA.lpszText = LPSTR_TEXTCALLBACKA; 402 toolinfoA.lParam = 0xdeadbeef; 403 GetClientRect(hwnd, &toolinfoA.rect); 404 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 405 ok(r, "Adding the tool to the tooltip failed\n"); 406 407 toolinfoA.hwnd = notify; 408 toolinfoA.uId = 0x1236abcd; 409 toolinfoA.lpszText = bufA; 410 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 411 ok(!r, "got %ld\n", r); 412 ok(!strcmp(toolinfoA.lpszText, testcallbackA), "lpszText should be an (%s) string\n", testcallbackA); 413 414 toolinfoA.lpszText = bufA; 415 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA); 416 todo_wine 417 ok(!r, "got %ld\n", r); 418 ok(toolinfoA.lpszText == LPSTR_TEXTCALLBACKA, "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA.lpszText); 419 420 DestroyWindow(hwnd); 421 DestroyWindow(notify); 422 423 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0, 424 10, 10, 300, 100, 425 NULL, NULL, NULL, 0); 426 ok(hwnd != NULL, "failed to create tooltip wnd\n"); 427 428 toolinfoW.cbSize = sizeof(TTTOOLINFOW); 429 toolinfoW.hwnd = NULL; 430 toolinfoW.hinst = GetModuleHandleA(NULL); 431 toolinfoW.uFlags = 0; 432 toolinfoW.uId = 0x1234ABCD; 433 toolinfoW.lpszText = NULL; 434 toolinfoW.lParam = 0xdeadbeef; 435 GetClientRect(hwnd, &toolinfoW.rect); 436 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW); 437 ok(!r, "Adding the tool to the tooltip succeeded!\n"); 438 439 /* lpszText with an invalid address */ 440 toolinfoW.cbSize = sizeof(TTTOOLINFOW); 441 toolinfoW.hwnd = notify; 442 toolinfoW.hinst = GetModuleHandleA(NULL); 443 toolinfoW.uFlags = 0; 444 toolinfoW.uId = 0; 445 toolinfoW.lpszText = (LPWSTR)0xdeadbeef; 446 toolinfoW.lParam = 0; 447 GetClientRect(hwnd, &toolinfoW.rect); 448 r = SendMessageA(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW); 449 ok(!r, "Adding the tool to the tooltip succeeded!\n"); 450 451 /* lpszText with an invalid address. Crashes using TTTOOLINFOA message */ 452 if(0) 453 { 454 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 455 toolinfoA.hwnd = notify; 456 toolinfoA.hinst = GetModuleHandleA(NULL); 457 toolinfoA.uFlags = 0; 458 toolinfoA.uId = 0; 459 toolinfoA.lpszText = (LPSTR)0xdeadbeef; 460 toolinfoA.lParam = 0; 461 GetClientRect(hwnd, &toolinfoA.rect); 462 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 463 ok(!r, "Adding the tool to the tooltip succeeded!\n"); 464 } 465 466 if (0) /* crashes on NT4 */ 467 { 468 toolinfoW.hwnd = NULL; 469 toolinfoW.uId = 0x1234ABCD; 470 toolinfoW.lpszText = bufW; 471 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW); 472 ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n"); 473 } 474 475 /* text with embedded tabs */ 476 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 477 toolinfoA.hwnd = NULL; 478 toolinfoA.hinst = GetModuleHandleA(NULL); 479 toolinfoA.uFlags = 0; 480 toolinfoA.uId = 0x1235abce; 481 strcpy(bufA, testtip2A); 482 toolinfoA.lpszText = bufA; 483 toolinfoA.lParam = 0xdeadbeef; 484 GetClientRect(hwnd, &toolinfoA.rect); 485 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 486 ok(r, "got %ld\n", r); 487 488 toolinfoA.hwnd = NULL; 489 toolinfoA.uId = 0x1235abce; 490 toolinfoA.lpszText = bufA; 491 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 492 ok(!r, "got %ld\n", r); 493 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %s\n", testtipA, toolinfoA.lpszText); 494 495 /* enable TTS_NOPREFIX, original text is retained */ 496 style = GetWindowLongA(hwnd, GWL_STYLE); 497 SetWindowLongA(hwnd, GWL_STYLE, style | TTS_NOPREFIX); 498 499 toolinfoA.hwnd = NULL; 500 toolinfoA.uId = 0x1235abce; 501 toolinfoA.lpszText = bufA; 502 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 503 ok(!r, "got %ld\n", r); 504 ok(!strcmp(toolinfoA.lpszText, testtip2A), "expected %s, got %s\n", testtip2A, toolinfoA.lpszText); 505 506 DestroyWindow(hwnd); 507 } 508 509 static void test_ttm_gettoolinfo(void) 510 { 511 TTTOOLINFOA ti; 512 TTTOOLINFOW tiW; 513 HWND hwnd; 514 DWORD r; 515 516 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 517 10, 10, 300, 100, 518 NULL, NULL, NULL, 0); 519 520 ti.cbSize = TTTOOLINFOA_V2_SIZE; 521 ti.hwnd = NULL; 522 ti.hinst = GetModuleHandleA(NULL); 523 ti.uFlags = 0; 524 ti.uId = 0x1234ABCD; 525 ti.lpszText = NULL; 526 ti.lParam = 0x1abe11ed; 527 GetClientRect(hwnd, &ti.rect); 528 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 529 ok(r, "Adding the tool to the tooltip failed\n"); 530 531 ti.cbSize = TTTOOLINFOA_V2_SIZE; 532 ti.lParam = 0xaaaaaaaa; 533 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti); 534 ok(r, "Getting tooltip info failed\n"); 535 ok(0x1abe11ed == ti.lParam || 536 broken(0x1abe11ed != ti.lParam), /* comctl32 < 5.81 */ 537 "Expected 0x1abe11ed, got %lx\n", ti.lParam); 538 539 tiW.cbSize = TTTOOLINFOW_V2_SIZE; 540 tiW.hwnd = NULL; 541 tiW.uId = 0x1234ABCD; 542 tiW.lParam = 0xaaaaaaaa; 543 tiW.lpszText = NULL; 544 r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW); 545 ok(r, "Getting tooltip info failed\n"); 546 ok(0x1abe11ed == tiW.lParam || 547 broken(0x1abe11ed != tiW.lParam), /* comctl32 < 5.81 */ 548 "Expected 0x1abe11ed, got %lx\n", tiW.lParam); 549 550 ti.cbSize = TTTOOLINFOA_V2_SIZE; 551 ti.uId = 0x1234ABCD; 552 ti.lParam = 0x55555555; 553 SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti); 554 555 ti.cbSize = TTTOOLINFOA_V2_SIZE; 556 ti.lParam = 0xdeadbeef; 557 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti); 558 ok(r, "Getting tooltip info failed\n"); 559 ok(0x55555555 == ti.lParam || 560 broken(0x55555555 != ti.lParam), /* comctl32 < 5.81 */ 561 "Expected 0x55555555, got %lx\n", ti.lParam); 562 563 DestroyWindow(hwnd); 564 565 /* 1. test size parameter validation rules (ansi messages) */ 566 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 567 10, 10, 300, 100, 568 NULL, NULL, NULL, 0); 569 570 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1; 571 ti.hwnd = NULL; 572 ti.hinst = GetModuleHandleA(NULL); 573 ti.uFlags = 0; 574 ti.uId = 0x1234ABCD; 575 ti.lpszText = NULL; 576 ti.lParam = 0xdeadbeef; 577 GetClientRect(hwnd, &ti.rect); 578 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 579 ok(r, "Adding the tool to the tooltip failed\n"); 580 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 581 expect(1, r); 582 583 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1; 584 ti.hwnd = NULL; 585 ti.uId = 0x1234ABCD; 586 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti); 587 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 588 expect(0, r); 589 590 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1; 591 ti.hwnd = NULL; 592 ti.hinst = GetModuleHandleA(NULL); 593 ti.uFlags = 0; 594 ti.uId = 0x1234ABCD; 595 ti.lpszText = NULL; 596 ti.lParam = 0xdeadbeef; 597 GetClientRect(hwnd, &ti.rect); 598 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 599 ok(r, "Adding the tool to the tooltip failed\n"); 600 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 601 expect(1, r); 602 603 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1; 604 ti.hwnd = NULL; 605 ti.uId = 0x1234ABCD; 606 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti); 607 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 608 expect(0, r); 609 610 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1; 611 ti.hwnd = NULL; 612 ti.hinst = GetModuleHandleA(NULL); 613 ti.uFlags = 0; 614 ti.uId = 0x1234ABCD; 615 ti.lpszText = NULL; 616 ti.lParam = 0xdeadbeef; 617 GetClientRect(hwnd, &ti.rect); 618 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti); 619 ok(r, "Adding the tool to the tooltip failed\n"); 620 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 621 expect(1, r); 622 623 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1; 624 ti.hwnd = NULL; 625 ti.uId = 0x1234ABCD; 626 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti); 627 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0); 628 expect(0, r); 629 630 DestroyWindow(hwnd); 631 632 /* 2. test size parameter validation rules (w-messages) */ 633 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0, 634 10, 10, 300, 100, 635 NULL, NULL, NULL, 0); 636 if(!hwnd) 637 { 638 win_skip("CreateWindowExW() not supported. Skipping.\n"); 639 return; 640 } 641 642 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1; 643 tiW.hwnd = NULL; 644 tiW.hinst = GetModuleHandleA(NULL); 645 tiW.uFlags = 0; 646 tiW.uId = 0x1234ABCD; 647 tiW.lpszText = NULL; 648 tiW.lParam = 0xdeadbeef; 649 GetClientRect(hwnd, &tiW.rect); 650 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW); 651 ok(r, "Adding the tool to the tooltip failed\n"); 652 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 653 expect(1, r); 654 655 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1; 656 tiW.hwnd = NULL; 657 tiW.uId = 0x1234ABCD; 658 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW); 659 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 660 expect(0, r); 661 662 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1; 663 tiW.hwnd = NULL; 664 tiW.hinst = GetModuleHandleA(NULL); 665 tiW.uFlags = 0; 666 tiW.uId = 0x1234ABCD; 667 tiW.lpszText = NULL; 668 tiW.lParam = 0xdeadbeef; 669 GetClientRect(hwnd, &tiW.rect); 670 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW); 671 ok(r, "Adding the tool to the tooltip failed\n"); 672 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 673 expect(1, r); 674 675 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1; 676 tiW.hwnd = NULL; 677 tiW.uId = 0x1234ABCD; 678 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW); 679 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 680 expect(0, r); 681 682 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1; 683 tiW.hwnd = NULL; 684 tiW.hinst = GetModuleHandleA(NULL); 685 tiW.uFlags = 0; 686 tiW.uId = 0x1234ABCD; 687 tiW.lpszText = NULL; 688 tiW.lParam = 0xdeadbeef; 689 GetClientRect(hwnd, &tiW.rect); 690 r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW); 691 ok(r, "Adding the tool to the tooltip failed\n"); 692 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 693 expect(1, r); 694 /* looks like TTM_DELTOOLW doesn't work with invalid size */ 695 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1; 696 tiW.hwnd = NULL; 697 tiW.uId = 0x1234ABCD; 698 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW); 699 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 700 expect(1, r); 701 702 tiW.cbSize = TTTOOLINFOW_V2_SIZE; 703 tiW.hwnd = NULL; 704 tiW.uId = 0x1234ABCD; 705 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW); 706 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0); 707 expect(0, r); 708 709 DestroyWindow(hwnd); 710 } 711 712 static void test_longtextA(void) 713 { 714 static const char longtextA[] = 715 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum " 716 "80 chars including null. In fact, the buffer is not null-terminated."; 717 HWND hwnd; 718 TTTOOLINFOA toolinfoA = { 0 }; 719 CHAR bufA[256]; 720 LRESULT r; 721 722 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 723 10, 10, 300, 100, 724 NULL, NULL, NULL, 0); 725 toolinfoA.cbSize = sizeof(TTTOOLINFOA); 726 toolinfoA.hwnd = NULL; 727 toolinfoA.hinst = GetModuleHandleA(NULL); 728 toolinfoA.uFlags = 0; 729 toolinfoA.uId = 0x1234ABCD; 730 strcpy(bufA, longtextA); 731 toolinfoA.lpszText = bufA; 732 toolinfoA.lParam = 0xdeadbeef; 733 GetClientRect(hwnd, &toolinfoA.rect); 734 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA); 735 if (r) 736 { 737 int textlen; 738 memset(bufA, 0, sizeof(bufA)); 739 toolinfoA.hwnd = NULL; 740 toolinfoA.uId = 0xABCD1234; 741 toolinfoA.lpszText = bufA; 742 SendMessageA(hwnd, TTM_ENUMTOOLSA, 0, (LPARAM)&toolinfoA); 743 textlen = lstrlenA(toolinfoA.lpszText); 744 ok(textlen == 80, "lpszText has %d chars\n", textlen); 745 ok(toolinfoA.uId == 0x1234ABCD, 746 "uId should be retrieved, got %p\n", (void*)toolinfoA.uId); 747 748 memset(bufA, 0, sizeof(bufA)); 749 toolinfoA.hwnd = NULL; 750 toolinfoA.uId = 0x1234ABCD; 751 toolinfoA.lpszText = bufA; 752 SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA); 753 textlen = lstrlenA(toolinfoA.lpszText); 754 ok(textlen == 80, "lpszText has %d chars\n", textlen); 755 756 memset(bufA, 0, sizeof(bufA)); 757 toolinfoA.hwnd = NULL; 758 toolinfoA.uId = 0x1234ABCD; 759 toolinfoA.lpszText = bufA; 760 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA); 761 textlen = lstrlenA(toolinfoA.lpszText); 762 ok(textlen == 80, "lpszText has %d chars\n", textlen); 763 } 764 765 DestroyWindow(hwnd); 766 } 767 768 static void test_longtextW(void) 769 { 770 static const char longtextA[] = 771 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum " 772 "80 chars including null. Actually, this is not applied for wide version."; 773 HWND hwnd; 774 TTTOOLINFOW toolinfoW = { 0 }; 775 WCHAR bufW[256]; 776 LRESULT r; 777 int lenW; 778 779 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0, 780 10, 10, 300, 100, 781 NULL, NULL, NULL, 0); 782 if(!hwnd) 783 { 784 win_skip("CreateWindowExW() not supported. Skipping.\n"); 785 return; 786 } 787 788 toolinfoW.cbSize = TTTOOLINFOW_V2_SIZE; 789 toolinfoW.hwnd = NULL; 790 toolinfoW.hinst = GetModuleHandleW(NULL); 791 toolinfoW.uFlags = 0; 792 toolinfoW.uId = 0x1234ABCD; 793 MultiByteToWideChar(CP_ACP, 0, longtextA, -1, bufW, sizeof(bufW)/sizeof(bufW[0])); 794 lenW = lstrlenW(bufW); 795 toolinfoW.lpszText = bufW; 796 toolinfoW.lParam = 0xdeadbeef; 797 GetClientRect(hwnd, &toolinfoW.rect); 798 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW); 799 if (r) 800 { 801 int textlen; 802 memset(bufW, 0, sizeof(bufW)); 803 toolinfoW.hwnd = NULL; 804 toolinfoW.uId = 0xABCD1234; 805 toolinfoW.lpszText = bufW; 806 SendMessageW(hwnd, TTM_ENUMTOOLSW, 0, (LPARAM)&toolinfoW); 807 textlen = lstrlenW(toolinfoW.lpszText); 808 ok(textlen == lenW, "lpszText has %d chars\n", textlen); 809 ok(toolinfoW.uId == 0x1234ABCD, 810 "uId should be retrieved, got %p\n", (void*)toolinfoW.uId); 811 812 memset(bufW, 0, sizeof(bufW)); 813 toolinfoW.hwnd = NULL; 814 toolinfoW.uId = 0x1234ABCD; 815 toolinfoW.lpszText = bufW; 816 SendMessageW(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&toolinfoW); 817 textlen = lstrlenW(toolinfoW.lpszText); 818 ok(textlen == lenW, "lpszText has %d chars\n", textlen); 819 820 memset(bufW, 0, sizeof(bufW)); 821 toolinfoW.hwnd = NULL; 822 toolinfoW.uId = 0x1234ABCD; 823 toolinfoW.lpszText = bufW; 824 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW); 825 textlen = lstrlenW(toolinfoW.lpszText); 826 ok(textlen == lenW || 827 broken(textlen == 0 && toolinfoW.lpszText == NULL), /* nt4, kb186177 */ 828 "lpszText has %d chars\n", textlen); 829 } 830 831 DestroyWindow(hwnd); 832 } 833 834 static BOOL almost_eq(int a, int b) 835 { 836 return a-5<b && a+5>b; 837 } 838 839 static void test_track(void) 840 { 841 WCHAR textW[] = {'t','e','x','t',0}; 842 TTTOOLINFOW info = { 0 }; 843 HWND parent, tt; 844 LRESULT res; 845 RECT pos; 846 847 parent = CreateWindowExW(0, WC_STATICW, NULL, WS_CAPTION | WS_VISIBLE, 848 50, 50, 300, 300, NULL, NULL, NULL, 0); 849 ok(parent != NULL, "creation of parent window failed\n"); 850 851 ShowWindow(parent, SW_SHOWNORMAL); 852 flush_events(100); 853 854 tt = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, 855 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 856 parent, NULL, GetModuleHandleW(NULL), 0); 857 ok(tt != NULL, "creation of tooltip window failed\n"); 858 859 info.cbSize = TTTOOLINFOW_V1_SIZE; 860 info.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE; 861 info.hwnd = parent; 862 info.hinst = GetModuleHandleW(NULL); 863 info.lpszText = textW; 864 info.uId = (UINT_PTR)parent; 865 GetClientRect(parent, &info.rect); 866 867 res = SendMessageW(tt, TTM_ADDTOOLW, 0, (LPARAM)&info); 868 ok(res, "adding the tool to the tooltip failed\n"); 869 870 SendMessageW(tt, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0)); 871 SendMessageW(tt, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&info); 872 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10)); 873 874 GetWindowRect(tt, &pos); 875 ok(almost_eq(pos.left, 10), "pos.left = %d\n", pos.left); 876 ok(almost_eq(pos.top, 10), "pos.top = %d\n", pos.top); 877 878 info.uFlags = TTF_IDISHWND | TTF_ABSOLUTE; 879 SendMessageW(tt, TTM_SETTOOLINFOW, 0, (LPARAM)&info); 880 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10)); 881 882 GetWindowRect(tt, &pos); 883 ok(!almost_eq(pos.left, 10), "pos.left = %d\n", pos.left); 884 ok(!almost_eq(pos.top, 10), "pos.top = %d\n", pos.top); 885 886 DestroyWindow(tt); 887 DestroyWindow(parent); 888 } 889 890 static LRESULT CALLBACK info_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 891 { 892 switch(msg) { 893 894 case WM_DESTROY: 895 PostQuitMessage(0); 896 break; 897 898 default: 899 return DefWindowProcA(hWnd, msg, wParam, lParam); 900 } 901 return 0; 902 } 903 904 static void test_setinfo(void) 905 { 906 WNDCLASSA wc; 907 LRESULT lResult; 908 HWND parent, parent2, hwndTip, hwndTip2; 909 TTTOOLINFOA toolInfo = { 0 }; 910 TTTOOLINFOA toolInfo2 = { 0 }; 911 WNDPROC wndProc; 912 913 /* Create a class to use the custom draw wndproc */ 914 wc.style = CS_HREDRAW | CS_VREDRAW; 915 wc.cbClsExtra = 0; 916 wc.cbWndExtra = 0; 917 wc.hInstance = GetModuleHandleA(NULL); 918 wc.hIcon = NULL; 919 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW); 920 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW); 921 wc.lpszMenuName = NULL; 922 wc.lpszClassName = "SetInfoClass"; 923 wc.lpfnWndProc = info_wnd_proc; 924 RegisterClassA(&wc); 925 926 /* Create a main window */ 927 parent = CreateWindowExA(0, "SetInfoClass", NULL, 928 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 929 WS_MAXIMIZEBOX | WS_VISIBLE, 930 50, 50, 931 300, 300, 932 NULL, NULL, NULL, 0); 933 ok(parent != NULL, "Creation of main window failed\n"); 934 935 parent2 = CreateWindowExA(0, "SetInfoClass", NULL, 936 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 937 WS_MAXIMIZEBOX | WS_VISIBLE, 938 50, 50, 939 300, 300, 940 NULL, NULL, NULL, 0); 941 ok(parent2 != NULL, "Creation of main window failed\n"); 942 943 /* Make it show */ 944 ShowWindow(parent2, SW_SHOWNORMAL); 945 flush_events(100); 946 947 /* Create Tooltip */ 948 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, 949 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, 950 CW_USEDEFAULT, CW_USEDEFAULT, 951 CW_USEDEFAULT, CW_USEDEFAULT, 952 parent, NULL, GetModuleHandleA(NULL), 0); 953 ok(hwndTip != NULL, "Creation of tooltip window failed\n"); 954 955 hwndTip2 = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, 956 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP, 957 CW_USEDEFAULT, CW_USEDEFAULT, 958 CW_USEDEFAULT, CW_USEDEFAULT, 959 parent, NULL, GetModuleHandleA(NULL), 0); 960 ok(hwndTip2 != NULL, "Creation of tooltip window failed\n"); 961 962 963 /* Make it topmost, as per the MSDN */ 964 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0, 965 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 966 967 /* Create a tool */ 968 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; 969 toolInfo.hwnd = parent; 970 toolInfo.hinst = GetModuleHandleA(NULL); 971 toolInfo.uFlags = TTF_SUBCLASS; 972 toolInfo.uId = 0x1234ABCD; 973 toolInfo.lpszText = (LPSTR)"This is a test tooltip"; 974 toolInfo.lParam = 0xdeadbeef; 975 GetClientRect (parent, &toolInfo.rect); 976 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); 977 ok(lResult, "Adding the tool to the tooltip failed\n"); 978 979 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE; 980 toolInfo.hwnd = parent2; 981 toolInfo.hinst = GetModuleHandleA(NULL); 982 toolInfo.uFlags = 0; 983 toolInfo.uId = 0x1234ABCE; 984 toolInfo.lpszText = (LPSTR)"This is a test tooltip"; 985 toolInfo.lParam = 0xdeadbeef; 986 GetClientRect (parent, &toolInfo.rect); 987 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo); 988 ok(lResult, "Adding the tool to the tooltip failed\n"); 989 990 /* Try to Remove Subclass */ 991 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE; 992 toolInfo2.hwnd = parent; 993 toolInfo2.uId = 0x1234ABCD; 994 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); 995 ok(lResult, "GetToolInfo failed\n"); 996 ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n"); 997 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC); 998 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n"); 999 1000 toolInfo2.uFlags &= ~TTF_SUBCLASS; 1001 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2); 1002 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); 1003 ok(lResult, "GetToolInfo failed\n"); 1004 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n"); 1005 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC); 1006 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n"); 1007 1008 /* Try to Add Subclass */ 1009 1010 /* Make it topmost, as per the MSDN */ 1011 SetWindowPos(hwndTip2, HWND_TOPMOST, 0, 0, 0, 0, 1012 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 1013 1014 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE; 1015 toolInfo2.hwnd = parent2; 1016 toolInfo2.uId = 0x1234ABCE; 1017 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); 1018 ok(lResult, "GetToolInfo failed\n"); 1019 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n"); 1020 wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC); 1021 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n"); 1022 1023 toolInfo2.uFlags |= TTF_SUBCLASS; 1024 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2); 1025 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2); 1026 ok(lResult, "GetToolInfo failed\n"); 1027 ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n"); 1028 wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC); 1029 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n"); 1030 1031 /* Clean up */ 1032 DestroyWindow(hwndTip); 1033 DestroyWindow(hwndTip2); 1034 DestroyWindow(parent); 1035 DestroyWindow(parent2); 1036 } 1037 1038 static void test_margin(void) 1039 { 1040 RECT r, r1; 1041 HWND hwnd; 1042 DWORD ret; 1043 1044 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 1045 10, 10, 300, 100, 1046 NULL, NULL, NULL, 0); 1047 ok(hwnd != NULL, "failed to create tooltip wnd\n"); 1048 1049 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0); 1050 ok(!ret, "got %d\n", ret); 1051 1052 SetRect(&r, -1, -1, 1, 1); 1053 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, (LPARAM)&r); 1054 ok(!ret, "got %d\n", ret); 1055 1056 SetRectEmpty(&r1); 1057 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1); 1058 ok(!ret, "got %d\n", ret); 1059 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r)); 1060 1061 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0); 1062 ok(!ret, "got %d\n", ret); 1063 1064 SetRectEmpty(&r1); 1065 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1); 1066 ok(!ret, "got %d\n", ret); 1067 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r)); 1068 1069 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, 0); 1070 ok(!ret, "got %d\n", ret); 1071 1072 DestroyWindow(hwnd); 1073 } 1074 1075 START_TEST(tooltips) 1076 { 1077 InitCommonControls(); 1078 1079 test_create_tooltip(); 1080 test_customdraw(); 1081 test_gettext(); 1082 test_ttm_gettoolinfo(); 1083 test_longtextA(); 1084 test_longtextW(); 1085 test_track(); 1086 test_setinfo(); 1087 test_margin(); 1088 } 1089