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"
27 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
29 static void test_create_tooltip(void)
32 DWORD style
, exp_style
;
34 parent
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
37 ok(parent
!= NULL
, "failed to create parent wnd\n");
39 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0x7fffffff | WS_POPUP
,
41 parent
, NULL
, NULL
, 0);
42 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
44 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
45 trace("style = %08x\n", style
);
46 exp_style
= 0x7fffffff | WS_POPUP
;
47 exp_style
&= ~(WS_CHILD
| WS_MAXIMIZE
| WS_BORDER
| WS_DLGFRAME
);
48 ok(style
== exp_style
|| broken(style
== (exp_style
| WS_BORDER
)), /* nt4 */
49 "wrong style %08x/%08x\n", style
, exp_style
);
53 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
55 parent
, NULL
, NULL
, 0);
56 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
58 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
59 trace("style = %08x\n", style
);
60 ok(style
== (WS_POPUP
| WS_CLIPSIBLINGS
| WS_BORDER
),
61 "wrong style %08x\n", style
);
65 DestroyWindow(parent
);
68 /* try to make sure pending X events have been processed before continuing */
69 static void flush_events(int waitTime
)
73 DWORD time
= GetTickCount() + waitTime
;
77 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min(100,diff
), QS_ALLEVENTS
) == WAIT_TIMEOUT
) break;
78 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
79 diff
= time
- GetTickCount();
84 static LRESULT CD_Result
;
87 #define TEST_CDDS_PREPAINT 0x00000001
88 #define TEST_CDDS_POSTPAINT 0x00000002
89 #define TEST_CDDS_PREERASE 0x00000004
90 #define TEST_CDDS_POSTERASE 0x00000008
91 #define TEST_CDDS_ITEMPREPAINT 0x00000010
92 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
93 #define TEST_CDDS_ITEMPREERASE 0x00000040
94 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
95 #define TEST_CDDS_SUBITEM 0x00000100
97 static LRESULT CALLBACK
custom_draw_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
106 if (((NMHDR
*)lParam
)->code
== NM_CUSTOMDRAW
) {
107 NMTTCUSTOMDRAW
*ttcd
= (NMTTCUSTOMDRAW
*) lParam
;
108 ok(ttcd
->nmcd
.hdr
.hwndFrom
== g_hwnd
, "Unexpected hwnd source %p (%p)\n",
109 ttcd
->nmcd
.hdr
.hwndFrom
, g_hwnd
);
110 ok(ttcd
->nmcd
.hdr
.idFrom
== 0x1234ABCD, "Unexpected id %x\n", (int)ttcd
->nmcd
.hdr
.idFrom
);
112 switch (ttcd
->nmcd
.dwDrawStage
) {
113 case CDDS_PREPAINT
: CD_Stages
|= TEST_CDDS_PREPAINT
; break;
114 case CDDS_POSTPAINT
: CD_Stages
|= TEST_CDDS_POSTPAINT
; break;
115 case CDDS_PREERASE
: CD_Stages
|= TEST_CDDS_PREERASE
; break;
116 case CDDS_POSTERASE
: CD_Stages
|= TEST_CDDS_POSTERASE
; break;
117 case CDDS_ITEMPREPAINT
: CD_Stages
|= TEST_CDDS_ITEMPREPAINT
; break;
118 case CDDS_ITEMPOSTPAINT
: CD_Stages
|= TEST_CDDS_ITEMPOSTPAINT
; break;
119 case CDDS_ITEMPREERASE
: CD_Stages
|= TEST_CDDS_ITEMPREERASE
; break;
120 case CDDS_ITEMPOSTERASE
: CD_Stages
|= TEST_CDDS_ITEMPOSTERASE
; break;
121 case CDDS_SUBITEM
: CD_Stages
|= TEST_CDDS_SUBITEM
; break;
122 default: CD_Stages
= -1;
125 if (ttcd
->nmcd
.dwDrawStage
== CDDS_PREPAINT
) return CD_Result
;
130 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
136 static void test_customdraw(void) {
138 LRESULT FirstReturnValue
;
140 } expectedResults
[] = {
141 /* Valid notification responses */
142 {CDRF_DODEFAULT
, TEST_CDDS_PREPAINT
},
143 {CDRF_SKIPDEFAULT
, TEST_CDDS_PREPAINT
},
144 {CDRF_NOTIFYPOSTPAINT
, TEST_CDDS_PREPAINT
| TEST_CDDS_POSTPAINT
},
146 /* Invalid notification responses */
147 {CDRF_NOTIFYITEMDRAW
, TEST_CDDS_PREPAINT
},
148 {CDRF_NOTIFYPOSTERASE
, TEST_CDDS_PREPAINT
},
149 {CDRF_NEWFONT
, TEST_CDDS_PREPAINT
}
152 DWORD iterationNumber
;
156 /* Create a class to use the custom draw wndproc */
157 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
160 wc
.hInstance
= GetModuleHandleA(NULL
);
162 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
163 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
164 wc
.lpszMenuName
= NULL
;
165 wc
.lpszClassName
= "CustomDrawClass";
166 wc
.lpfnWndProc
= custom_draw_wnd_proc
;
169 for (iterationNumber
= 0;
170 iterationNumber
< sizeof(expectedResults
)/sizeof(expectedResults
[0]);
173 HWND parent
, hwndTip
;
175 TTTOOLINFOA toolInfo
= { 0 };
177 /* Create a main window */
178 parent
= CreateWindowExA(0, "CustomDrawClass", NULL
,
179 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
180 WS_MAXIMIZEBOX
| WS_VISIBLE
,
183 NULL
, NULL
, NULL
, 0);
184 ok(parent
!= NULL
, "Creation of main window failed\n");
187 ShowWindow(parent
, SW_SHOWNORMAL
);
191 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
192 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
193 CW_USEDEFAULT
, CW_USEDEFAULT
,
194 CW_USEDEFAULT
, CW_USEDEFAULT
,
195 parent
, NULL
, GetModuleHandleA(NULL
), 0);
196 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
198 /* Set up parms for the wndproc to handle */
200 CD_Result
= expectedResults
[iterationNumber
].FirstReturnValue
;
203 /* Make it topmost, as per the MSDN */
204 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
205 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
208 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
209 toolInfo
.hwnd
= parent
;
210 toolInfo
.hinst
= GetModuleHandleA(NULL
);
211 toolInfo
.uFlags
= TTF_SUBCLASS
;
212 toolInfo
.uId
= 0x1234ABCD;
213 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
214 toolInfo
.lParam
= 0xdeadbeef;
215 GetClientRect (parent
, &toolInfo
.rect
);
216 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
217 ok(lResult
, "Adding the tool to the tooltip failed\n");
219 /* Make tooltip appear quickly */
220 SendMessageA(hwndTip
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
222 /* Put cursor inside window, tooltip will appear immediately */
223 GetWindowRect( parent
, &rect
);
224 SetCursorPos( (rect
.left
+ rect
.right
) / 2, (rect
.top
+ rect
.bottom
) / 2 );
229 /* Check CustomDraw results */
230 ok(CD_Stages
== expectedResults
[iterationNumber
].ExpectedCalls
||
231 broken(CD_Stages
== (expectedResults
[iterationNumber
].ExpectedCalls
& ~TEST_CDDS_POSTPAINT
)), /* nt4 */
232 "CustomDraw run %d stages %x, expected %x\n", iterationNumber
, CD_Stages
,
233 expectedResults
[iterationNumber
].ExpectedCalls
);
237 DestroyWindow(hwndTip
);
238 DestroyWindow(parent
);
244 static const CHAR testcallbackA
[] = "callback";
246 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
248 if (message
== WM_NOTIFY
&& lParam
)
250 NMTTDISPINFOA
*ttnmdi
= (NMTTDISPINFOA
*)lParam
;
252 if (ttnmdi
->hdr
.code
== TTN_GETDISPINFOA
)
253 lstrcpyA(ttnmdi
->lpszText
, testcallbackA
);
256 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
259 static BOOL
register_parent_wnd_class(void)
264 cls
.lpfnWndProc
= parent_wnd_proc
;
267 cls
.hInstance
= GetModuleHandleA(NULL
);
269 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
270 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
271 cls
.lpszMenuName
= NULL
;
272 cls
.lpszClassName
= "Tooltips test parent class";
273 return RegisterClassA(&cls
);
276 static HWND
create_parent_window(void)
278 if (!register_parent_wnd_class())
281 return CreateWindowExA(0, "Tooltips test parent class",
282 "Tooltips test parent window",
283 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
284 WS_MAXIMIZEBOX
| WS_VISIBLE
,
286 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
289 static void test_gettext(void)
292 TTTOOLINFOA toolinfoA
;
293 TTTOOLINFOW toolinfoW
;
296 WCHAR bufW
[10] = { 0 };
297 static const CHAR testtipA
[] = "testtip";
299 notify
= create_parent_window();
300 ok(notify
!= NULL
, "Expected notification window to be created\n");
302 /* For bug 14790 - lpszText is NULL */
303 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
305 NULL
, NULL
, NULL
, 0);
306 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
308 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
309 /* otherwise it crashes on the NULL lpszText */
310 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
311 toolinfoA
.hwnd
= NULL
;
312 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
313 toolinfoA
.uFlags
= 0;
314 toolinfoA
.uId
= 0x1234ABCD;
315 toolinfoA
.lpszText
= NULL
;
316 toolinfoA
.lParam
= 0xdeadbeef;
317 GetClientRect(hwnd
, &toolinfoA
.rect
);
318 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
321 toolinfoA
.hwnd
= NULL
;
322 toolinfoA
.uId
= 0x1234ABCD;
323 toolinfoA
.lpszText
= bufA
;
324 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
325 ok(strcmp(toolinfoA
.lpszText
, "") == 0, "lpszText should be an empty string\n");
327 toolinfoA
.lpszText
= bufA
;
328 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
329 ok(toolinfoA
.lpszText
== NULL
,
330 "expected NULL, got %p\n", toolinfoA
.lpszText
);
332 /* NULL hinst, valid resource id for text */
333 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
334 toolinfoA
.hwnd
= NULL
;
335 toolinfoA
.hinst
= NULL
;
336 toolinfoA
.uFlags
= 0;
337 toolinfoA
.uId
= 0x1233ABCD;
338 toolinfoA
.lpszText
= MAKEINTRESOURCEA(IDS_TBADD1
);
339 toolinfoA
.lParam
= 0xdeadbeef;
340 GetClientRect(hwnd
, &toolinfoA
.rect
);
341 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
342 ok(r
, "failed to add a tool\n");
344 toolinfoA
.hwnd
= NULL
;
345 toolinfoA
.uId
= 0x1233ABCD;
346 toolinfoA
.lpszText
= bufA
;
347 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
348 ok(strcmp(toolinfoA
.lpszText
, "abc") == 0, "lpszText should be an empty string\n");
350 toolinfoA
.hinst
= (HINSTANCE
)0xdeadbee;
351 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
352 ok(toolinfoA
.hinst
== NULL
, "expected NULL, got %p\n", toolinfoA
.hinst
);
354 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&toolinfoA
);
358 win_skip( "Old comctl32, not testing NULL text\n" );
359 DestroyWindow( hwnd
);
363 /* add another tool with text */
364 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
365 toolinfoA
.hwnd
= NULL
;
366 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
367 toolinfoA
.uFlags
= 0;
368 toolinfoA
.uId
= 0x1235ABCD;
369 strcpy(bufA
, testtipA
);
370 toolinfoA
.lpszText
= bufA
;
371 toolinfoA
.lParam
= 0xdeadbeef;
372 GetClientRect(hwnd
, &toolinfoA
.rect
);
373 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
374 ok(r
, "Adding the tool to the tooltip failed\n");
379 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
380 ok(length
== 0, "Expected 0, got %d\n", length
);
382 toolinfoA
.hwnd
= NULL
;
383 toolinfoA
.uId
= 0x1235ABCD;
384 toolinfoA
.lpszText
= bufA
;
385 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
386 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0, "lpszText should be an empty string\n");
388 memset(bufA
, 0x1f, sizeof(bufA
));
389 toolinfoA
.lpszText
= bufA
;
390 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
391 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0,
392 "expected %s, got %p\n", testtipA
, toolinfoA
.lpszText
);
394 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
395 ok(length
== 0, "Expected 0, got %d\n", length
);
398 /* add another with callback text */
399 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
400 toolinfoA
.hwnd
= notify
;
401 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
402 toolinfoA
.uFlags
= 0;
403 toolinfoA
.uId
= 0x1236ABCD;
404 toolinfoA
.lpszText
= LPSTR_TEXTCALLBACKA
;
405 toolinfoA
.lParam
= 0xdeadbeef;
406 GetClientRect(hwnd
, &toolinfoA
.rect
);
407 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
408 ok(r
, "Adding the tool to the tooltip failed\n");
411 toolinfoA
.hwnd
= notify
;
412 toolinfoA
.uId
= 0x1236ABCD;
413 toolinfoA
.lpszText
= bufA
;
414 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
415 ok(strcmp(toolinfoA
.lpszText
, testcallbackA
) == 0,
416 "lpszText should be an (%s) string\n", testcallbackA
);
418 toolinfoA
.lpszText
= bufA
;
419 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
420 ok(toolinfoA
.lpszText
== LPSTR_TEXTCALLBACKA
,
421 "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA
.lpszText
);
425 DestroyWindow(notify
);
427 SetLastError(0xdeadbeef);
428 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
430 NULL
, NULL
, NULL
, 0);
432 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
433 win_skip("CreateWindowExW is not implemented\n");
436 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
438 toolinfoW
.cbSize
= sizeof(TTTOOLINFOW
);
439 toolinfoW
.hwnd
= NULL
;
440 toolinfoW
.hinst
= GetModuleHandleA(NULL
);
441 toolinfoW
.uFlags
= 0;
442 toolinfoW
.uId
= 0x1234ABCD;
443 toolinfoW
.lpszText
= NULL
;
444 toolinfoW
.lParam
= 0xdeadbeef;
445 GetClientRect(hwnd
, &toolinfoW
.rect
);
446 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
447 ok(!r
, "Adding the tool to the tooltip succeeded!\n");
449 if (0) /* crashes on NT4 */
451 toolinfoW
.hwnd
= NULL
;
452 toolinfoW
.uId
= 0x1234ABCD;
453 toolinfoW
.lpszText
= bufW
;
454 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
455 ok(toolinfoW
.lpszText
[0] == 0, "lpszText should be an empty string\n");
461 static void test_ttm_gettoolinfo(void)
468 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
470 NULL
, NULL
, NULL
, 0);
472 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
474 ti
.hinst
= GetModuleHandleA(NULL
);
478 ti
.lParam
= 0x1abe11ed;
479 GetClientRect(hwnd
, &ti
.rect
);
480 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
481 ok(r
, "Adding the tool to the tooltip failed\n");
483 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
484 ti
.lParam
= 0xaaaaaaaa;
485 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
486 ok(r
, "Getting tooltip info failed\n");
487 ok(0x1abe11ed == ti
.lParam
||
488 broken(0x1abe11ed != ti
.lParam
), /* comctl32 < 5.81 */
489 "Expected 0x1abe11ed, got %lx\n", ti
.lParam
);
491 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
493 tiW
.uId
= 0x1234ABCD;
494 tiW
.lParam
= 0xaaaaaaaa;
496 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&tiW
);
497 ok(r
, "Getting tooltip info failed\n");
498 ok(0x1abe11ed == tiW
.lParam
||
499 broken(0x1abe11ed != tiW
.lParam
), /* comctl32 < 5.81 */
500 "Expected 0x1abe11ed, got %lx\n", tiW
.lParam
);
502 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
504 ti
.lParam
= 0x55555555;
505 SendMessageA(hwnd
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&ti
);
507 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
508 ti
.lParam
= 0xdeadbeef;
509 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
510 ok(r
, "Getting tooltip info failed\n");
511 ok(0x55555555 == ti
.lParam
||
512 broken(0x55555555 != ti
.lParam
), /* comctl32 < 5.81 */
513 "Expected 0x55555555, got %lx\n", ti
.lParam
);
517 /* 1. test size parameter validation rules (ansi messages) */
518 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
520 NULL
, NULL
, NULL
, 0);
522 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
524 ti
.hinst
= GetModuleHandleA(NULL
);
528 ti
.lParam
= 0xdeadbeef;
529 GetClientRect(hwnd
, &ti
.rect
);
530 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
531 ok(r
, "Adding the tool to the tooltip failed\n");
532 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
535 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
538 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
539 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
542 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
544 ti
.hinst
= GetModuleHandleA(NULL
);
548 ti
.lParam
= 0xdeadbeef;
549 GetClientRect(hwnd
, &ti
.rect
);
550 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
551 ok(r
, "Adding the tool to the tooltip failed\n");
552 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
555 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
558 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
559 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
562 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
564 ti
.hinst
= GetModuleHandleA(NULL
);
568 ti
.lParam
= 0xdeadbeef;
569 GetClientRect(hwnd
, &ti
.rect
);
570 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
571 ok(r
, "Adding the tool to the tooltip failed\n");
572 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
575 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
578 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
579 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
584 /* 2. test size parameter validation rules (w-messages) */
585 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
587 NULL
, NULL
, NULL
, 0);
590 win_skip("CreateWindowExW() not supported. Skipping.\n");
594 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
596 tiW
.hinst
= GetModuleHandleA(NULL
);
598 tiW
.uId
= 0x1234ABCD;
600 tiW
.lParam
= 0xdeadbeef;
601 GetClientRect(hwnd
, &tiW
.rect
);
602 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
603 ok(r
, "Adding the tool to the tooltip failed\n");
604 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
607 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
609 tiW
.uId
= 0x1234ABCD;
610 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
611 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
614 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
616 tiW
.hinst
= GetModuleHandleA(NULL
);
618 tiW
.uId
= 0x1234ABCD;
620 tiW
.lParam
= 0xdeadbeef;
621 GetClientRect(hwnd
, &tiW
.rect
);
622 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
623 ok(r
, "Adding the tool to the tooltip failed\n");
624 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
627 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
629 tiW
.uId
= 0x1234ABCD;
630 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
631 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
634 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
636 tiW
.hinst
= GetModuleHandleA(NULL
);
638 tiW
.uId
= 0x1234ABCD;
640 tiW
.lParam
= 0xdeadbeef;
641 GetClientRect(hwnd
, &tiW
.rect
);
642 r
= SendMessageW(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&tiW
);
643 ok(r
, "Adding the tool to the tooltip failed\n");
644 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
646 /* looks like TTM_DELTOOLW doesn't work with invalid size */
647 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
649 tiW
.uId
= 0x1234ABCD;
650 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
651 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
654 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
656 tiW
.uId
= 0x1234ABCD;
657 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
658 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
664 static void test_longtextA(void)
666 static const char longtextA
[] =
667 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
668 "80 chars including null. In fact, the buffer is not null-terminated.";
670 TTTOOLINFOA toolinfoA
= { 0 };
674 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
676 NULL
, NULL
, NULL
, 0);
677 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
678 toolinfoA
.hwnd
= NULL
;
679 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
680 toolinfoA
.uFlags
= 0;
681 toolinfoA
.uId
= 0x1234ABCD;
682 strcpy(bufA
, longtextA
);
683 toolinfoA
.lpszText
= bufA
;
684 toolinfoA
.lParam
= 0xdeadbeef;
685 GetClientRect(hwnd
, &toolinfoA
.rect
);
686 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
690 memset(bufA
, 0, sizeof(bufA
));
691 toolinfoA
.hwnd
= NULL
;
692 toolinfoA
.uId
= 0xABCD1234;
693 toolinfoA
.lpszText
= bufA
;
694 SendMessageA(hwnd
, TTM_ENUMTOOLSA
, 0, (LPARAM
)&toolinfoA
);
695 textlen
= lstrlenA(toolinfoA
.lpszText
);
696 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
697 ok(toolinfoA
.uId
== 0x1234ABCD,
698 "uId should be retrieved, got %p\n", (void*)toolinfoA
.uId
);
700 memset(bufA
, 0, sizeof(bufA
));
701 toolinfoA
.hwnd
= NULL
;
702 toolinfoA
.uId
= 0x1234ABCD;
703 toolinfoA
.lpszText
= bufA
;
704 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
705 textlen
= lstrlenA(toolinfoA
.lpszText
);
706 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
708 memset(bufA
, 0, sizeof(bufA
));
709 toolinfoA
.hwnd
= NULL
;
710 toolinfoA
.uId
= 0x1234ABCD;
711 toolinfoA
.lpszText
= bufA
;
712 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
713 textlen
= lstrlenA(toolinfoA
.lpszText
);
714 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
720 static void test_longtextW(void)
722 static const char longtextA
[] =
723 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
724 "80 chars including null. Actually, this is not applied for wide version.";
726 TTTOOLINFOW toolinfoW
= { 0 };
731 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
733 NULL
, NULL
, NULL
, 0);
736 win_skip("CreateWindowExW() not supported. Skipping.\n");
740 toolinfoW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
741 toolinfoW
.hwnd
= NULL
;
742 toolinfoW
.hinst
= GetModuleHandleW(NULL
);
743 toolinfoW
.uFlags
= 0;
744 toolinfoW
.uId
= 0x1234ABCD;
745 MultiByteToWideChar(CP_ACP
, 0, longtextA
, -1, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
746 lenW
= lstrlenW(bufW
);
747 toolinfoW
.lpszText
= bufW
;
748 toolinfoW
.lParam
= 0xdeadbeef;
749 GetClientRect(hwnd
, &toolinfoW
.rect
);
750 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
754 memset(bufW
, 0, sizeof(bufW
));
755 toolinfoW
.hwnd
= NULL
;
756 toolinfoW
.uId
= 0xABCD1234;
757 toolinfoW
.lpszText
= bufW
;
758 SendMessageW(hwnd
, TTM_ENUMTOOLSW
, 0, (LPARAM
)&toolinfoW
);
759 textlen
= lstrlenW(toolinfoW
.lpszText
);
760 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
761 ok(toolinfoW
.uId
== 0x1234ABCD,
762 "uId should be retrieved, got %p\n", (void*)toolinfoW
.uId
);
764 memset(bufW
, 0, sizeof(bufW
));
765 toolinfoW
.hwnd
= NULL
;
766 toolinfoW
.uId
= 0x1234ABCD;
767 toolinfoW
.lpszText
= bufW
;
768 SendMessageW(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&toolinfoW
);
769 textlen
= lstrlenW(toolinfoW
.lpszText
);
770 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
772 memset(bufW
, 0, sizeof(bufW
));
773 toolinfoW
.hwnd
= NULL
;
774 toolinfoW
.uId
= 0x1234ABCD;
775 toolinfoW
.lpszText
= bufW
;
776 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
777 textlen
= lstrlenW(toolinfoW
.lpszText
);
778 ok(textlen
== lenW
||
779 broken(textlen
== 0 && toolinfoW
.lpszText
== NULL
), /* nt4, kb186177 */
780 "lpszText has %d chars\n", textlen
);
786 static BOOL
almost_eq(int a
, int b
)
788 return a
-5<b
&& a
+5>b
;
791 static void test_track(void)
793 WCHAR textW
[] = {'t','e','x','t',0};
794 TTTOOLINFOW info
= { 0 };
799 parent
= CreateWindowExW(0, WC_STATICW
, NULL
, WS_CAPTION
| WS_VISIBLE
,
800 50, 50, 300, 300, NULL
, NULL
, NULL
, 0);
801 ok(parent
!= NULL
, "creation of parent window failed\n");
803 ShowWindow(parent
, SW_SHOWNORMAL
);
806 tt
= CreateWindowExW(WS_EX_TOPMOST
, TOOLTIPS_CLASSW
, NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
807 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
808 parent
, NULL
, GetModuleHandleW(NULL
), 0);
809 ok(tt
!= NULL
, "creation of tooltip window failed\n");
811 info
.cbSize
= TTTOOLINFOW_V1_SIZE
;
812 info
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
814 info
.hinst
= GetModuleHandleW(NULL
);
815 info
.lpszText
= textW
;
816 info
.uId
= (UINT_PTR
)parent
;
817 GetClientRect(parent
, &info
.rect
);
819 res
= SendMessageW(tt
, TTM_ADDTOOLW
, 0, (LPARAM
)&info
);
820 ok(res
, "adding the tool to the tooltip failed\n");
822 SendMessageW(tt
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
823 SendMessageW(tt
, TTM_TRACKACTIVATE
, (WPARAM
)TRUE
, (LPARAM
)&info
);
824 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
826 GetWindowRect(tt
, &pos
);
827 ok(almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
828 ok(almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
830 info
.uFlags
= TTF_IDISHWND
| TTF_ABSOLUTE
;
831 SendMessageW(tt
, TTM_SETTOOLINFOW
, 0, (LPARAM
)&info
);
832 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
834 GetWindowRect(tt
, &pos
);
835 ok(!almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
836 ok(!almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
839 DestroyWindow(parent
);
842 static LRESULT CALLBACK
info_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
851 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
856 static void test_setinfo(void)
860 HWND parent
, parent2
, hwndTip
, hwndTip2
;
861 TTTOOLINFOA toolInfo
= { 0 };
862 TTTOOLINFOA toolInfo2
= { 0 };
865 /* Create a class to use the custom draw wndproc */
866 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
869 wc
.hInstance
= GetModuleHandleA(NULL
);
871 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
872 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
873 wc
.lpszMenuName
= NULL
;
874 wc
.lpszClassName
= "SetInfoClass";
875 wc
.lpfnWndProc
= info_wnd_proc
;
878 /* Create a main window */
879 parent
= CreateWindowExA(0, "SetInfoClass", NULL
,
880 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
881 WS_MAXIMIZEBOX
| WS_VISIBLE
,
884 NULL
, NULL
, NULL
, 0);
885 ok(parent
!= NULL
, "Creation of main window failed\n");
887 parent2
= CreateWindowExA(0, "SetInfoClass", NULL
,
888 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
889 WS_MAXIMIZEBOX
| WS_VISIBLE
,
892 NULL
, NULL
, NULL
, 0);
893 ok(parent2
!= NULL
, "Creation of main window failed\n");
896 ShowWindow(parent2
, SW_SHOWNORMAL
);
900 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
901 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
902 CW_USEDEFAULT
, CW_USEDEFAULT
,
903 CW_USEDEFAULT
, CW_USEDEFAULT
,
904 parent
, NULL
, GetModuleHandleA(NULL
), 0);
905 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
907 hwndTip2
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
908 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
909 CW_USEDEFAULT
, CW_USEDEFAULT
,
910 CW_USEDEFAULT
, CW_USEDEFAULT
,
911 parent
, NULL
, GetModuleHandleA(NULL
), 0);
912 ok(hwndTip2
!= NULL
, "Creation of tooltip window failed\n");
915 /* Make it topmost, as per the MSDN */
916 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
917 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
920 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
921 toolInfo
.hwnd
= parent
;
922 toolInfo
.hinst
= GetModuleHandleA(NULL
);
923 toolInfo
.uFlags
= TTF_SUBCLASS
;
924 toolInfo
.uId
= 0x1234ABCD;
925 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
926 toolInfo
.lParam
= 0xdeadbeef;
927 GetClientRect (parent
, &toolInfo
.rect
);
928 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
929 ok(lResult
, "Adding the tool to the tooltip failed\n");
931 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
932 toolInfo
.hwnd
= parent2
;
933 toolInfo
.hinst
= GetModuleHandleA(NULL
);
935 toolInfo
.uId
= 0x1234ABCE;
936 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
937 toolInfo
.lParam
= 0xdeadbeef;
938 GetClientRect (parent
, &toolInfo
.rect
);
939 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
940 ok(lResult
, "Adding the tool to the tooltip failed\n");
942 /* Try to Remove Subclass */
943 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
944 toolInfo2
.hwnd
= parent
;
945 toolInfo2
.uId
= 0x1234ABCD;
946 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
947 ok(lResult
, "GetToolInfo failed\n");
948 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
, "uFlags does not have subclass\n");
949 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
950 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
952 toolInfo2
.uFlags
&= ~TTF_SUBCLASS
;
953 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
954 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
955 ok(lResult
, "GetToolInfo failed\n");
956 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
957 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
958 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
960 /* Try to Add Subclass */
962 /* Make it topmost, as per the MSDN */
963 SetWindowPos(hwndTip2
, HWND_TOPMOST
, 0, 0, 0, 0,
964 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
966 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
967 toolInfo2
.hwnd
= parent2
;
968 toolInfo2
.uId
= 0x1234ABCE;
969 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
970 ok(lResult
, "GetToolInfo failed\n");
971 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
972 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
973 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
975 toolInfo2
.uFlags
|= TTF_SUBCLASS
;
976 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
977 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
978 ok(lResult
, "GetToolInfo failed\n");
979 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
, "uFlags does not have subclass\n");
980 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
981 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
984 DestroyWindow(hwndTip
);
985 DestroyWindow(hwndTip2
);
986 DestroyWindow(parent
);
987 DestroyWindow(parent2
);
992 InitCommonControls();
994 test_create_tooltip();
997 test_ttm_gettoolinfo();