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