[COMCTL32_WINETEST] Add a PCH.
[reactos.git] / modules / rostests / winetests / comctl32 / tooltips.c
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 }