ia2comproxy: Introduce new proxy stub DLL for IAccessible2.
[wine.git] / dlls / comctl32 / tests / tooltips.c
blobb6f3ace7285147f92d71393a1f3392e09089c0f1
1 /*
2 * Copyright 2005 Dmitry Timoshkov
3 * Copyright 2008 Jason Edmeades
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.
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.
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
20 #include <windows.h>
21 #include <commctrl.h>
23 #include "resources.h"
25 #include "wine/test.h"
27 #include "v6util.h"
28 #include "msg.h"
30 #define expect(expected, got) ok(got == expected, "Expected %d, got %ld\n", expected, got)
32 enum seq_index
34 PARENT_SEQ_INDEX = 0,
35 NUM_MSG_SEQUENCES
38 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
40 static void test_create_tooltip(BOOL is_v6)
42 HWND parent, hwnd;
43 DWORD style, exp_style;
45 parent = CreateWindowExA(0, "static", NULL, WS_POPUP,
46 0, 0, 0, 0,
47 NULL, NULL, NULL, 0);
48 ok(parent != NULL, "failed to create parent wnd\n");
50 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0x7fffffff | WS_POPUP,
51 10, 10, 300, 100,
52 parent, NULL, NULL, 0);
53 ok(hwnd != NULL, "failed to create tooltip wnd\n");
55 style = GetWindowLongA(hwnd, GWL_STYLE);
56 exp_style = 0x7fffffff | WS_POPUP;
57 exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME);
58 ok(style == exp_style, "wrong style %08lx/%08lx\n", style, exp_style);
60 DestroyWindow(hwnd);
62 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
63 10, 10, 300, 100,
64 parent, NULL, NULL, 0);
65 ok(hwnd != NULL, "failed to create tooltip wnd\n");
67 style = GetWindowLongA(hwnd, GWL_STYLE);
68 exp_style = WS_POPUP | WS_CLIPSIBLINGS;
69 if (!is_v6)
70 exp_style |= WS_BORDER;
71 todo_wine_if(is_v6)
72 ok(style == exp_style || broken(style == (exp_style | WS_BORDER)) /* XP */,
73 "Unexpected window style %#lx.\n", style);
75 DestroyWindow(hwnd);
77 DestroyWindow(parent);
80 /* try to make sure pending X events have been processed before continuing */
81 static void flush_events(int waitTime)
83 MSG msg;
84 int diff = waitTime;
85 DWORD time = GetTickCount() + waitTime;
87 while (diff > 0)
89 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min(100,diff), QS_ALLEVENTS) == WAIT_TIMEOUT) break;
90 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
91 diff = time - GetTickCount();
95 static int CD_Stages;
96 static LRESULT CD_Result;
97 static HWND g_hwnd;
99 #define TEST_CDDS_PREPAINT 0x00000001
100 #define TEST_CDDS_POSTPAINT 0x00000002
101 #define TEST_CDDS_PREERASE 0x00000004
102 #define TEST_CDDS_POSTERASE 0x00000008
103 #define TEST_CDDS_ITEMPREPAINT 0x00000010
104 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
105 #define TEST_CDDS_ITEMPREERASE 0x00000040
106 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
107 #define TEST_CDDS_SUBITEM 0x00000100
109 static LRESULT CALLBACK custom_draw_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
111 switch(msg) {
113 case WM_DESTROY:
114 PostQuitMessage(0);
115 break;
117 case WM_NOTIFY:
118 if (((NMHDR *)lParam)->code == NM_CUSTOMDRAW) {
119 NMTTCUSTOMDRAW *ttcd = (NMTTCUSTOMDRAW*) lParam;
120 ok(ttcd->nmcd.hdr.hwndFrom == g_hwnd, "Unexpected hwnd source %p (%p)\n",
121 ttcd->nmcd.hdr.hwndFrom, g_hwnd);
122 ok(ttcd->nmcd.hdr.idFrom == 0x1234ABCD, "Unexpected id %x\n", (int)ttcd->nmcd.hdr.idFrom);
124 switch (ttcd->nmcd.dwDrawStage) {
125 case CDDS_PREPAINT : CD_Stages |= TEST_CDDS_PREPAINT; break;
126 case CDDS_POSTPAINT : CD_Stages |= TEST_CDDS_POSTPAINT; break;
127 case CDDS_PREERASE : CD_Stages |= TEST_CDDS_PREERASE; break;
128 case CDDS_POSTERASE : CD_Stages |= TEST_CDDS_POSTERASE; break;
129 case CDDS_ITEMPREPAINT : CD_Stages |= TEST_CDDS_ITEMPREPAINT; break;
130 case CDDS_ITEMPOSTPAINT: CD_Stages |= TEST_CDDS_ITEMPOSTPAINT; break;
131 case CDDS_ITEMPREERASE : CD_Stages |= TEST_CDDS_ITEMPREERASE; break;
132 case CDDS_ITEMPOSTERASE: CD_Stages |= TEST_CDDS_ITEMPOSTERASE; break;
133 case CDDS_SUBITEM : CD_Stages |= TEST_CDDS_SUBITEM; break;
134 default: CD_Stages = -1;
137 if (ttcd->nmcd.dwDrawStage == CDDS_PREPAINT) return CD_Result;
139 /* drop through */
141 default:
142 return DefWindowProcA(hWnd, msg, wParam, lParam);
145 return 0L;
148 static void test_customdraw(void) {
149 static struct {
150 LRESULT FirstReturnValue;
151 int ExpectedCalls;
152 } expectedResults[] = {
153 /* Valid notification responses */
154 {CDRF_DODEFAULT, TEST_CDDS_PREPAINT},
155 {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT},
156 {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT},
158 /* Invalid notification responses */
159 {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
160 {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
161 {CDRF_NEWFONT, TEST_CDDS_PREPAINT}
164 DWORD iterationNumber;
165 WNDCLASSA wc;
166 POINT orig_pos;
167 LRESULT ret;
169 /* Create a class to use the custom draw wndproc */
170 wc.style = CS_HREDRAW | CS_VREDRAW;
171 wc.cbClsExtra = 0;
172 wc.cbWndExtra = 0;
173 wc.hInstance = GetModuleHandleA(NULL);
174 wc.hIcon = NULL;
175 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
176 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
177 wc.lpszMenuName = NULL;
178 wc.lpszClassName = "CustomDrawClass";
179 wc.lpfnWndProc = custom_draw_wnd_proc;
180 RegisterClassA(&wc);
182 GetCursorPos(&orig_pos);
184 for (iterationNumber = 0;
185 iterationNumber < ARRAY_SIZE(expectedResults);
186 iterationNumber++) {
188 HWND parent, hwndTip;
189 RECT rect;
190 TTTOOLINFOA toolInfo = { 0 };
191 winetest_push_context("%ld", iterationNumber);
193 /* Create a main window */
194 parent = CreateWindowExA(0, "CustomDrawClass", NULL,
195 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
196 WS_MAXIMIZEBOX | WS_VISIBLE,
197 50, 50,
198 300, 300,
199 NULL, NULL, NULL, 0);
200 ok(parent != NULL, "Creation of main window failed\n");
202 /* Make it show */
203 ShowWindow(parent, SW_SHOWNORMAL);
204 flush_events(100);
206 /* Create Tooltip */
207 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
208 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
209 CW_USEDEFAULT, CW_USEDEFAULT,
210 CW_USEDEFAULT, CW_USEDEFAULT,
211 parent, NULL, GetModuleHandleA(NULL), 0);
212 ok(hwndTip != NULL, "Creation of tooltip window failed\n");
214 /* Set up parms for the wndproc to handle */
215 CD_Stages = 0;
216 CD_Result = expectedResults[iterationNumber].FirstReturnValue;
217 g_hwnd = hwndTip;
219 /* Make it topmost, as per the MSDN */
220 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
221 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
223 /* Create a tool */
224 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
225 toolInfo.hwnd = parent;
226 toolInfo.hinst = GetModuleHandleA(NULL);
227 toolInfo.uFlags = TTF_SUBCLASS;
228 toolInfo.uId = 0x1234ABCD;
229 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
230 toolInfo.lParam = 0xdeadbeef;
231 GetClientRect (parent, &toolInfo.rect);
232 ret = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
233 ok(ret, "Failed to add the tool.\n");
235 /* Make tooltip appear quickly */
236 SendMessageA(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
238 /* Put cursor inside window, tooltip will appear immediately */
239 GetWindowRect( parent, &rect );
240 SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
241 flush_events(200);
243 if (CD_Stages)
245 /* Check CustomDraw results */
246 ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls,
247 "CustomDraw stages %x, expected %x\n", CD_Stages,
248 expectedResults[iterationNumber].ExpectedCalls);
251 ret = SendMessageA(hwndTip, TTM_GETCURRENTTOOLA, 0, 0);
252 ok(ret, "Failed to get current tool %#Ix.\n", ret);
254 memset(&toolInfo, 0xcc, sizeof(toolInfo));
255 toolInfo.cbSize = sizeof(toolInfo);
256 toolInfo.lpszText = NULL;
257 toolInfo.lpReserved = (void *)0xdeadbeef;
258 SendMessageA(hwndTip, TTM_GETCURRENTTOOLA, 0, (LPARAM)&toolInfo);
259 ok(toolInfo.hwnd == parent, "Unexpected hwnd %p.\n", toolInfo.hwnd);
260 ok(toolInfo.hinst == GetModuleHandleA(NULL), "Unexpected hinst %p.\n", toolInfo.hinst);
261 ok(toolInfo.uId == 0x1234abcd, "Unexpected uId %Ix.\n", toolInfo.uId);
262 ok(toolInfo.lParam == 0, "Unexpected lParam %Ix.\n", toolInfo.lParam);
263 ok(toolInfo.lpReserved == (void *)0xdeadbeef, "Unexpected lpReserved %p.\n", toolInfo.lpReserved);
265 /* Clean up */
266 DestroyWindow(hwndTip);
267 DestroyWindow(parent);
268 winetest_pop_context();
271 SetCursorPos(orig_pos.x, orig_pos.y);
274 static const CHAR testcallbackA[] = "callback";
276 static RECT g_ttip_rect;
277 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
279 static LONG defwndproc_counter = 0;
280 struct message msg;
281 LRESULT ret;
283 if (message == WM_NOTIFY && lParam)
285 NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
286 NMHDR *hdr = (NMHDR *)lParam;
287 RECT rect;
289 if (hdr->code != NM_CUSTOMDRAW)
291 msg.message = message;
292 msg.flags = sent|wparam|lparam;
293 if (defwndproc_counter) msg.flags |= defwinproc;
294 msg.wParam = wParam;
295 msg.lParam = lParam;
296 msg.id = hdr->code;
297 add_message(sequences, PARENT_SEQ_INDEX, &msg);
300 switch (hdr->code)
302 case TTN_GETDISPINFOA:
303 lstrcpyA(ttnmdi->lpszText, testcallbackA);
304 break;
305 case TTN_SHOW:
306 GetWindowRect(hdr->hwndFrom, &rect);
307 ok(!EqualRect(&g_ttip_rect, &rect), "Unexpected window rectangle.\n");
308 break;
312 defwndproc_counter++;
313 if (IsWindowUnicode(hwnd))
314 ret = DefWindowProcW(hwnd, message, wParam, lParam);
315 else
316 ret = DefWindowProcA(hwnd, message, wParam, lParam);
317 defwndproc_counter--;
319 return ret;
322 static void register_parent_wnd_class(void)
324 WNDCLASSA cls;
325 BOOL ret;
327 cls.style = 0;
328 cls.lpfnWndProc = parent_wnd_proc;
329 cls.cbClsExtra = 0;
330 cls.cbWndExtra = 0;
331 cls.hInstance = GetModuleHandleA(NULL);
332 cls.hIcon = 0;
333 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
334 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
335 cls.lpszMenuName = NULL;
336 cls.lpszClassName = "Tooltips test parent class";
337 ret = RegisterClassA(&cls);
338 ok(ret, "Failed to register test parent class.\n");
341 static HWND create_parent_window(void)
343 return CreateWindowExA(0, "Tooltips test parent class",
344 "Tooltips test parent window",
345 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
346 WS_MAXIMIZEBOX | WS_VISIBLE,
347 0, 0, 100, 100,
348 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
351 static void test_gettext(void)
353 static const CHAR testtip2A[] = "testtip\ttest2";
354 static const CHAR testtipA[] = "testtip";
355 HWND hwnd, notify;
356 TTTOOLINFOA toolinfoA;
357 TTTOOLINFOW toolinfoW;
358 LRESULT r;
359 CHAR bufA[16] = "";
360 WCHAR bufW[10] = { 0 };
361 DWORD length, style;
363 notify = create_parent_window();
364 ok(notify != NULL, "Expected notification window to be created\n");
366 /* For bug 14790 - lpszText is NULL */
367 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
368 10, 10, 300, 100,
369 NULL, NULL, NULL, 0);
370 ok(hwnd != NULL, "failed to create tooltip wnd\n");
372 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
373 /* otherwise it crashes on the NULL lpszText */
374 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
375 toolinfoA.hwnd = NULL;
376 toolinfoA.hinst = GetModuleHandleA(NULL);
377 toolinfoA.uFlags = 0;
378 toolinfoA.uId = 0x1234ABCD;
379 toolinfoA.lpszText = NULL;
380 toolinfoA.lParam = 0xdeadbeef;
381 GetClientRect(hwnd, &toolinfoA.rect);
382 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
383 ok(r, "got %Id\n", r);
385 toolinfoA.hwnd = NULL;
386 toolinfoA.uId = 0x1234abcd;
387 toolinfoA.lpszText = bufA;
388 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
389 ok(!r, "got %Id\n", r);
390 ok(!*toolinfoA.lpszText, "lpszText should be empty, got %s\n", toolinfoA.lpszText);
392 toolinfoA.lpszText = bufA;
393 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
394 todo_wine
395 ok(!r, "got %Id\n", r);
396 ok(toolinfoA.lpszText == NULL, "expected NULL, got %p\n", toolinfoA.lpszText);
398 /* NULL hinst, valid resource id for text */
399 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
400 toolinfoA.hwnd = NULL;
401 toolinfoA.hinst = NULL;
402 toolinfoA.uFlags = 0;
403 toolinfoA.uId = 0x1233abcd;
404 toolinfoA.lpszText = MAKEINTRESOURCEA(IDS_TBADD1);
405 toolinfoA.lParam = 0xdeadbeef;
406 GetClientRect(hwnd, &toolinfoA.rect);
407 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
408 ok(r, "failed to add a tool\n");
410 toolinfoA.hwnd = NULL;
411 toolinfoA.uId = 0x1233abcd;
412 toolinfoA.lpszText = bufA;
413 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
414 ok(!r, "got %Id\n", r);
415 ok(!strcmp(toolinfoA.lpszText, "abc"), "got wrong text, %s\n", toolinfoA.lpszText);
417 toolinfoA.hinst = (HINSTANCE)0xdeadbee;
418 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
419 todo_wine
420 ok(!r, "got %Id\n", r);
421 ok(toolinfoA.hinst == NULL, "expected NULL, got %p\n", toolinfoA.hinst);
423 r = SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&toolinfoA);
424 ok(!r, "got %Id\n", r);
426 /* add another tool with text */
427 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
428 toolinfoA.hwnd = NULL;
429 toolinfoA.hinst = GetModuleHandleA(NULL);
430 toolinfoA.uFlags = 0;
431 toolinfoA.uId = 0x1235ABCD;
432 strcpy(bufA, testtipA);
433 toolinfoA.lpszText = bufA;
434 toolinfoA.lParam = 0xdeadbeef;
435 GetClientRect(hwnd, &toolinfoA.rect);
436 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
437 ok(r, "Adding the tool to the tooltip failed\n");
439 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0);
440 ok(length == 0, "Expected 0, got %ld\n", length);
442 toolinfoA.hwnd = NULL;
443 toolinfoA.uId = 0x1235abcd;
444 toolinfoA.lpszText = bufA;
445 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
446 ok(!r, "got %Id\n", r);
447 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText);
449 memset(bufA, 0x1f, sizeof(bufA));
450 toolinfoA.lpszText = bufA;
451 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
452 todo_wine
453 ok(!r, "got %Id\n", r);
454 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText);
456 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0);
457 ok(length == 0, "Expected 0, got %ld\n", length);
459 /* add another with callback text */
460 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
461 toolinfoA.hwnd = notify;
462 toolinfoA.hinst = GetModuleHandleA(NULL);
463 toolinfoA.uFlags = 0;
464 toolinfoA.uId = 0x1236ABCD;
465 toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
466 toolinfoA.lParam = 0xdeadbeef;
467 GetClientRect(hwnd, &toolinfoA.rect);
468 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
469 ok(r, "Adding the tool to the tooltip failed\n");
471 toolinfoA.hwnd = notify;
472 toolinfoA.uId = 0x1236abcd;
473 toolinfoA.lpszText = bufA;
474 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
475 ok(!r, "got %Id\n", r);
476 ok(!strcmp(toolinfoA.lpszText, testcallbackA), "lpszText should be an (%s) string\n", testcallbackA);
478 toolinfoA.lpszText = bufA;
479 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
480 todo_wine
481 ok(!r, "got %Id\n", r);
482 ok(toolinfoA.lpszText == LPSTR_TEXTCALLBACKA, "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA.lpszText);
484 DestroyWindow(hwnd);
485 DestroyWindow(notify);
487 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
488 10, 10, 300, 100,
489 NULL, NULL, NULL, 0);
490 ok(hwnd != NULL, "failed to create tooltip wnd\n");
492 toolinfoW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
493 toolinfoW.hwnd = NULL;
494 toolinfoW.hinst = GetModuleHandleA(NULL);
495 toolinfoW.uFlags = 0;
496 toolinfoW.uId = 0x1234ABCD;
497 toolinfoW.lpszText = NULL;
498 toolinfoW.lParam = 0xdeadbeef;
499 GetClientRect(hwnd, &toolinfoW.rect);
500 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW);
501 /* Wine currently checks for V3 structure size, which matches what V6 control does.
502 Older implementation was never updated to support lpReserved field. */
503 todo_wine
504 ok(!r, "Adding the tool to the tooltip succeeded!\n");
506 toolinfoW.hwnd = NULL;
507 toolinfoW.uId = 0x1234ABCD;
508 toolinfoW.lpszText = bufW;
509 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
510 ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n");
512 /* text with embedded tabs */
513 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
514 toolinfoA.hwnd = NULL;
515 toolinfoA.hinst = GetModuleHandleA(NULL);
516 toolinfoA.uFlags = 0;
517 toolinfoA.uId = 0x1235abce;
518 strcpy(bufA, testtip2A);
519 toolinfoA.lpszText = bufA;
520 toolinfoA.lParam = 0xdeadbeef;
521 GetClientRect(hwnd, &toolinfoA.rect);
522 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
523 ok(r, "got %Id\n", r);
525 toolinfoA.hwnd = NULL;
526 toolinfoA.uId = 0x1235abce;
527 toolinfoA.lpszText = bufA;
528 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
529 ok(!r, "got %Id\n", r);
530 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %s\n", testtipA, toolinfoA.lpszText);
532 /* enable TTS_NOPREFIX, original text is retained */
533 style = GetWindowLongA(hwnd, GWL_STYLE);
534 SetWindowLongA(hwnd, GWL_STYLE, style | TTS_NOPREFIX);
536 toolinfoA.hwnd = NULL;
537 toolinfoA.uId = 0x1235abce;
538 toolinfoA.lpszText = bufA;
539 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
540 ok(!r, "got %Id\n", r);
541 ok(!strcmp(toolinfoA.lpszText, testtip2A), "expected %s, got %s\n", testtip2A, toolinfoA.lpszText);
543 DestroyWindow(hwnd);
546 static void test_ttm_gettoolinfo(void)
548 TTTOOLINFOA ti;
549 TTTOOLINFOW tiW;
550 HWND hwnd;
551 DWORD r;
553 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 10, 10, 300, 100, NULL, NULL, NULL, 0);
554 ok(hwnd != NULL, "Failed to create tooltip control.\n");
556 ti.cbSize = TTTOOLINFOA_V2_SIZE;
557 ti.hwnd = NULL;
558 ti.hinst = GetModuleHandleA(NULL);
559 ti.uFlags = 0;
560 ti.uId = 0x1234ABCD;
561 ti.lpszText = NULL;
562 ti.lParam = 0x1abe11ed;
563 GetClientRect(hwnd, &ti.rect);
564 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
565 ok(r, "Adding the tool to the tooltip failed\n");
567 ti.cbSize = TTTOOLINFOA_V2_SIZE;
568 ti.lParam = 0xaaaaaaaa;
569 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
570 ok(r, "Getting tooltip info failed\n");
571 ok(0x1abe11ed == ti.lParam, "Expected 0x1abe11ed, got %Ix\n", ti.lParam);
573 tiW.cbSize = TTTOOLINFOW_V2_SIZE;
574 tiW.hwnd = NULL;
575 tiW.uId = 0x1234ABCD;
576 tiW.lParam = 0xaaaaaaaa;
577 tiW.lpszText = NULL;
578 r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
579 ok(r, "Getting tooltip info failed\n");
580 ok(0x1abe11ed == tiW.lParam, "Expected 0x1abe11ed, got %Ix\n", tiW.lParam);
582 ti.cbSize = TTTOOLINFOA_V2_SIZE;
583 ti.uId = 0x1234ABCD;
584 ti.lParam = 0x55555555;
585 SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
587 ti.cbSize = TTTOOLINFOA_V2_SIZE;
588 ti.lParam = 0xdeadbeef;
589 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
590 ok(r, "Getting tooltip info failed\n");
591 ok(0x55555555 == ti.lParam, "Expected 0x55555555, got %Ix\n", ti.lParam);
593 DestroyWindow(hwnd);
595 /* 1. test size parameter validation rules (ansi messages) */
596 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
597 10, 10, 300, 100,
598 NULL, NULL, NULL, 0);
600 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
601 ti.hwnd = NULL;
602 ti.hinst = GetModuleHandleA(NULL);
603 ti.uFlags = 0;
604 ti.uId = 0x1234ABCD;
605 ti.lpszText = NULL;
606 ti.lParam = 0xdeadbeef;
607 GetClientRect(hwnd, &ti.rect);
608 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
609 ok(r, "Adding the tool to the tooltip failed\n");
610 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
611 expect(1, r);
613 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
614 ti.hwnd = NULL;
615 ti.uId = 0x1234ABCD;
616 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
617 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
618 expect(0, r);
620 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
621 ti.hwnd = NULL;
622 ti.hinst = GetModuleHandleA(NULL);
623 ti.uFlags = 0;
624 ti.uId = 0x1234ABCD;
625 ti.lpszText = NULL;
626 ti.lParam = 0xdeadbeef;
627 GetClientRect(hwnd, &ti.rect);
628 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
629 ok(r, "Adding the tool to the tooltip failed\n");
630 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
631 expect(1, r);
633 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
634 ti.hwnd = NULL;
635 ti.uId = 0x1234ABCD;
636 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
637 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
638 expect(0, r);
640 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
641 ti.hwnd = NULL;
642 ti.hinst = GetModuleHandleA(NULL);
643 ti.uFlags = 0;
644 ti.uId = 0x1234ABCD;
645 ti.lpszText = NULL;
646 ti.lParam = 0xdeadbeef;
647 GetClientRect(hwnd, &ti.rect);
648 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
649 ok(r, "Adding the tool to the tooltip failed\n");
650 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
651 expect(1, r);
653 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
654 ti.hwnd = NULL;
655 ti.uId = 0x1234ABCD;
656 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
657 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
658 expect(0, r);
660 DestroyWindow(hwnd);
662 /* 2. test size parameter validation rules (w-messages) */
663 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
664 10, 10, 300, 100,
665 NULL, NULL, NULL, 0);
666 ok(hwnd != NULL, "Failed to create tooltip window.\n");
668 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
669 tiW.hwnd = NULL;
670 tiW.hinst = GetModuleHandleA(NULL);
671 tiW.uFlags = 0;
672 tiW.uId = 0x1234ABCD;
673 tiW.lpszText = NULL;
674 tiW.lParam = 0xdeadbeef;
675 GetClientRect(hwnd, &tiW.rect);
676 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
677 ok(r, "Adding the tool to the tooltip failed\n");
678 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
679 expect(1, r);
681 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
682 tiW.hwnd = NULL;
683 tiW.uId = 0x1234ABCD;
684 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
685 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
686 expect(0, r);
688 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
689 tiW.hwnd = NULL;
690 tiW.hinst = GetModuleHandleA(NULL);
691 tiW.uFlags = 0;
692 tiW.uId = 0x1234ABCD;
693 tiW.lpszText = NULL;
694 tiW.lParam = 0xdeadbeef;
695 GetClientRect(hwnd, &tiW.rect);
696 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
697 ok(r, "Adding the tool to the tooltip failed\n");
698 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
699 expect(1, r);
701 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
702 tiW.hwnd = NULL;
703 tiW.uId = 0x1234ABCD;
704 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
705 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
706 expect(0, r);
708 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
709 tiW.hwnd = NULL;
710 tiW.hinst = GetModuleHandleA(NULL);
711 tiW.uFlags = 0;
712 tiW.uId = 0x1234ABCD;
713 tiW.lpszText = NULL;
714 tiW.lParam = 0xdeadbeef;
715 GetClientRect(hwnd, &tiW.rect);
716 r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
717 ok(r, "Adding the tool to the tooltip failed\n");
718 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
719 expect(1, r);
720 /* looks like TTM_DELTOOLW doesn't work with invalid size */
721 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
722 tiW.hwnd = NULL;
723 tiW.uId = 0x1234ABCD;
724 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
725 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
726 expect(1, r);
728 tiW.cbSize = TTTOOLINFOW_V2_SIZE;
729 tiW.hwnd = NULL;
730 tiW.uId = 0x1234ABCD;
731 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
732 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
733 expect(0, r);
735 DestroyWindow(hwnd);
738 static void test_longtextA(void)
740 static const char longtextA[] =
741 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
742 "80 chars including null. In fact, the buffer is not null-terminated.";
743 HWND hwnd;
744 TTTOOLINFOA toolinfoA = { 0 };
745 CHAR bufA[256];
746 LRESULT r;
748 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
749 10, 10, 300, 100,
750 NULL, NULL, NULL, 0);
751 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
752 toolinfoA.hwnd = NULL;
753 toolinfoA.hinst = GetModuleHandleA(NULL);
754 toolinfoA.uFlags = 0;
755 toolinfoA.uId = 0x1234ABCD;
756 strcpy(bufA, longtextA);
757 toolinfoA.lpszText = bufA;
758 toolinfoA.lParam = 0xdeadbeef;
759 GetClientRect(hwnd, &toolinfoA.rect);
760 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
761 if (r)
763 int textlen;
764 memset(bufA, 0, sizeof(bufA));
765 toolinfoA.hwnd = NULL;
766 toolinfoA.uId = 0xABCD1234;
767 toolinfoA.lpszText = bufA;
768 SendMessageA(hwnd, TTM_ENUMTOOLSA, 0, (LPARAM)&toolinfoA);
769 textlen = lstrlenA(toolinfoA.lpszText);
770 ok(textlen == 80, "lpszText has %d chars\n", textlen);
771 ok(toolinfoA.uId == 0x1234ABCD,
772 "uId should be retrieved, got %p\n", (void*)toolinfoA.uId);
774 memset(bufA, 0, sizeof(bufA));
775 toolinfoA.hwnd = NULL;
776 toolinfoA.uId = 0x1234ABCD;
777 toolinfoA.lpszText = bufA;
778 SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
779 textlen = lstrlenA(toolinfoA.lpszText);
780 ok(textlen == 80, "lpszText has %d chars\n", textlen);
782 memset(bufA, 0, sizeof(bufA));
783 toolinfoA.hwnd = NULL;
784 toolinfoA.uId = 0x1234ABCD;
785 toolinfoA.lpszText = bufA;
786 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
787 textlen = lstrlenA(toolinfoA.lpszText);
788 ok(textlen == 80, "lpszText has %d chars\n", textlen);
791 DestroyWindow(hwnd);
794 static void test_longtextW(void)
796 static const char longtextA[] =
797 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
798 "80 chars including null. Actually, this is not applied for wide version.";
799 HWND hwnd;
800 TTTOOLINFOW toolinfoW = { 0 };
801 WCHAR bufW[256];
802 LRESULT r;
803 int lenW;
805 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
806 10, 10, 300, 100,
807 NULL, NULL, NULL, 0);
808 ok(hwnd != NULL, "Failed to create tooltip window.\n");
810 toolinfoW.cbSize = TTTOOLINFOW_V2_SIZE;
811 toolinfoW.hwnd = NULL;
812 toolinfoW.hinst = GetModuleHandleW(NULL);
813 toolinfoW.uFlags = 0;
814 toolinfoW.uId = 0x1234ABCD;
815 MultiByteToWideChar(CP_ACP, 0, longtextA, -1, bufW, ARRAY_SIZE(bufW));
816 lenW = lstrlenW(bufW);
817 toolinfoW.lpszText = bufW;
818 toolinfoW.lParam = 0xdeadbeef;
819 GetClientRect(hwnd, &toolinfoW.rect);
820 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW);
821 if (r)
823 int textlen;
824 memset(bufW, 0, sizeof(bufW));
825 toolinfoW.hwnd = NULL;
826 toolinfoW.uId = 0xABCD1234;
827 toolinfoW.lpszText = bufW;
828 SendMessageW(hwnd, TTM_ENUMTOOLSW, 0, (LPARAM)&toolinfoW);
829 textlen = lstrlenW(toolinfoW.lpszText);
830 ok(textlen == lenW, "lpszText has %d chars\n", textlen);
831 ok(toolinfoW.uId == 0x1234ABCD,
832 "uId should be retrieved, got %p\n", (void*)toolinfoW.uId);
834 memset(bufW, 0, sizeof(bufW));
835 toolinfoW.hwnd = NULL;
836 toolinfoW.uId = 0x1234ABCD;
837 toolinfoW.lpszText = bufW;
838 SendMessageW(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&toolinfoW);
839 textlen = lstrlenW(toolinfoW.lpszText);
840 ok(textlen == lenW, "lpszText has %d chars\n", textlen);
842 memset(bufW, 0, sizeof(bufW));
843 toolinfoW.hwnd = NULL;
844 toolinfoW.uId = 0x1234ABCD;
845 toolinfoW.lpszText = bufW;
846 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
847 textlen = lstrlenW(toolinfoW.lpszText);
848 ok(textlen == lenW, "lpszText has %d chars\n", textlen);
851 DestroyWindow(hwnd);
854 static BOOL almost_eq(int a, int b)
856 return a-5<b && a+5>b;
859 static void test_track(void)
861 WCHAR textW[] = {'t','e','x','t',0};
862 TTTOOLINFOW info = { 0 };
863 HWND parent, tt;
864 LRESULT res;
865 RECT pos;
867 parent = CreateWindowExW(0, WC_STATICW, NULL, WS_CAPTION | WS_VISIBLE,
868 50, 50, 300, 300, NULL, NULL, NULL, 0);
869 ok(parent != NULL, "creation of parent window failed\n");
871 ShowWindow(parent, SW_SHOWNORMAL);
872 flush_events(100);
874 tt = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
875 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
876 parent, NULL, GetModuleHandleW(NULL), 0);
877 ok(tt != NULL, "creation of tooltip window failed\n");
879 info.cbSize = TTTOOLINFOW_V1_SIZE;
880 info.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
881 info.hwnd = parent;
882 info.hinst = GetModuleHandleW(NULL);
883 info.lpszText = textW;
884 info.uId = (UINT_PTR)parent;
885 GetClientRect(parent, &info.rect);
887 res = SendMessageW(tt, TTM_ADDTOOLW, 0, (LPARAM)&info);
888 ok(res, "adding the tool to the tooltip failed\n");
890 SendMessageW(tt, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
891 SendMessageW(tt, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&info);
892 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10));
894 GetWindowRect(tt, &pos);
895 ok(almost_eq(pos.left, 10), "pos.left = %ld\n", pos.left);
896 ok(almost_eq(pos.top, 10), "pos.top = %ld\n", pos.top);
898 info.uFlags = TTF_IDISHWND | TTF_ABSOLUTE;
899 SendMessageW(tt, TTM_SETTOOLINFOW, 0, (LPARAM)&info);
900 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10));
902 GetWindowRect(tt, &pos);
903 ok(!almost_eq(pos.left, 10), "pos.left = %ld\n", pos.left);
904 ok(!almost_eq(pos.top, 10), "pos.top = %ld\n", pos.top);
906 DestroyWindow(tt);
907 DestroyWindow(parent);
910 static LRESULT CALLBACK info_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
912 switch(msg) {
914 case WM_DESTROY:
915 PostQuitMessage(0);
916 break;
918 default:
919 return DefWindowProcA(hWnd, msg, wParam, lParam);
921 return 0;
924 static void test_setinfo(BOOL is_v6)
926 WNDCLASSA wc;
927 LRESULT lResult;
928 HWND parent, parent2, hwndTip, hwndTip2;
929 TTTOOLINFOA toolInfo = { 0 };
930 TTTOOLINFOA toolInfo2 = { 0 };
931 WNDPROC wndProc;
933 /* Create a class to use the custom draw wndproc */
934 wc.style = CS_HREDRAW | CS_VREDRAW;
935 wc.cbClsExtra = 0;
936 wc.cbWndExtra = 0;
937 wc.hInstance = GetModuleHandleA(NULL);
938 wc.hIcon = NULL;
939 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
940 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
941 wc.lpszMenuName = NULL;
942 wc.lpszClassName = "SetInfoClass";
943 wc.lpfnWndProc = info_wnd_proc;
944 RegisterClassA(&wc);
946 /* Create a main window */
947 parent = CreateWindowExA(0, "SetInfoClass", NULL,
948 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
949 WS_MAXIMIZEBOX | WS_VISIBLE,
950 50, 50,
951 300, 300,
952 NULL, NULL, NULL, 0);
953 ok(parent != NULL, "Creation of main window failed\n");
955 parent2 = CreateWindowExA(0, "SetInfoClass", NULL,
956 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
957 WS_MAXIMIZEBOX | WS_VISIBLE,
958 50, 50,
959 300, 300,
960 NULL, NULL, NULL, 0);
961 ok(parent2 != NULL, "Creation of main window failed\n");
963 /* Make it show */
964 ShowWindow(parent2, SW_SHOWNORMAL);
965 flush_events(100);
967 /* Create Tooltip */
968 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
969 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
970 CW_USEDEFAULT, CW_USEDEFAULT,
971 CW_USEDEFAULT, CW_USEDEFAULT,
972 parent, NULL, GetModuleHandleA(NULL), 0);
973 ok(hwndTip != NULL, "Creation of tooltip window failed\n");
975 hwndTip2 = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
976 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
977 CW_USEDEFAULT, CW_USEDEFAULT,
978 CW_USEDEFAULT, CW_USEDEFAULT,
979 parent, NULL, GetModuleHandleA(NULL), 0);
980 ok(hwndTip2 != NULL, "Creation of tooltip window failed\n");
983 /* Make it topmost, as per the MSDN */
984 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
985 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
987 /* Create a tool */
988 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
989 toolInfo.hwnd = parent;
990 toolInfo.hinst = GetModuleHandleA(NULL);
991 toolInfo.uFlags = TTF_SUBCLASS;
992 toolInfo.uId = 0x1234ABCD;
993 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
994 toolInfo.lParam = 0xdeadbeef;
995 GetClientRect (parent, &toolInfo.rect);
996 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
997 ok(lResult, "Adding the tool to the tooltip failed\n");
999 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
1000 toolInfo.hwnd = parent2;
1001 toolInfo.hinst = GetModuleHandleA(NULL);
1002 toolInfo.uFlags = 0;
1003 toolInfo.uId = 0x1234ABCE;
1004 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
1005 toolInfo.lParam = 0xdeadbeef;
1006 GetClientRect (parent, &toolInfo.rect);
1007 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
1008 ok(lResult, "Adding the tool to the tooltip failed\n");
1010 /* Try to Remove Subclass */
1011 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
1012 toolInfo2.hwnd = parent;
1013 toolInfo2.uId = 0x1234ABCD;
1014 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1015 ok(lResult, "GetToolInfo failed\n");
1016 ok(toolInfo2.uFlags & TTF_SUBCLASS || broken(is_v6 && !(toolInfo2.uFlags & TTF_SUBCLASS)) /* XP */,
1017 "uFlags does not have subclass\n");
1018 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
1019 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
1021 toolInfo2.uFlags &= ~TTF_SUBCLASS;
1022 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1023 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1024 ok(lResult, "GetToolInfo failed\n");
1025 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
1026 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
1027 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
1029 /* Try to Add Subclass */
1031 /* Make it topmost, as per the MSDN */
1032 SetWindowPos(hwndTip2, HWND_TOPMOST, 0, 0, 0, 0,
1033 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1035 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
1036 toolInfo2.hwnd = parent2;
1037 toolInfo2.uId = 0x1234ABCE;
1038 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1039 ok(lResult, "GetToolInfo failed\n");
1040 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
1041 wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC);
1042 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
1044 toolInfo2.uFlags |= TTF_SUBCLASS;
1045 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1046 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
1047 ok(lResult, "GetToolInfo failed\n");
1048 ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n");
1049 wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC);
1050 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
1052 /* Clean up */
1053 DestroyWindow(hwndTip);
1054 DestroyWindow(hwndTip2);
1055 DestroyWindow(parent);
1056 DestroyWindow(parent2);
1059 static void test_margin(void)
1061 RECT r, r1;
1062 HWND hwnd;
1063 DWORD ret;
1065 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1066 10, 10, 300, 100,
1067 NULL, NULL, NULL, 0);
1068 ok(hwnd != NULL, "failed to create tooltip wnd\n");
1070 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0);
1071 ok(!ret, "got %ld\n", ret);
1073 SetRect(&r, -1, -1, 1, 1);
1074 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, (LPARAM)&r);
1075 ok(!ret, "got %ld\n", ret);
1077 SetRectEmpty(&r1);
1078 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1);
1079 ok(!ret, "got %ld\n", ret);
1080 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r));
1082 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0);
1083 ok(!ret, "got %ld\n", ret);
1085 SetRectEmpty(&r1);
1086 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1);
1087 ok(!ret, "got %ld\n", ret);
1088 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r));
1090 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, 0);
1091 ok(!ret, "got %ld\n", ret);
1093 DestroyWindow(hwnd);
1096 static void test_TTM_ADDTOOL(BOOL is_v6)
1098 TTTOOLINFOW tiW;
1099 TTTOOLINFOA ti;
1100 int ret, size;
1101 HWND hwnd, parent;
1102 UINT max_size;
1104 parent = CreateWindowExA(0, "Static", NULL, WS_POPUP, 0, 0, 0, 0, NULL, NULL, NULL, 0);
1105 ok(parent != NULL, "failed to create parent wnd\n");
1107 hwnd = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
1108 0, 0, 100, 100, NULL, NULL, GetModuleHandleA(NULL), 0);
1109 ok(hwnd != NULL, "Failed to create tooltip window.\n");
1111 for (size = 0; size <= TTTOOLINFOW_V3_SIZE + 1; size++)
1113 ti.cbSize = size;
1114 ti.hwnd = NULL;
1115 ti.hinst = GetModuleHandleA(NULL);
1116 ti.uFlags = 0;
1117 ti.uId = 0x1234abce;
1118 ti.lpszText = (LPSTR)"Test";
1119 ti.lParam = 0xdeadbeef;
1120 GetClientRect(hwnd, &ti.rect);
1122 ret = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1123 ok(ret, "Failed to add a tool, size %d.\n", size);
1125 ret = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
1126 ok(ret == 1, "Unexpected tool count %d, size %d.\n", ret, size);
1128 ret = SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
1129 ok(!ret, "Unexpected ret value %d.\n", ret);
1131 ret = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
1132 ok(ret == 0, "Unexpected tool count %d, size %d.\n", ret, size);
1135 /* W variant checks cbSize. */
1136 max_size = is_v6 ? TTTOOLINFOW_V3_SIZE : TTTOOLINFOW_V2_SIZE;
1137 for (size = 0; size <= max_size + 1; size++)
1139 tiW.cbSize = size;
1140 tiW.hwnd = NULL;
1141 tiW.hinst = GetModuleHandleA(NULL);
1142 tiW.uFlags = 0;
1143 tiW.uId = 0x1234abce;
1144 tiW.lpszText = (LPWSTR)L"Test";
1145 tiW.lParam = 0xdeadbeef;
1146 GetClientRect(hwnd, &tiW.rect);
1148 ret = SendMessageA(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
1149 todo_wine_if(!is_v6 && size > max_size)
1150 ok(size <= max_size ? ret : !ret, "%d: Unexpected ret value %d, size %d, max size %d.\n", is_v6, ret, size, max_size);
1151 if (ret)
1153 ret = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
1154 ok(ret == 1, "Unexpected tool count %d.\n", ret);
1156 ret = SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&tiW);
1157 ok(!ret, "Unexpected ret value %d.\n", ret);
1159 ret = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
1160 ok(ret == 0, "Unexpected tool count %d.\n", ret);
1164 DestroyWindow(hwnd);
1167 static const struct message ttn_show_parent_seq[] =
1169 { WM_NOTIFY, sent|id, 0, 0, TTN_SHOW },
1170 { 0 }
1173 static void test_TTN_SHOW(void)
1175 HWND hwndTip, hwnd;
1176 TTTOOLINFOA ti;
1177 RECT rect;
1178 BOOL ret;
1180 hwnd = create_parent_window();
1181 ok(hwnd != NULL, "Failed to create parent window.\n");
1183 /* Put cursor outside the window */
1184 GetWindowRect(hwnd, &rect);
1185 SetCursorPos(rect.right + 200, 0);
1187 ShowWindow(hwnd, SW_SHOWNORMAL);
1188 flush_events(100);
1190 /* Create tooltip */
1191 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA, NULL, TTS_ALWAYSTIP, 10, 10, 300, 300,
1192 hwnd, NULL, NULL, 0);
1193 ok(hwndTip != NULL, "Failed to create tooltip window.\n");
1195 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1197 ti.cbSize = sizeof(TTTOOLINFOA);
1198 ti.hwnd = hwnd;
1199 ti.hinst = GetModuleHandleA(NULL);
1200 ti.uFlags = TTF_SUBCLASS;
1201 ti.uId = 0x1234abcd;
1202 ti.lpszText = (LPSTR)"This is a test tooltip";
1203 ti.lParam = 0xdeadbeef;
1204 GetClientRect(hwnd, &ti.rect);
1205 ret = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&ti);
1206 ok(ret, "Failed to add a tool.\n");
1208 /* Make tooltip appear quickly */
1209 SendMessageA(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1, 0));
1211 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1213 /* Put cursor inside window, tooltip will appear immediately */
1214 GetWindowRect(hwnd, &rect);
1215 SetCursorPos((rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2);
1216 flush_events(200);
1218 ok_sequence(sequences, PARENT_SEQ_INDEX, ttn_show_parent_seq, "TTN_SHOW parent seq", FALSE);
1220 DestroyWindow(hwndTip);
1221 DestroyWindow(hwnd);
1224 START_TEST(tooltips)
1226 ULONG_PTR ctx_cookie;
1227 HANDLE hCtx;
1229 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
1231 LoadLibraryA("comctl32.dll");
1233 register_parent_wnd_class();
1235 test_create_tooltip(FALSE);
1236 test_customdraw();
1237 test_gettext();
1238 test_ttm_gettoolinfo();
1239 test_longtextA();
1240 test_longtextW();
1241 test_track();
1242 test_setinfo(FALSE);
1243 test_margin();
1244 test_TTM_ADDTOOL(FALSE);
1245 test_TTN_SHOW();
1247 if (!load_v6_module(&ctx_cookie, &hCtx))
1248 return;
1250 test_create_tooltip(TRUE);
1251 test_customdraw();
1252 test_longtextW();
1253 test_track();
1254 test_setinfo(TRUE);
1255 test_margin();
1256 test_TTM_ADDTOOL(TRUE);
1257 test_TTN_SHOW();
1259 unload_v6_module(ctx_cookie, hCtx);