7564a11e4bccf98cf489110ff948187439380a09
[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 POINT orig_pos;
150 LRESULT ret;
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 ret = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
215 ok(ret, "Failed to add the tool.\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 ret = SendMessageA(hwndTip, TTM_GETCURRENTTOOLA, 0, 0);
235 ok(ret, "Failed to get current tool %#lx.\n", ret);
236
237 memset(&toolInfo, 0xcc, sizeof(toolInfo));
238 toolInfo.cbSize = sizeof(toolInfo);
239 toolInfo.lpszText = NULL;
240 toolInfo.lpReserved = (void *)0xdeadbeef;
241 SendMessageA(hwndTip, TTM_GETCURRENTTOOLA, 0, (LPARAM)&toolInfo);
242 ok(toolInfo.hwnd == parent, "Unexpected hwnd %p.\n", toolInfo.hwnd);
243 ok(toolInfo.hinst == GetModuleHandleA(NULL), "Unexpected hinst %p.\n", toolInfo.hinst);
244 ok(toolInfo.uId == 0x1234abcd, "Unexpected uId %lx.\n", toolInfo.uId);
245 ok(toolInfo.lParam == 0, "Unexpected lParam %lx.\n", toolInfo.lParam);
246 ok(toolInfo.lpReserved == (void *)0xdeadbeef, "Unexpected lpReserved %p.\n", toolInfo.lpReserved);
247
248 /* Clean up */
249 DestroyWindow(hwndTip);
250 DestroyWindow(parent);
251 }
252
253 SetCursorPos(orig_pos.x, orig_pos.y);
254 }
255
256 static const CHAR testcallbackA[] = "callback";
257
258 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
259 {
260 if (message == WM_NOTIFY && lParam)
261 {
262 NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
263
264 if (ttnmdi->hdr.code == TTN_GETDISPINFOA)
265 lstrcpyA(ttnmdi->lpszText, testcallbackA);
266 }
267
268 return DefWindowProcA(hwnd, message, wParam, lParam);
269 }
270
271 static BOOL register_parent_wnd_class(void)
272 {
273 WNDCLASSA cls;
274
275 cls.style = 0;
276 cls.lpfnWndProc = parent_wnd_proc;
277 cls.cbClsExtra = 0;
278 cls.cbWndExtra = 0;
279 cls.hInstance = GetModuleHandleA(NULL);
280 cls.hIcon = 0;
281 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
282 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
283 cls.lpszMenuName = NULL;
284 cls.lpszClassName = "Tooltips test parent class";
285 return RegisterClassA(&cls);
286 }
287
288 static HWND create_parent_window(void)
289 {
290 if (!register_parent_wnd_class())
291 return NULL;
292
293 return CreateWindowExA(0, "Tooltips test parent class",
294 "Tooltips test parent window",
295 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
296 WS_MAXIMIZEBOX | WS_VISIBLE,
297 0, 0, 100, 100,
298 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
299 }
300
301 static void test_gettext(void)
302 {
303 static const CHAR testtip2A[] = "testtip\ttest2";
304 static const CHAR testtipA[] = "testtip";
305 HWND hwnd, notify;
306 TTTOOLINFOA toolinfoA;
307 TTTOOLINFOW toolinfoW;
308 LRESULT r;
309 CHAR bufA[16] = "";
310 WCHAR bufW[10] = { 0 };
311 DWORD length, style;
312
313 notify = create_parent_window();
314 ok(notify != NULL, "Expected notification window to be created\n");
315
316 /* For bug 14790 - lpszText is NULL */
317 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
318 10, 10, 300, 100,
319 NULL, NULL, NULL, 0);
320 ok(hwnd != NULL, "failed to create tooltip wnd\n");
321
322 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
323 /* otherwise it crashes on the NULL lpszText */
324 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
325 toolinfoA.hwnd = NULL;
326 toolinfoA.hinst = GetModuleHandleA(NULL);
327 toolinfoA.uFlags = 0;
328 toolinfoA.uId = 0x1234ABCD;
329 toolinfoA.lpszText = NULL;
330 toolinfoA.lParam = 0xdeadbeef;
331 GetClientRect(hwnd, &toolinfoA.rect);
332 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
333 ok(r, "got %ld\n", r);
334
335 toolinfoA.hwnd = NULL;
336 toolinfoA.uId = 0x1234abcd;
337 toolinfoA.lpszText = bufA;
338 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
339 ok(!r, "got %ld\n", r);
340 ok(!*toolinfoA.lpszText, "lpszText should be empty, got %s\n", toolinfoA.lpszText);
341
342 toolinfoA.lpszText = bufA;
343 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
344 todo_wine
345 ok(!r, "got %ld\n", r);
346 ok(toolinfoA.lpszText == NULL, "expected NULL, got %p\n", toolinfoA.lpszText);
347
348 /* NULL hinst, valid resource id for text */
349 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
350 toolinfoA.hwnd = NULL;
351 toolinfoA.hinst = NULL;
352 toolinfoA.uFlags = 0;
353 toolinfoA.uId = 0x1233abcd;
354 toolinfoA.lpszText = MAKEINTRESOURCEA(IDS_TBADD1);
355 toolinfoA.lParam = 0xdeadbeef;
356 GetClientRect(hwnd, &toolinfoA.rect);
357 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
358 ok(r, "failed to add a tool\n");
359
360 toolinfoA.hwnd = NULL;
361 toolinfoA.uId = 0x1233abcd;
362 toolinfoA.lpszText = bufA;
363 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
364 ok(!r, "got %ld\n", r);
365 ok(!strcmp(toolinfoA.lpszText, "abc"), "got wrong text, %s\n", toolinfoA.lpszText);
366
367 toolinfoA.hinst = (HINSTANCE)0xdeadbee;
368 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
369 todo_wine
370 ok(!r, "got %ld\n", r);
371 ok(toolinfoA.hinst == NULL, "expected NULL, got %p\n", toolinfoA.hinst);
372
373 r = SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&toolinfoA);
374 ok(!r, "got %ld\n", r);
375
376 /* add another tool with text */
377 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
378 toolinfoA.hwnd = NULL;
379 toolinfoA.hinst = GetModuleHandleA(NULL);
380 toolinfoA.uFlags = 0;
381 toolinfoA.uId = 0x1235ABCD;
382 strcpy(bufA, testtipA);
383 toolinfoA.lpszText = bufA;
384 toolinfoA.lParam = 0xdeadbeef;
385 GetClientRect(hwnd, &toolinfoA.rect);
386 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
387 ok(r, "Adding the tool to the tooltip failed\n");
388
389 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0);
390 ok(length == 0, "Expected 0, got %d\n", length);
391
392 toolinfoA.hwnd = NULL;
393 toolinfoA.uId = 0x1235abcd;
394 toolinfoA.lpszText = bufA;
395 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
396 ok(!r, "got %ld\n", r);
397 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText);
398
399 memset(bufA, 0x1f, sizeof(bufA));
400 toolinfoA.lpszText = bufA;
401 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
402 todo_wine
403 ok(!r, "got %ld\n", r);
404 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %p\n", testtipA, toolinfoA.lpszText);
405
406 length = SendMessageA(hwnd, WM_GETTEXTLENGTH, 0, 0);
407 ok(length == 0, "Expected 0, got %d\n", length);
408
409 /* add another with callback text */
410 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
411 toolinfoA.hwnd = notify;
412 toolinfoA.hinst = GetModuleHandleA(NULL);
413 toolinfoA.uFlags = 0;
414 toolinfoA.uId = 0x1236ABCD;
415 toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
416 toolinfoA.lParam = 0xdeadbeef;
417 GetClientRect(hwnd, &toolinfoA.rect);
418 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
419 ok(r, "Adding the tool to the tooltip failed\n");
420
421 toolinfoA.hwnd = notify;
422 toolinfoA.uId = 0x1236abcd;
423 toolinfoA.lpszText = bufA;
424 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
425 ok(!r, "got %ld\n", r);
426 ok(!strcmp(toolinfoA.lpszText, testcallbackA), "lpszText should be an (%s) string\n", testcallbackA);
427
428 toolinfoA.lpszText = bufA;
429 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
430 todo_wine
431 ok(!r, "got %ld\n", r);
432 ok(toolinfoA.lpszText == LPSTR_TEXTCALLBACKA, "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA.lpszText);
433
434 DestroyWindow(hwnd);
435 DestroyWindow(notify);
436
437 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
438 10, 10, 300, 100,
439 NULL, NULL, NULL, 0);
440 ok(hwnd != NULL, "failed to create tooltip wnd\n");
441
442 toolinfoW.cbSize = sizeof(TTTOOLINFOW);
443 toolinfoW.hwnd = NULL;
444 toolinfoW.hinst = GetModuleHandleA(NULL);
445 toolinfoW.uFlags = 0;
446 toolinfoW.uId = 0x1234ABCD;
447 toolinfoW.lpszText = NULL;
448 toolinfoW.lParam = 0xdeadbeef;
449 GetClientRect(hwnd, &toolinfoW.rect);
450 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW);
451 ok(!r, "Adding the tool to the tooltip succeeded!\n");
452
453 if (0) /* crashes on NT4 */
454 {
455 toolinfoW.hwnd = NULL;
456 toolinfoW.uId = 0x1234ABCD;
457 toolinfoW.lpszText = bufW;
458 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
459 ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n");
460 }
461
462 /* text with embedded tabs */
463 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
464 toolinfoA.hwnd = NULL;
465 toolinfoA.hinst = GetModuleHandleA(NULL);
466 toolinfoA.uFlags = 0;
467 toolinfoA.uId = 0x1235abce;
468 strcpy(bufA, testtip2A);
469 toolinfoA.lpszText = bufA;
470 toolinfoA.lParam = 0xdeadbeef;
471 GetClientRect(hwnd, &toolinfoA.rect);
472 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
473 ok(r, "got %ld\n", r);
474
475 toolinfoA.hwnd = NULL;
476 toolinfoA.uId = 0x1235abce;
477 toolinfoA.lpszText = bufA;
478 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
479 ok(!r, "got %ld\n", r);
480 ok(!strcmp(toolinfoA.lpszText, testtipA), "expected %s, got %s\n", testtipA, toolinfoA.lpszText);
481
482 /* enable TTS_NOPREFIX, original text is retained */
483 style = GetWindowLongA(hwnd, GWL_STYLE);
484 SetWindowLongA(hwnd, GWL_STYLE, style | TTS_NOPREFIX);
485
486 toolinfoA.hwnd = NULL;
487 toolinfoA.uId = 0x1235abce;
488 toolinfoA.lpszText = bufA;
489 r = SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
490 ok(!r, "got %ld\n", r);
491 ok(!strcmp(toolinfoA.lpszText, testtip2A), "expected %s, got %s\n", testtip2A, toolinfoA.lpszText);
492
493 DestroyWindow(hwnd);
494 }
495
496 static void test_ttm_gettoolinfo(void)
497 {
498 TTTOOLINFOA ti;
499 TTTOOLINFOW tiW;
500 HWND hwnd;
501 DWORD r;
502
503 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0, 10, 10, 300, 100, NULL, NULL, NULL, 0);
504 ok(hwnd != NULL, "Failed to create tooltip control.\n");
505
506 ti.cbSize = TTTOOLINFOA_V2_SIZE;
507 ti.hwnd = NULL;
508 ti.hinst = GetModuleHandleA(NULL);
509 ti.uFlags = 0;
510 ti.uId = 0x1234ABCD;
511 ti.lpszText = NULL;
512 ti.lParam = 0x1abe11ed;
513 GetClientRect(hwnd, &ti.rect);
514 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
515 ok(r, "Adding the tool to the tooltip failed\n");
516
517 ti.cbSize = TTTOOLINFOA_V2_SIZE;
518 ti.lParam = 0xaaaaaaaa;
519 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
520 ok(r, "Getting tooltip info failed\n");
521 ok(0x1abe11ed == ti.lParam ||
522 broken(0x1abe11ed != ti.lParam), /* comctl32 < 5.81 */
523 "Expected 0x1abe11ed, got %lx\n", ti.lParam);
524
525 tiW.cbSize = TTTOOLINFOW_V2_SIZE;
526 tiW.hwnd = NULL;
527 tiW.uId = 0x1234ABCD;
528 tiW.lParam = 0xaaaaaaaa;
529 tiW.lpszText = NULL;
530 r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
531 ok(r, "Getting tooltip info failed\n");
532 ok(0x1abe11ed == tiW.lParam ||
533 broken(0x1abe11ed != tiW.lParam), /* comctl32 < 5.81 */
534 "Expected 0x1abe11ed, got %lx\n", tiW.lParam);
535
536 ti.cbSize = TTTOOLINFOA_V2_SIZE;
537 ti.uId = 0x1234ABCD;
538 ti.lParam = 0x55555555;
539 SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
540
541 ti.cbSize = TTTOOLINFOA_V2_SIZE;
542 ti.lParam = 0xdeadbeef;
543 r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
544 ok(r, "Getting tooltip info failed\n");
545 ok(0x55555555 == ti.lParam ||
546 broken(0x55555555 != ti.lParam), /* comctl32 < 5.81 */
547 "Expected 0x55555555, got %lx\n", ti.lParam);
548
549 DestroyWindow(hwnd);
550
551 /* 1. test size parameter validation rules (ansi messages) */
552 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
553 10, 10, 300, 100,
554 NULL, NULL, NULL, 0);
555
556 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
557 ti.hwnd = NULL;
558 ti.hinst = GetModuleHandleA(NULL);
559 ti.uFlags = 0;
560 ti.uId = 0x1234ABCD;
561 ti.lpszText = NULL;
562 ti.lParam = 0xdeadbeef;
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");
566 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
567 expect(1, r);
568
569 ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
570 ti.hwnd = NULL;
571 ti.uId = 0x1234ABCD;
572 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
573 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
574 expect(0, r);
575
576 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
577 ti.hwnd = NULL;
578 ti.hinst = GetModuleHandleA(NULL);
579 ti.uFlags = 0;
580 ti.uId = 0x1234ABCD;
581 ti.lpszText = NULL;
582 ti.lParam = 0xdeadbeef;
583 GetClientRect(hwnd, &ti.rect);
584 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
585 ok(r, "Adding the tool to the tooltip failed\n");
586 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
587 expect(1, r);
588
589 ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
590 ti.hwnd = NULL;
591 ti.uId = 0x1234ABCD;
592 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
593 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
594 expect(0, r);
595
596 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
597 ti.hwnd = NULL;
598 ti.hinst = GetModuleHandleA(NULL);
599 ti.uFlags = 0;
600 ti.uId = 0x1234ABCD;
601 ti.lpszText = NULL;
602 ti.lParam = 0xdeadbeef;
603 GetClientRect(hwnd, &ti.rect);
604 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
605 ok(r, "Adding the tool to the tooltip failed\n");
606 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
607 expect(1, r);
608
609 ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
610 ti.hwnd = NULL;
611 ti.uId = 0x1234ABCD;
612 SendMessageA(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
613 r = SendMessageA(hwnd, TTM_GETTOOLCOUNT, 0, 0);
614 expect(0, r);
615
616 DestroyWindow(hwnd);
617
618 /* 2. test size parameter validation rules (w-messages) */
619 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
620 10, 10, 300, 100,
621 NULL, NULL, NULL, 0);
622 ok(hwnd != NULL, "Failed to create tooltip window.\n");
623
624 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
625 tiW.hwnd = NULL;
626 tiW.hinst = GetModuleHandleA(NULL);
627 tiW.uFlags = 0;
628 tiW.uId = 0x1234ABCD;
629 tiW.lpszText = NULL;
630 tiW.lParam = 0xdeadbeef;
631 GetClientRect(hwnd, &tiW.rect);
632 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
633 ok(r, "Adding the tool to the tooltip failed\n");
634 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
635 expect(1, r);
636
637 tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
638 tiW.hwnd = NULL;
639 tiW.uId = 0x1234ABCD;
640 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
641 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
642 expect(0, r);
643
644 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
645 tiW.hwnd = NULL;
646 tiW.hinst = GetModuleHandleA(NULL);
647 tiW.uFlags = 0;
648 tiW.uId = 0x1234ABCD;
649 tiW.lpszText = NULL;
650 tiW.lParam = 0xdeadbeef;
651 GetClientRect(hwnd, &tiW.rect);
652 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
653 ok(r, "Adding the tool to the tooltip failed\n");
654 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
655 expect(1, r);
656
657 tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
658 tiW.hwnd = NULL;
659 tiW.uId = 0x1234ABCD;
660 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
661 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
662 expect(0, r);
663
664 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
665 tiW.hwnd = NULL;
666 tiW.hinst = GetModuleHandleA(NULL);
667 tiW.uFlags = 0;
668 tiW.uId = 0x1234ABCD;
669 tiW.lpszText = NULL;
670 tiW.lParam = 0xdeadbeef;
671 GetClientRect(hwnd, &tiW.rect);
672 r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
673 ok(r, "Adding the tool to the tooltip failed\n");
674 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
675 expect(1, r);
676 /* looks like TTM_DELTOOLW doesn't work with invalid size */
677 tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
678 tiW.hwnd = NULL;
679 tiW.uId = 0x1234ABCD;
680 SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
681 r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
682 expect(1, r);
683
684 tiW.cbSize = TTTOOLINFOW_V2_SIZE;
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 DestroyWindow(hwnd);
692 }
693
694 static void test_longtextA(void)
695 {
696 static const char longtextA[] =
697 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
698 "80 chars including null. In fact, the buffer is not null-terminated.";
699 HWND hwnd;
700 TTTOOLINFOA toolinfoA = { 0 };
701 CHAR bufA[256];
702 LRESULT r;
703
704 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
705 10, 10, 300, 100,
706 NULL, NULL, NULL, 0);
707 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
708 toolinfoA.hwnd = NULL;
709 toolinfoA.hinst = GetModuleHandleA(NULL);
710 toolinfoA.uFlags = 0;
711 toolinfoA.uId = 0x1234ABCD;
712 strcpy(bufA, longtextA);
713 toolinfoA.lpszText = bufA;
714 toolinfoA.lParam = 0xdeadbeef;
715 GetClientRect(hwnd, &toolinfoA.rect);
716 r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&toolinfoA);
717 if (r)
718 {
719 int textlen;
720 memset(bufA, 0, sizeof(bufA));
721 toolinfoA.hwnd = NULL;
722 toolinfoA.uId = 0xABCD1234;
723 toolinfoA.lpszText = bufA;
724 SendMessageA(hwnd, TTM_ENUMTOOLSA, 0, (LPARAM)&toolinfoA);
725 textlen = lstrlenA(toolinfoA.lpszText);
726 ok(textlen == 80, "lpszText has %d chars\n", textlen);
727 ok(toolinfoA.uId == 0x1234ABCD,
728 "uId should be retrieved, got %p\n", (void*)toolinfoA.uId);
729
730 memset(bufA, 0, sizeof(bufA));
731 toolinfoA.hwnd = NULL;
732 toolinfoA.uId = 0x1234ABCD;
733 toolinfoA.lpszText = bufA;
734 SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&toolinfoA);
735 textlen = lstrlenA(toolinfoA.lpszText);
736 ok(textlen == 80, "lpszText has %d chars\n", textlen);
737
738 memset(bufA, 0, sizeof(bufA));
739 toolinfoA.hwnd = NULL;
740 toolinfoA.uId = 0x1234ABCD;
741 toolinfoA.lpszText = bufA;
742 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
743 textlen = lstrlenA(toolinfoA.lpszText);
744 ok(textlen == 80, "lpszText has %d chars\n", textlen);
745 }
746
747 DestroyWindow(hwnd);
748 }
749
750 static void test_longtextW(void)
751 {
752 static const char longtextA[] =
753 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
754 "80 chars including null. Actually, this is not applied for wide version.";
755 HWND hwnd;
756 TTTOOLINFOW toolinfoW = { 0 };
757 WCHAR bufW[256];
758 LRESULT r;
759 int lenW;
760
761 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
762 10, 10, 300, 100,
763 NULL, NULL, NULL, 0);
764 ok(hwnd != NULL, "Failed to create tooltip window.\n");
765
766 toolinfoW.cbSize = TTTOOLINFOW_V2_SIZE;
767 toolinfoW.hwnd = NULL;
768 toolinfoW.hinst = GetModuleHandleW(NULL);
769 toolinfoW.uFlags = 0;
770 toolinfoW.uId = 0x1234ABCD;
771 MultiByteToWideChar(CP_ACP, 0, longtextA, -1, bufW, sizeof(bufW)/sizeof(bufW[0]));
772 lenW = lstrlenW(bufW);
773 toolinfoW.lpszText = bufW;
774 toolinfoW.lParam = 0xdeadbeef;
775 GetClientRect(hwnd, &toolinfoW.rect);
776 r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&toolinfoW);
777 if (r)
778 {
779 int textlen;
780 memset(bufW, 0, sizeof(bufW));
781 toolinfoW.hwnd = NULL;
782 toolinfoW.uId = 0xABCD1234;
783 toolinfoW.lpszText = bufW;
784 SendMessageW(hwnd, TTM_ENUMTOOLSW, 0, (LPARAM)&toolinfoW);
785 textlen = lstrlenW(toolinfoW.lpszText);
786 ok(textlen == lenW, "lpszText has %d chars\n", textlen);
787 ok(toolinfoW.uId == 0x1234ABCD,
788 "uId should be retrieved, got %p\n", (void*)toolinfoW.uId);
789
790 memset(bufW, 0, sizeof(bufW));
791 toolinfoW.hwnd = NULL;
792 toolinfoW.uId = 0x1234ABCD;
793 toolinfoW.lpszText = bufW;
794 SendMessageW(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&toolinfoW);
795 textlen = lstrlenW(toolinfoW.lpszText);
796 ok(textlen == lenW, "lpszText has %d chars\n", textlen);
797
798 memset(bufW, 0, sizeof(bufW));
799 toolinfoW.hwnd = NULL;
800 toolinfoW.uId = 0x1234ABCD;
801 toolinfoW.lpszText = bufW;
802 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
803 textlen = lstrlenW(toolinfoW.lpszText);
804 ok(textlen == lenW ||
805 broken(textlen == 0 && toolinfoW.lpszText == NULL), /* nt4, kb186177 */
806 "lpszText has %d chars\n", textlen);
807 }
808
809 DestroyWindow(hwnd);
810 }
811
812 static BOOL almost_eq(int a, int b)
813 {
814 return a-5<b && a+5>b;
815 }
816
817 static void test_track(void)
818 {
819 WCHAR textW[] = {'t','e','x','t',0};
820 TTTOOLINFOW info = { 0 };
821 HWND parent, tt;
822 LRESULT res;
823 RECT pos;
824
825 parent = CreateWindowExW(0, WC_STATICW, NULL, WS_CAPTION | WS_VISIBLE,
826 50, 50, 300, 300, NULL, NULL, NULL, 0);
827 ok(parent != NULL, "creation of parent window failed\n");
828
829 ShowWindow(parent, SW_SHOWNORMAL);
830 flush_events(100);
831
832 tt = CreateWindowExW(WS_EX_TOPMOST, TOOLTIPS_CLASSW, NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
833 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
834 parent, NULL, GetModuleHandleW(NULL), 0);
835 ok(tt != NULL, "creation of tooltip window failed\n");
836
837 info.cbSize = TTTOOLINFOW_V1_SIZE;
838 info.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
839 info.hwnd = parent;
840 info.hinst = GetModuleHandleW(NULL);
841 info.lpszText = textW;
842 info.uId = (UINT_PTR)parent;
843 GetClientRect(parent, &info.rect);
844
845 res = SendMessageW(tt, TTM_ADDTOOLW, 0, (LPARAM)&info);
846 ok(res, "adding the tool to the tooltip failed\n");
847
848 SendMessageW(tt, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
849 SendMessageW(tt, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&info);
850 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10));
851
852 GetWindowRect(tt, &pos);
853 ok(almost_eq(pos.left, 10), "pos.left = %d\n", pos.left);
854 ok(almost_eq(pos.top, 10), "pos.top = %d\n", pos.top);
855
856 info.uFlags = TTF_IDISHWND | TTF_ABSOLUTE;
857 SendMessageW(tt, TTM_SETTOOLINFOW, 0, (LPARAM)&info);
858 SendMessageW(tt, TTM_TRACKPOSITION, 0, MAKELPARAM(10, 10));
859
860 GetWindowRect(tt, &pos);
861 ok(!almost_eq(pos.left, 10), "pos.left = %d\n", pos.left);
862 ok(!almost_eq(pos.top, 10), "pos.top = %d\n", pos.top);
863
864 DestroyWindow(tt);
865 DestroyWindow(parent);
866 }
867
868 static LRESULT CALLBACK info_wnd_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
869 {
870 switch(msg) {
871
872 case WM_DESTROY:
873 PostQuitMessage(0);
874 break;
875
876 default:
877 return DefWindowProcA(hWnd, msg, wParam, lParam);
878 }
879 return 0;
880 }
881
882 static void test_setinfo(void)
883 {
884 WNDCLASSA wc;
885 LRESULT lResult;
886 HWND parent, parent2, hwndTip, hwndTip2;
887 TTTOOLINFOA toolInfo = { 0 };
888 TTTOOLINFOA toolInfo2 = { 0 };
889 WNDPROC wndProc;
890
891 /* Create a class to use the custom draw wndproc */
892 wc.style = CS_HREDRAW | CS_VREDRAW;
893 wc.cbClsExtra = 0;
894 wc.cbWndExtra = 0;
895 wc.hInstance = GetModuleHandleA(NULL);
896 wc.hIcon = NULL;
897 wc.hCursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
898 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
899 wc.lpszMenuName = NULL;
900 wc.lpszClassName = "SetInfoClass";
901 wc.lpfnWndProc = info_wnd_proc;
902 RegisterClassA(&wc);
903
904 /* Create a main window */
905 parent = CreateWindowExA(0, "SetInfoClass", NULL,
906 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
907 WS_MAXIMIZEBOX | WS_VISIBLE,
908 50, 50,
909 300, 300,
910 NULL, NULL, NULL, 0);
911 ok(parent != NULL, "Creation of main window failed\n");
912
913 parent2 = CreateWindowExA(0, "SetInfoClass", NULL,
914 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
915 WS_MAXIMIZEBOX | WS_VISIBLE,
916 50, 50,
917 300, 300,
918 NULL, NULL, NULL, 0);
919 ok(parent2 != NULL, "Creation of main window failed\n");
920
921 /* Make it show */
922 ShowWindow(parent2, SW_SHOWNORMAL);
923 flush_events(100);
924
925 /* Create Tooltip */
926 hwndTip = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
927 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
928 CW_USEDEFAULT, CW_USEDEFAULT,
929 CW_USEDEFAULT, CW_USEDEFAULT,
930 parent, NULL, GetModuleHandleA(NULL), 0);
931 ok(hwndTip != NULL, "Creation of tooltip window failed\n");
932
933 hwndTip2 = CreateWindowExA(WS_EX_TOPMOST, TOOLTIPS_CLASSA,
934 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
935 CW_USEDEFAULT, CW_USEDEFAULT,
936 CW_USEDEFAULT, CW_USEDEFAULT,
937 parent, NULL, GetModuleHandleA(NULL), 0);
938 ok(hwndTip2 != NULL, "Creation of tooltip window failed\n");
939
940
941 /* Make it topmost, as per the MSDN */
942 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
943 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
944
945 /* Create a tool */
946 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
947 toolInfo.hwnd = parent;
948 toolInfo.hinst = GetModuleHandleA(NULL);
949 toolInfo.uFlags = TTF_SUBCLASS;
950 toolInfo.uId = 0x1234ABCD;
951 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
952 toolInfo.lParam = 0xdeadbeef;
953 GetClientRect (parent, &toolInfo.rect);
954 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
955 ok(lResult, "Adding the tool to the tooltip failed\n");
956
957 toolInfo.cbSize = TTTOOLINFOA_V1_SIZE;
958 toolInfo.hwnd = parent2;
959 toolInfo.hinst = GetModuleHandleA(NULL);
960 toolInfo.uFlags = 0;
961 toolInfo.uId = 0x1234ABCE;
962 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
963 toolInfo.lParam = 0xdeadbeef;
964 GetClientRect (parent, &toolInfo.rect);
965 lResult = SendMessageA(hwndTip, TTM_ADDTOOLA, 0, (LPARAM)&toolInfo);
966 ok(lResult, "Adding the tool to the tooltip failed\n");
967
968 /* Try to Remove Subclass */
969 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
970 toolInfo2.hwnd = parent;
971 toolInfo2.uId = 0x1234ABCD;
972 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
973 ok(lResult, "GetToolInfo failed\n");
974 ok(toolInfo2.uFlags & TTF_SUBCLASS, "uFlags does not have subclass\n");
975 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
976 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
977
978 toolInfo2.uFlags &= ~TTF_SUBCLASS;
979 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
980 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
981 ok(lResult, "GetToolInfo failed\n");
982 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
983 wndProc = (WNDPROC)GetWindowLongPtrA(parent, GWLP_WNDPROC);
984 ok (wndProc != info_wnd_proc, "Window Proc is wrong\n");
985
986 /* Try to Add Subclass */
987
988 /* Make it topmost, as per the MSDN */
989 SetWindowPos(hwndTip2, HWND_TOPMOST, 0, 0, 0, 0,
990 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
991
992 toolInfo2.cbSize = TTTOOLINFOA_V1_SIZE;
993 toolInfo2.hwnd = parent2;
994 toolInfo2.uId = 0x1234ABCE;
995 lResult = SendMessageA(hwndTip, TTM_GETTOOLINFOA, 0, (LPARAM)&toolInfo2);
996 ok(lResult, "GetToolInfo failed\n");
997 ok(!(toolInfo2.uFlags & TTF_SUBCLASS), "uFlags has subclass\n");
998 wndProc = (WNDPROC)GetWindowLongPtrA(parent2, GWLP_WNDPROC);
999 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
1000
1001 toolInfo2.uFlags |= TTF_SUBCLASS;
1002 SendMessageA(hwndTip, TTM_SETTOOLINFOA, 0, (LPARAM)&toolInfo2);
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(parent2, GWLP_WNDPROC);
1007 ok (wndProc == info_wnd_proc, "Window Proc is wrong\n");
1008
1009 /* Clean up */
1010 DestroyWindow(hwndTip);
1011 DestroyWindow(hwndTip2);
1012 DestroyWindow(parent);
1013 DestroyWindow(parent2);
1014 }
1015
1016 static void test_margin(void)
1017 {
1018 RECT r, r1;
1019 HWND hwnd;
1020 DWORD ret;
1021
1022 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1023 10, 10, 300, 100,
1024 NULL, NULL, NULL, 0);
1025 ok(hwnd != NULL, "failed to create tooltip wnd\n");
1026
1027 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0);
1028 ok(!ret, "got %d\n", ret);
1029
1030 SetRect(&r, -1, -1, 1, 1);
1031 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, (LPARAM)&r);
1032 ok(!ret, "got %d\n", ret);
1033
1034 SetRectEmpty(&r1);
1035 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1);
1036 ok(!ret, "got %d\n", ret);
1037 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r));
1038
1039 ret = SendMessageA(hwnd, TTM_SETMARGIN, 0, 0);
1040 ok(!ret, "got %d\n", ret);
1041
1042 SetRectEmpty(&r1);
1043 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, (LPARAM)&r1);
1044 ok(!ret, "got %d\n", ret);
1045 ok(EqualRect(&r, &r1), "got %s, was %s\n", wine_dbgstr_rect(&r1), wine_dbgstr_rect(&r));
1046
1047 ret = SendMessageA(hwnd, TTM_GETMARGIN, 0, 0);
1048 ok(!ret, "got %d\n", ret);
1049
1050 DestroyWindow(hwnd);
1051 }
1052
1053 START_TEST(tooltips)
1054 {
1055 InitCommonControls();
1056
1057 test_create_tooltip();
1058 test_customdraw();
1059 test_gettext();
1060 test_ttm_gettoolinfo();
1061 test_longtextA();
1062 test_longtextW();
1063 test_track();
1064 test_setinfo();
1065 test_margin();
1066 }