2 * Copyright 2005 Dmitry Timoshkov
3 * Copyright 2008 Jason Edmeades
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "resources.h"
25 #include "wine/test.h"
30 #define expect(expected, got) ok(got == expected, "Expected %d, got %ld\n", expected, got)
38 static struct msg_sequence
*sequences
[NUM_MSG_SEQUENCES
];
40 static void test_create_tooltip(BOOL is_v6
)
43 DWORD style
, exp_style
;
45 parent
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
48 ok(parent
!= NULL
, "failed to create parent wnd\n");
50 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0x7fffffff | WS_POPUP
,
52 parent
, NULL
, NULL
, 0);
53 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
55 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
56 exp_style
= 0x7fffffff | WS_POPUP
;
57 exp_style
&= ~(WS_CHILD
| WS_MAXIMIZE
| WS_BORDER
| WS_DLGFRAME
);
58 ok(style
== exp_style
, "wrong style %08lx/%08lx\n", style
, exp_style
);
62 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
64 parent
, NULL
, NULL
, 0);
65 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
67 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
68 exp_style
= WS_POPUP
| WS_CLIPSIBLINGS
;
70 exp_style
|= WS_BORDER
;
72 ok(style
== exp_style
|| broken(style
== (exp_style
| WS_BORDER
)) /* XP */,
73 "Unexpected window style %#lx.\n", style
);
77 DestroyWindow(parent
);
80 /* try to make sure pending X events have been processed before continuing */
81 static void flush_events(int waitTime
)
85 DWORD time
= GetTickCount() + waitTime
;
89 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min(100,diff
), QS_ALLEVENTS
) == WAIT_TIMEOUT
) break;
90 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
91 diff
= time
- GetTickCount();
96 static LRESULT CD_Result
;
99 #define TEST_CDDS_PREPAINT 0x00000001
100 #define TEST_CDDS_POSTPAINT 0x00000002
101 #define TEST_CDDS_PREERASE 0x00000004
102 #define TEST_CDDS_POSTERASE 0x00000008
103 #define TEST_CDDS_ITEMPREPAINT 0x00000010
104 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
105 #define TEST_CDDS_ITEMPREERASE 0x00000040
106 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
107 #define TEST_CDDS_SUBITEM 0x00000100
109 static LRESULT CALLBACK
custom_draw_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
118 if (((NMHDR
*)lParam
)->code
== NM_CUSTOMDRAW
) {
119 NMTTCUSTOMDRAW
*ttcd
= (NMTTCUSTOMDRAW
*) lParam
;
120 ok(ttcd
->nmcd
.hdr
.hwndFrom
== g_hwnd
, "Unexpected hwnd source %p (%p)\n",
121 ttcd
->nmcd
.hdr
.hwndFrom
, g_hwnd
);
122 ok(ttcd
->nmcd
.hdr
.idFrom
== 0x1234ABCD, "Unexpected id %x\n", (int)ttcd
->nmcd
.hdr
.idFrom
);
124 switch (ttcd
->nmcd
.dwDrawStage
) {
125 case CDDS_PREPAINT
: CD_Stages
|= TEST_CDDS_PREPAINT
; break;
126 case CDDS_POSTPAINT
: CD_Stages
|= TEST_CDDS_POSTPAINT
; break;
127 case CDDS_PREERASE
: CD_Stages
|= TEST_CDDS_PREERASE
; break;
128 case CDDS_POSTERASE
: CD_Stages
|= TEST_CDDS_POSTERASE
; break;
129 case CDDS_ITEMPREPAINT
: CD_Stages
|= TEST_CDDS_ITEMPREPAINT
; break;
130 case CDDS_ITEMPOSTPAINT
: CD_Stages
|= TEST_CDDS_ITEMPOSTPAINT
; break;
131 case CDDS_ITEMPREERASE
: CD_Stages
|= TEST_CDDS_ITEMPREERASE
; break;
132 case CDDS_ITEMPOSTERASE
: CD_Stages
|= TEST_CDDS_ITEMPOSTERASE
; break;
133 case CDDS_SUBITEM
: CD_Stages
|= TEST_CDDS_SUBITEM
; break;
134 default: CD_Stages
= -1;
137 if (ttcd
->nmcd
.dwDrawStage
== CDDS_PREPAINT
) return CD_Result
;
142 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
148 static void test_customdraw(void) {
150 LRESULT FirstReturnValue
;
152 } expectedResults
[] = {
153 /* Valid notification responses */
154 {CDRF_DODEFAULT
, TEST_CDDS_PREPAINT
},
155 {CDRF_SKIPDEFAULT
, TEST_CDDS_PREPAINT
},
156 {CDRF_NOTIFYPOSTPAINT
, TEST_CDDS_PREPAINT
| TEST_CDDS_POSTPAINT
},
158 /* Invalid notification responses */
159 {CDRF_NOTIFYITEMDRAW
, TEST_CDDS_PREPAINT
},
160 {CDRF_NOTIFYPOSTERASE
, TEST_CDDS_PREPAINT
},
161 {CDRF_NEWFONT
, TEST_CDDS_PREPAINT
}
164 DWORD iterationNumber
;
169 /* Create a class to use the custom draw wndproc */
170 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
173 wc
.hInstance
= GetModuleHandleA(NULL
);
175 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
176 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
177 wc
.lpszMenuName
= NULL
;
178 wc
.lpszClassName
= "CustomDrawClass";
179 wc
.lpfnWndProc
= custom_draw_wnd_proc
;
182 GetCursorPos(&orig_pos
);
184 for (iterationNumber
= 0;
185 iterationNumber
< ARRAY_SIZE(expectedResults
);
188 HWND parent
, hwndTip
;
190 TTTOOLINFOA toolInfo
= { 0 };
191 winetest_push_context("%ld", iterationNumber
);
193 /* Create a main window */
194 parent
= CreateWindowExA(0, "CustomDrawClass", NULL
,
195 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
196 WS_MAXIMIZEBOX
| WS_VISIBLE
,
199 NULL
, NULL
, NULL
, 0);
200 ok(parent
!= NULL
, "Creation of main window failed\n");
203 ShowWindow(parent
, SW_SHOWNORMAL
);
207 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
208 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
209 CW_USEDEFAULT
, CW_USEDEFAULT
,
210 CW_USEDEFAULT
, CW_USEDEFAULT
,
211 parent
, NULL
, GetModuleHandleA(NULL
), 0);
212 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
214 /* Set up parms for the wndproc to handle */
216 CD_Result
= expectedResults
[iterationNumber
].FirstReturnValue
;
219 /* Make it topmost, as per the MSDN */
220 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
221 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
224 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
225 toolInfo
.hwnd
= parent
;
226 toolInfo
.hinst
= GetModuleHandleA(NULL
);
227 toolInfo
.uFlags
= TTF_SUBCLASS
;
228 toolInfo
.uId
= 0x1234ABCD;
229 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
230 toolInfo
.lParam
= 0xdeadbeef;
231 GetClientRect (parent
, &toolInfo
.rect
);
232 ret
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
233 ok(ret
, "Failed to add the tool.\n");
235 /* Make tooltip appear quickly */
236 SendMessageA(hwndTip
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
238 /* Put cursor inside window, tooltip will appear immediately */
239 GetWindowRect( parent
, &rect
);
240 SetCursorPos( (rect
.left
+ rect
.right
) / 2, (rect
.top
+ rect
.bottom
) / 2 );
245 /* Check CustomDraw results */
246 ok(CD_Stages
== expectedResults
[iterationNumber
].ExpectedCalls
,
247 "CustomDraw stages %x, expected %x\n", CD_Stages
,
248 expectedResults
[iterationNumber
].ExpectedCalls
);
251 ret
= SendMessageA(hwndTip
, TTM_GETCURRENTTOOLA
, 0, 0);
252 ok(ret
, "Failed to get current tool %#Ix.\n", ret
);
254 memset(&toolInfo
, 0xcc, sizeof(toolInfo
));
255 toolInfo
.cbSize
= sizeof(toolInfo
);
256 toolInfo
.lpszText
= NULL
;
257 toolInfo
.lpReserved
= (void *)0xdeadbeef;
258 SendMessageA(hwndTip
, TTM_GETCURRENTTOOLA
, 0, (LPARAM
)&toolInfo
);
259 ok(toolInfo
.hwnd
== parent
, "Unexpected hwnd %p.\n", toolInfo
.hwnd
);
260 ok(toolInfo
.hinst
== GetModuleHandleA(NULL
), "Unexpected hinst %p.\n", toolInfo
.hinst
);
261 ok(toolInfo
.uId
== 0x1234abcd, "Unexpected uId %Ix.\n", toolInfo
.uId
);
262 ok(toolInfo
.lParam
== 0, "Unexpected lParam %Ix.\n", toolInfo
.lParam
);
263 ok(toolInfo
.lpReserved
== (void *)0xdeadbeef, "Unexpected lpReserved %p.\n", toolInfo
.lpReserved
);
266 DestroyWindow(hwndTip
);
267 DestroyWindow(parent
);
268 winetest_pop_context();
271 SetCursorPos(orig_pos
.x
, orig_pos
.y
);
274 static const CHAR testcallbackA
[] = "callback";
276 static RECT g_ttip_rect
;
277 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
279 static LONG defwndproc_counter
= 0;
283 if (message
== WM_NOTIFY
&& lParam
)
285 NMTTDISPINFOA
*ttnmdi
= (NMTTDISPINFOA
*)lParam
;
286 NMHDR
*hdr
= (NMHDR
*)lParam
;
289 if (hdr
->code
!= NM_CUSTOMDRAW
)
291 msg
.message
= message
;
292 msg
.flags
= sent
|wparam
|lparam
;
293 if (defwndproc_counter
) msg
.flags
|= defwinproc
;
297 add_message(sequences
, PARENT_SEQ_INDEX
, &msg
);
302 case TTN_GETDISPINFOA
:
303 lstrcpyA(ttnmdi
->lpszText
, testcallbackA
);
306 GetWindowRect(hdr
->hwndFrom
, &rect
);
307 ok(!EqualRect(&g_ttip_rect
, &rect
), "Unexpected window rectangle.\n");
312 defwndproc_counter
++;
313 if (IsWindowUnicode(hwnd
))
314 ret
= DefWindowProcW(hwnd
, message
, wParam
, lParam
);
316 ret
= DefWindowProcA(hwnd
, message
, wParam
, lParam
);
317 defwndproc_counter
--;
322 static void register_parent_wnd_class(void)
328 cls
.lpfnWndProc
= parent_wnd_proc
;
331 cls
.hInstance
= GetModuleHandleA(NULL
);
333 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
334 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
335 cls
.lpszMenuName
= NULL
;
336 cls
.lpszClassName
= "Tooltips test parent class";
337 ret
= RegisterClassA(&cls
);
338 ok(ret
, "Failed to register test parent class.\n");
341 static HWND
create_parent_window(void)
343 return CreateWindowExA(0, "Tooltips test parent class",
344 "Tooltips test parent window",
345 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
346 WS_MAXIMIZEBOX
| WS_VISIBLE
,
348 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
351 static void test_gettext(void)
353 static const CHAR testtip2A
[] = "testtip\ttest2";
354 static const CHAR testtipA
[] = "testtip";
356 TTTOOLINFOA toolinfoA
;
357 TTTOOLINFOW toolinfoW
;
360 WCHAR bufW
[10] = { 0 };
363 notify
= create_parent_window();
364 ok(notify
!= NULL
, "Expected notification window to be created\n");
366 /* For bug 14790 - lpszText is NULL */
367 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
369 NULL
, NULL
, NULL
, 0);
370 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
372 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
373 /* otherwise it crashes on the NULL lpszText */
374 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
375 toolinfoA
.hwnd
= NULL
;
376 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
377 toolinfoA
.uFlags
= 0;
378 toolinfoA
.uId
= 0x1234ABCD;
379 toolinfoA
.lpszText
= NULL
;
380 toolinfoA
.lParam
= 0xdeadbeef;
381 GetClientRect(hwnd
, &toolinfoA
.rect
);
382 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
383 ok(r
, "got %Id\n", r
);
385 toolinfoA
.hwnd
= NULL
;
386 toolinfoA
.uId
= 0x1234abcd;
387 toolinfoA
.lpszText
= bufA
;
388 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
389 ok(!r
, "got %Id\n", r
);
390 ok(!*toolinfoA
.lpszText
, "lpszText should be empty, got %s\n", toolinfoA
.lpszText
);
392 toolinfoA
.lpszText
= bufA
;
393 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
395 ok(!r
, "got %Id\n", r
);
396 ok(toolinfoA
.lpszText
== NULL
, "expected NULL, got %p\n", toolinfoA
.lpszText
);
398 /* NULL hinst, valid resource id for text */
399 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
400 toolinfoA
.hwnd
= NULL
;
401 toolinfoA
.hinst
= NULL
;
402 toolinfoA
.uFlags
= 0;
403 toolinfoA
.uId
= 0x1233abcd;
404 toolinfoA
.lpszText
= MAKEINTRESOURCEA(IDS_TBADD1
);
405 toolinfoA
.lParam
= 0xdeadbeef;
406 GetClientRect(hwnd
, &toolinfoA
.rect
);
407 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
408 ok(r
, "failed to add a tool\n");
410 toolinfoA
.hwnd
= NULL
;
411 toolinfoA
.uId
= 0x1233abcd;
412 toolinfoA
.lpszText
= bufA
;
413 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
414 ok(!r
, "got %Id\n", r
);
415 ok(!strcmp(toolinfoA
.lpszText
, "abc"), "got wrong text, %s\n", toolinfoA
.lpszText
);
417 toolinfoA
.hinst
= (HINSTANCE
)0xdeadbee;
418 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
420 ok(!r
, "got %Id\n", r
);
421 ok(toolinfoA
.hinst
== NULL
, "expected NULL, got %p\n", toolinfoA
.hinst
);
423 r
= SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&toolinfoA
);
424 ok(!r
, "got %Id\n", r
);
426 /* add another tool with text */
427 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
428 toolinfoA
.hwnd
= NULL
;
429 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
430 toolinfoA
.uFlags
= 0;
431 toolinfoA
.uId
= 0x1235ABCD;
432 strcpy(bufA
, testtipA
);
433 toolinfoA
.lpszText
= bufA
;
434 toolinfoA
.lParam
= 0xdeadbeef;
435 GetClientRect(hwnd
, &toolinfoA
.rect
);
436 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
437 ok(r
, "Adding the tool to the tooltip failed\n");
439 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
440 ok(length
== 0, "Expected 0, got %ld\n", length
);
442 toolinfoA
.hwnd
= NULL
;
443 toolinfoA
.uId
= 0x1235abcd;
444 toolinfoA
.lpszText
= bufA
;
445 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
446 ok(!r
, "got %Id\n", r
);
447 ok(!strcmp(toolinfoA
.lpszText
, testtipA
), "expected %s, got %p\n", testtipA
, toolinfoA
.lpszText
);
449 memset(bufA
, 0x1f, sizeof(bufA
));
450 toolinfoA
.lpszText
= bufA
;
451 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
453 ok(!r
, "got %Id\n", r
);
454 ok(!strcmp(toolinfoA
.lpszText
, testtipA
), "expected %s, got %p\n", testtipA
, toolinfoA
.lpszText
);
456 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
457 ok(length
== 0, "Expected 0, got %ld\n", length
);
459 /* add another with callback text */
460 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
461 toolinfoA
.hwnd
= notify
;
462 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
463 toolinfoA
.uFlags
= 0;
464 toolinfoA
.uId
= 0x1236ABCD;
465 toolinfoA
.lpszText
= LPSTR_TEXTCALLBACKA
;
466 toolinfoA
.lParam
= 0xdeadbeef;
467 GetClientRect(hwnd
, &toolinfoA
.rect
);
468 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
469 ok(r
, "Adding the tool to the tooltip failed\n");
471 toolinfoA
.hwnd
= notify
;
472 toolinfoA
.uId
= 0x1236abcd;
473 toolinfoA
.lpszText
= bufA
;
474 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
475 ok(!r
, "got %Id\n", r
);
476 ok(!strcmp(toolinfoA
.lpszText
, testcallbackA
), "lpszText should be an (%s) string\n", testcallbackA
);
478 toolinfoA
.lpszText
= bufA
;
479 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
481 ok(!r
, "got %Id\n", r
);
482 ok(toolinfoA
.lpszText
== LPSTR_TEXTCALLBACKA
, "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA
.lpszText
);
485 DestroyWindow(notify
);
487 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
489 NULL
, NULL
, NULL
, 0);
490 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
492 toolinfoW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
493 toolinfoW
.hwnd
= NULL
;
494 toolinfoW
.hinst
= GetModuleHandleA(NULL
);
495 toolinfoW
.uFlags
= 0;
496 toolinfoW
.uId
= 0x1234ABCD;
497 toolinfoW
.lpszText
= NULL
;
498 toolinfoW
.lParam
= 0xdeadbeef;
499 GetClientRect(hwnd
, &toolinfoW
.rect
);
500 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
501 /* Wine currently checks for V3 structure size, which matches what V6 control does.
502 Older implementation was never updated to support lpReserved field. */
504 ok(!r
, "Adding the tool to the tooltip succeeded!\n");
506 toolinfoW
.hwnd
= NULL
;
507 toolinfoW
.uId
= 0x1234ABCD;
508 toolinfoW
.lpszText
= bufW
;
509 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
510 ok(toolinfoW
.lpszText
[0] == 0, "lpszText should be an empty string\n");
512 /* text with embedded tabs */
513 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
514 toolinfoA
.hwnd
= NULL
;
515 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
516 toolinfoA
.uFlags
= 0;
517 toolinfoA
.uId
= 0x1235abce;
518 strcpy(bufA
, testtip2A
);
519 toolinfoA
.lpszText
= bufA
;
520 toolinfoA
.lParam
= 0xdeadbeef;
521 GetClientRect(hwnd
, &toolinfoA
.rect
);
522 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
523 ok(r
, "got %Id\n", r
);
525 toolinfoA
.hwnd
= NULL
;
526 toolinfoA
.uId
= 0x1235abce;
527 toolinfoA
.lpszText
= bufA
;
528 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
529 ok(!r
, "got %Id\n", r
);
530 ok(!strcmp(toolinfoA
.lpszText
, testtipA
), "expected %s, got %s\n", testtipA
, toolinfoA
.lpszText
);
532 /* enable TTS_NOPREFIX, original text is retained */
533 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
534 SetWindowLongA(hwnd
, GWL_STYLE
, style
| TTS_NOPREFIX
);
536 toolinfoA
.hwnd
= NULL
;
537 toolinfoA
.uId
= 0x1235abce;
538 toolinfoA
.lpszText
= bufA
;
539 r
= SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
540 ok(!r
, "got %Id\n", r
);
541 ok(!strcmp(toolinfoA
.lpszText
, testtip2A
), "expected %s, got %s\n", testtip2A
, toolinfoA
.lpszText
);
546 static void test_ttm_gettoolinfo(void)
553 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0, 10, 10, 300, 100, NULL
, NULL
, NULL
, 0);
554 ok(hwnd
!= NULL
, "Failed to create tooltip control.\n");
556 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
558 ti
.hinst
= GetModuleHandleA(NULL
);
562 ti
.lParam
= 0x1abe11ed;
563 GetClientRect(hwnd
, &ti
.rect
);
564 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
565 ok(r
, "Adding the tool to the tooltip failed\n");
567 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
568 ti
.lParam
= 0xaaaaaaaa;
569 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
570 ok(r
, "Getting tooltip info failed\n");
571 ok(0x1abe11ed == ti
.lParam
, "Expected 0x1abe11ed, got %Ix\n", ti
.lParam
);
573 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
575 tiW
.uId
= 0x1234ABCD;
576 tiW
.lParam
= 0xaaaaaaaa;
578 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&tiW
);
579 ok(r
, "Getting tooltip info failed\n");
580 ok(0x1abe11ed == tiW
.lParam
, "Expected 0x1abe11ed, got %Ix\n", tiW
.lParam
);
582 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
584 ti
.lParam
= 0x55555555;
585 SendMessageA(hwnd
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&ti
);
587 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
588 ti
.lParam
= 0xdeadbeef;
589 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
590 ok(r
, "Getting tooltip info failed\n");
591 ok(0x55555555 == ti
.lParam
, "Expected 0x55555555, got %Ix\n", ti
.lParam
);
595 /* 1. test size parameter validation rules (ansi messages) */
596 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
598 NULL
, NULL
, NULL
, 0);
600 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
602 ti
.hinst
= GetModuleHandleA(NULL
);
606 ti
.lParam
= 0xdeadbeef;
607 GetClientRect(hwnd
, &ti
.rect
);
608 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
609 ok(r
, "Adding the tool to the tooltip failed\n");
610 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
613 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
616 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
617 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
620 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
622 ti
.hinst
= GetModuleHandleA(NULL
);
626 ti
.lParam
= 0xdeadbeef;
627 GetClientRect(hwnd
, &ti
.rect
);
628 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
629 ok(r
, "Adding the tool to the tooltip failed\n");
630 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
633 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
636 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
637 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
640 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
642 ti
.hinst
= GetModuleHandleA(NULL
);
646 ti
.lParam
= 0xdeadbeef;
647 GetClientRect(hwnd
, &ti
.rect
);
648 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
649 ok(r
, "Adding the tool to the tooltip failed\n");
650 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
653 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
656 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
657 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
662 /* 2. test size parameter validation rules (w-messages) */
663 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
665 NULL
, NULL
, NULL
, 0);
666 ok(hwnd
!= NULL
, "Failed to create tooltip window.\n");
668 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
670 tiW
.hinst
= GetModuleHandleA(NULL
);
672 tiW
.uId
= 0x1234ABCD;
674 tiW
.lParam
= 0xdeadbeef;
675 GetClientRect(hwnd
, &tiW
.rect
);
676 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
677 ok(r
, "Adding the tool to the tooltip failed\n");
678 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
681 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
683 tiW
.uId
= 0x1234ABCD;
684 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
685 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
688 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
690 tiW
.hinst
= GetModuleHandleA(NULL
);
692 tiW
.uId
= 0x1234ABCD;
694 tiW
.lParam
= 0xdeadbeef;
695 GetClientRect(hwnd
, &tiW
.rect
);
696 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
697 ok(r
, "Adding the tool to the tooltip failed\n");
698 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
701 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
703 tiW
.uId
= 0x1234ABCD;
704 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
705 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
708 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
710 tiW
.hinst
= GetModuleHandleA(NULL
);
712 tiW
.uId
= 0x1234ABCD;
714 tiW
.lParam
= 0xdeadbeef;
715 GetClientRect(hwnd
, &tiW
.rect
);
716 r
= SendMessageW(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&tiW
);
717 ok(r
, "Adding the tool to the tooltip failed\n");
718 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
720 /* looks like TTM_DELTOOLW doesn't work with invalid size */
721 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
723 tiW
.uId
= 0x1234ABCD;
724 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
725 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
728 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
730 tiW
.uId
= 0x1234ABCD;
731 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
732 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
738 static void test_longtextA(void)
740 static const char longtextA
[] =
741 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
742 "80 chars including null. In fact, the buffer is not null-terminated.";
744 TTTOOLINFOA toolinfoA
= { 0 };
748 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
750 NULL
, NULL
, NULL
, 0);
751 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
752 toolinfoA
.hwnd
= NULL
;
753 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
754 toolinfoA
.uFlags
= 0;
755 toolinfoA
.uId
= 0x1234ABCD;
756 strcpy(bufA
, longtextA
);
757 toolinfoA
.lpszText
= bufA
;
758 toolinfoA
.lParam
= 0xdeadbeef;
759 GetClientRect(hwnd
, &toolinfoA
.rect
);
760 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
764 memset(bufA
, 0, sizeof(bufA
));
765 toolinfoA
.hwnd
= NULL
;
766 toolinfoA
.uId
= 0xABCD1234;
767 toolinfoA
.lpszText
= bufA
;
768 SendMessageA(hwnd
, TTM_ENUMTOOLSA
, 0, (LPARAM
)&toolinfoA
);
769 textlen
= lstrlenA(toolinfoA
.lpszText
);
770 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
771 ok(toolinfoA
.uId
== 0x1234ABCD,
772 "uId should be retrieved, got %p\n", (void*)toolinfoA
.uId
);
774 memset(bufA
, 0, sizeof(bufA
));
775 toolinfoA
.hwnd
= NULL
;
776 toolinfoA
.uId
= 0x1234ABCD;
777 toolinfoA
.lpszText
= bufA
;
778 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
779 textlen
= lstrlenA(toolinfoA
.lpszText
);
780 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
782 memset(bufA
, 0, sizeof(bufA
));
783 toolinfoA
.hwnd
= NULL
;
784 toolinfoA
.uId
= 0x1234ABCD;
785 toolinfoA
.lpszText
= bufA
;
786 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
787 textlen
= lstrlenA(toolinfoA
.lpszText
);
788 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
794 static void test_longtextW(void)
796 static const char longtextA
[] =
797 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
798 "80 chars including null. Actually, this is not applied for wide version.";
800 TTTOOLINFOW toolinfoW
= { 0 };
805 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
807 NULL
, NULL
, NULL
, 0);
808 ok(hwnd
!= NULL
, "Failed to create tooltip window.\n");
810 toolinfoW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
811 toolinfoW
.hwnd
= NULL
;
812 toolinfoW
.hinst
= GetModuleHandleW(NULL
);
813 toolinfoW
.uFlags
= 0;
814 toolinfoW
.uId
= 0x1234ABCD;
815 MultiByteToWideChar(CP_ACP
, 0, longtextA
, -1, bufW
, ARRAY_SIZE(bufW
));
816 lenW
= lstrlenW(bufW
);
817 toolinfoW
.lpszText
= bufW
;
818 toolinfoW
.lParam
= 0xdeadbeef;
819 GetClientRect(hwnd
, &toolinfoW
.rect
);
820 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
824 memset(bufW
, 0, sizeof(bufW
));
825 toolinfoW
.hwnd
= NULL
;
826 toolinfoW
.uId
= 0xABCD1234;
827 toolinfoW
.lpszText
= bufW
;
828 SendMessageW(hwnd
, TTM_ENUMTOOLSW
, 0, (LPARAM
)&toolinfoW
);
829 textlen
= lstrlenW(toolinfoW
.lpszText
);
830 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
831 ok(toolinfoW
.uId
== 0x1234ABCD,
832 "uId should be retrieved, got %p\n", (void*)toolinfoW
.uId
);
834 memset(bufW
, 0, sizeof(bufW
));
835 toolinfoW
.hwnd
= NULL
;
836 toolinfoW
.uId
= 0x1234ABCD;
837 toolinfoW
.lpszText
= bufW
;
838 SendMessageW(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&toolinfoW
);
839 textlen
= lstrlenW(toolinfoW
.lpszText
);
840 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
842 memset(bufW
, 0, sizeof(bufW
));
843 toolinfoW
.hwnd
= NULL
;
844 toolinfoW
.uId
= 0x1234ABCD;
845 toolinfoW
.lpszText
= bufW
;
846 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
847 textlen
= lstrlenW(toolinfoW
.lpszText
);
848 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
854 static BOOL
almost_eq(int a
, int b
)
856 return a
-5<b
&& a
+5>b
;
859 static void test_track(void)
861 WCHAR textW
[] = {'t','e','x','t',0};
862 TTTOOLINFOW info
= { 0 };
867 parent
= CreateWindowExW(0, WC_STATICW
, NULL
, WS_CAPTION
| WS_VISIBLE
,
868 50, 50, 300, 300, NULL
, NULL
, NULL
, 0);
869 ok(parent
!= NULL
, "creation of parent window failed\n");
871 ShowWindow(parent
, SW_SHOWNORMAL
);
874 tt
= CreateWindowExW(WS_EX_TOPMOST
, TOOLTIPS_CLASSW
, NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
875 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
876 parent
, NULL
, GetModuleHandleW(NULL
), 0);
877 ok(tt
!= NULL
, "creation of tooltip window failed\n");
879 info
.cbSize
= TTTOOLINFOW_V1_SIZE
;
880 info
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
882 info
.hinst
= GetModuleHandleW(NULL
);
883 info
.lpszText
= textW
;
884 info
.uId
= (UINT_PTR
)parent
;
885 GetClientRect(parent
, &info
.rect
);
887 res
= SendMessageW(tt
, TTM_ADDTOOLW
, 0, (LPARAM
)&info
);
888 ok(res
, "adding the tool to the tooltip failed\n");
890 SendMessageW(tt
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
891 SendMessageW(tt
, TTM_TRACKACTIVATE
, (WPARAM
)TRUE
, (LPARAM
)&info
);
892 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
894 GetWindowRect(tt
, &pos
);
895 ok(almost_eq(pos
.left
, 10), "pos.left = %ld\n", pos
.left
);
896 ok(almost_eq(pos
.top
, 10), "pos.top = %ld\n", pos
.top
);
898 info
.uFlags
= TTF_IDISHWND
| TTF_ABSOLUTE
;
899 SendMessageW(tt
, TTM_SETTOOLINFOW
, 0, (LPARAM
)&info
);
900 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
902 GetWindowRect(tt
, &pos
);
903 ok(!almost_eq(pos
.left
, 10), "pos.left = %ld\n", pos
.left
);
904 ok(!almost_eq(pos
.top
, 10), "pos.top = %ld\n", pos
.top
);
907 DestroyWindow(parent
);
910 static LRESULT CALLBACK
info_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
919 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
924 static void test_setinfo(BOOL is_v6
)
928 HWND parent
, parent2
, hwndTip
, hwndTip2
;
929 TTTOOLINFOA toolInfo
= { 0 };
930 TTTOOLINFOA toolInfo2
= { 0 };
933 /* Create a class to use the custom draw wndproc */
934 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
937 wc
.hInstance
= GetModuleHandleA(NULL
);
939 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
940 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
941 wc
.lpszMenuName
= NULL
;
942 wc
.lpszClassName
= "SetInfoClass";
943 wc
.lpfnWndProc
= info_wnd_proc
;
946 /* Create a main window */
947 parent
= CreateWindowExA(0, "SetInfoClass", NULL
,
948 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
949 WS_MAXIMIZEBOX
| WS_VISIBLE
,
952 NULL
, NULL
, NULL
, 0);
953 ok(parent
!= NULL
, "Creation of main window failed\n");
955 parent2
= CreateWindowExA(0, "SetInfoClass", NULL
,
956 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
957 WS_MAXIMIZEBOX
| WS_VISIBLE
,
960 NULL
, NULL
, NULL
, 0);
961 ok(parent2
!= NULL
, "Creation of main window failed\n");
964 ShowWindow(parent2
, SW_SHOWNORMAL
);
968 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
969 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
970 CW_USEDEFAULT
, CW_USEDEFAULT
,
971 CW_USEDEFAULT
, CW_USEDEFAULT
,
972 parent
, NULL
, GetModuleHandleA(NULL
), 0);
973 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
975 hwndTip2
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
976 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
977 CW_USEDEFAULT
, CW_USEDEFAULT
,
978 CW_USEDEFAULT
, CW_USEDEFAULT
,
979 parent
, NULL
, GetModuleHandleA(NULL
), 0);
980 ok(hwndTip2
!= NULL
, "Creation of tooltip window failed\n");
983 /* Make it topmost, as per the MSDN */
984 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
985 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
988 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
989 toolInfo
.hwnd
= parent
;
990 toolInfo
.hinst
= GetModuleHandleA(NULL
);
991 toolInfo
.uFlags
= TTF_SUBCLASS
;
992 toolInfo
.uId
= 0x1234ABCD;
993 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
994 toolInfo
.lParam
= 0xdeadbeef;
995 GetClientRect (parent
, &toolInfo
.rect
);
996 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
997 ok(lResult
, "Adding the tool to the tooltip failed\n");
999 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
1000 toolInfo
.hwnd
= parent2
;
1001 toolInfo
.hinst
= GetModuleHandleA(NULL
);
1002 toolInfo
.uFlags
= 0;
1003 toolInfo
.uId
= 0x1234ABCE;
1004 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
1005 toolInfo
.lParam
= 0xdeadbeef;
1006 GetClientRect (parent
, &toolInfo
.rect
);
1007 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
1008 ok(lResult
, "Adding the tool to the tooltip failed\n");
1010 /* Try to Remove Subclass */
1011 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
1012 toolInfo2
.hwnd
= parent
;
1013 toolInfo2
.uId
= 0x1234ABCD;
1014 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1015 ok(lResult
, "GetToolInfo failed\n");
1016 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
|| broken(is_v6
&& !(toolInfo2
.uFlags
& TTF_SUBCLASS
)) /* XP */,
1017 "uFlags does not have subclass\n");
1018 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
1019 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
1021 toolInfo2
.uFlags
&= ~TTF_SUBCLASS
;
1022 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1023 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1024 ok(lResult
, "GetToolInfo failed\n");
1025 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
1026 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
1027 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
1029 /* Try to Add Subclass */
1031 /* Make it topmost, as per the MSDN */
1032 SetWindowPos(hwndTip2
, HWND_TOPMOST
, 0, 0, 0, 0,
1033 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1035 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
1036 toolInfo2
.hwnd
= parent2
;
1037 toolInfo2
.uId
= 0x1234ABCE;
1038 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1039 ok(lResult
, "GetToolInfo failed\n");
1040 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
1041 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
1042 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
1044 toolInfo2
.uFlags
|= TTF_SUBCLASS
;
1045 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1046 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
1047 ok(lResult
, "GetToolInfo failed\n");
1048 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
, "uFlags does not have subclass\n");
1049 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
1050 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
1053 DestroyWindow(hwndTip
);
1054 DestroyWindow(hwndTip2
);
1055 DestroyWindow(parent
);
1056 DestroyWindow(parent2
);
1059 static void test_margin(void)
1065 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
1067 NULL
, NULL
, NULL
, 0);
1068 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
1070 ret
= SendMessageA(hwnd
, TTM_SETMARGIN
, 0, 0);
1071 ok(!ret
, "got %ld\n", ret
);
1073 SetRect(&r
, -1, -1, 1, 1);
1074 ret
= SendMessageA(hwnd
, TTM_SETMARGIN
, 0, (LPARAM
)&r
);
1075 ok(!ret
, "got %ld\n", ret
);
1078 ret
= SendMessageA(hwnd
, TTM_GETMARGIN
, 0, (LPARAM
)&r1
);
1079 ok(!ret
, "got %ld\n", ret
);
1080 ok(EqualRect(&r
, &r1
), "got %s, was %s\n", wine_dbgstr_rect(&r1
), wine_dbgstr_rect(&r
));
1082 ret
= SendMessageA(hwnd
, TTM_SETMARGIN
, 0, 0);
1083 ok(!ret
, "got %ld\n", ret
);
1086 ret
= SendMessageA(hwnd
, TTM_GETMARGIN
, 0, (LPARAM
)&r1
);
1087 ok(!ret
, "got %ld\n", ret
);
1088 ok(EqualRect(&r
, &r1
), "got %s, was %s\n", wine_dbgstr_rect(&r1
), wine_dbgstr_rect(&r
));
1090 ret
= SendMessageA(hwnd
, TTM_GETMARGIN
, 0, 0);
1091 ok(!ret
, "got %ld\n", ret
);
1093 DestroyWindow(hwnd
);
1096 static void test_TTM_ADDTOOL(BOOL is_v6
)
1104 parent
= CreateWindowExA(0, "Static", NULL
, WS_POPUP
, 0, 0, 0, 0, NULL
, NULL
, NULL
, 0);
1105 ok(parent
!= NULL
, "failed to create parent wnd\n");
1107 hwnd
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
, NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
1108 0, 0, 100, 100, NULL
, NULL
, GetModuleHandleA(NULL
), 0);
1109 ok(hwnd
!= NULL
, "Failed to create tooltip window.\n");
1111 for (size
= 0; size
<= TTTOOLINFOW_V3_SIZE
+ 1; size
++)
1115 ti
.hinst
= GetModuleHandleA(NULL
);
1117 ti
.uId
= 0x1234abce;
1118 ti
.lpszText
= (LPSTR
)"Test";
1119 ti
.lParam
= 0xdeadbeef;
1120 GetClientRect(hwnd
, &ti
.rect
);
1122 ret
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
1123 ok(ret
, "Failed to add a tool, size %d.\n", size
);
1125 ret
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
1126 ok(ret
== 1, "Unexpected tool count %d, size %d.\n", ret
, size
);
1128 ret
= SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
1129 ok(!ret
, "Unexpected ret value %d.\n", ret
);
1131 ret
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
1132 ok(ret
== 0, "Unexpected tool count %d, size %d.\n", ret
, size
);
1135 /* W variant checks cbSize. */
1136 max_size
= is_v6
? TTTOOLINFOW_V3_SIZE
: TTTOOLINFOW_V2_SIZE
;
1137 for (size
= 0; size
<= max_size
+ 1; size
++)
1141 tiW
.hinst
= GetModuleHandleA(NULL
);
1143 tiW
.uId
= 0x1234abce;
1144 tiW
.lpszText
= (LPWSTR
)L
"Test";
1145 tiW
.lParam
= 0xdeadbeef;
1146 GetClientRect(hwnd
, &tiW
.rect
);
1148 ret
= SendMessageA(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
1149 todo_wine_if(!is_v6
&& size
> max_size
)
1150 ok(size
<= max_size
? ret
: !ret
, "%d: Unexpected ret value %d, size %d, max size %d.\n", is_v6
, ret
, size
, max_size
);
1153 ret
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
1154 ok(ret
== 1, "Unexpected tool count %d.\n", ret
);
1156 ret
= SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&tiW
);
1157 ok(!ret
, "Unexpected ret value %d.\n", ret
);
1159 ret
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
1160 ok(ret
== 0, "Unexpected tool count %d.\n", ret
);
1164 DestroyWindow(hwnd
);
1167 static const struct message ttn_show_parent_seq
[] =
1169 { WM_NOTIFY
, sent
|id
, 0, 0, TTN_SHOW
},
1173 static void test_TTN_SHOW(void)
1180 hwnd
= create_parent_window();
1181 ok(hwnd
!= NULL
, "Failed to create parent window.\n");
1183 /* Put cursor outside the window */
1184 GetWindowRect(hwnd
, &rect
);
1185 SetCursorPos(rect
.right
+ 200, 0);
1187 ShowWindow(hwnd
, SW_SHOWNORMAL
);
1190 /* Create tooltip */
1191 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
, NULL
, TTS_ALWAYSTIP
, 10, 10, 300, 300,
1192 hwnd
, NULL
, NULL
, 0);
1193 ok(hwndTip
!= NULL
, "Failed to create tooltip window.\n");
1195 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
1197 ti
.cbSize
= sizeof(TTTOOLINFOA
);
1199 ti
.hinst
= GetModuleHandleA(NULL
);
1200 ti
.uFlags
= TTF_SUBCLASS
;
1201 ti
.uId
= 0x1234abcd;
1202 ti
.lpszText
= (LPSTR
)"This is a test tooltip";
1203 ti
.lParam
= 0xdeadbeef;
1204 GetClientRect(hwnd
, &ti
.rect
);
1205 ret
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
1206 ok(ret
, "Failed to add a tool.\n");
1208 /* Make tooltip appear quickly */
1209 SendMessageA(hwndTip
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1, 0));
1211 flush_sequences(sequences
, NUM_MSG_SEQUENCES
);
1213 /* Put cursor inside window, tooltip will appear immediately */
1214 GetWindowRect(hwnd
, &rect
);
1215 SetCursorPos((rect
.left
+ rect
.right
) / 2, (rect
.top
+ rect
.bottom
) / 2);
1218 ok_sequence(sequences
, PARENT_SEQ_INDEX
, ttn_show_parent_seq
, "TTN_SHOW parent seq", FALSE
);
1220 DestroyWindow(hwndTip
);
1221 DestroyWindow(hwnd
);
1224 START_TEST(tooltips
)
1226 ULONG_PTR ctx_cookie
;
1229 init_msg_sequences(sequences
, NUM_MSG_SEQUENCES
);
1231 LoadLibraryA("comctl32.dll");
1233 register_parent_wnd_class();
1235 test_create_tooltip(FALSE
);
1238 test_ttm_gettoolinfo();
1242 test_setinfo(FALSE
);
1244 test_TTM_ADDTOOL(FALSE
);
1247 if (!load_v6_module(&ctx_cookie
, &hCtx
))
1250 test_create_tooltip(TRUE
);
1256 test_TTM_ADDTOOL(TRUE
);
1259 unload_v6_module(ctx_cookie
, hCtx
);