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
20 #include <wine/test.h>
23 //#include <windows.h>
29 #include "resources.h"
31 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
33 static void test_create_tooltip(void)
36 DWORD style
, exp_style
;
38 parent
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
41 ok(parent
!= NULL
, "failed to create parent wnd\n");
43 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0x7fffffff | WS_POPUP
,
45 parent
, NULL
, NULL
, 0);
46 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
48 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
49 trace("style = %08x\n", style
);
50 exp_style
= 0x7fffffff | WS_POPUP
;
51 exp_style
&= ~(WS_CHILD
| WS_MAXIMIZE
| WS_BORDER
| WS_DLGFRAME
);
52 ok(style
== exp_style
|| broken(style
== (exp_style
| WS_BORDER
)), /* nt4 */
53 "wrong style %08x/%08x\n", style
, exp_style
);
57 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
59 parent
, NULL
, NULL
, 0);
60 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
62 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
63 trace("style = %08x\n", style
);
64 ok(style
== (WS_POPUP
| WS_CLIPSIBLINGS
| WS_BORDER
),
65 "wrong style %08x\n", style
);
69 DestroyWindow(parent
);
72 /* try to make sure pending X events have been processed before continuing */
73 static void flush_events(int waitTime
)
77 DWORD time
= GetTickCount() + waitTime
;
81 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min(100,diff
), QS_ALLEVENTS
) == WAIT_TIMEOUT
) break;
82 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
83 diff
= time
- GetTickCount();
88 static LRESULT CD_Result
;
91 #define TEST_CDDS_PREPAINT 0x00000001
92 #define TEST_CDDS_POSTPAINT 0x00000002
93 #define TEST_CDDS_PREERASE 0x00000004
94 #define TEST_CDDS_POSTERASE 0x00000008
95 #define TEST_CDDS_ITEMPREPAINT 0x00000010
96 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
97 #define TEST_CDDS_ITEMPREERASE 0x00000040
98 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
99 #define TEST_CDDS_SUBITEM 0x00000100
101 static LRESULT CALLBACK
custom_draw_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
110 if (((NMHDR
*)lParam
)->code
== NM_CUSTOMDRAW
) {
111 NMTTCUSTOMDRAW
*ttcd
= (NMTTCUSTOMDRAW
*) lParam
;
112 ok(ttcd
->nmcd
.hdr
.hwndFrom
== g_hwnd
, "Unexpected hwnd source %p (%p)\n",
113 ttcd
->nmcd
.hdr
.hwndFrom
, g_hwnd
);
114 ok(ttcd
->nmcd
.hdr
.idFrom
== 0x1234ABCD, "Unexpected id %x\n", (int)ttcd
->nmcd
.hdr
.idFrom
);
116 switch (ttcd
->nmcd
.dwDrawStage
) {
117 case CDDS_PREPAINT
: CD_Stages
|= TEST_CDDS_PREPAINT
; break;
118 case CDDS_POSTPAINT
: CD_Stages
|= TEST_CDDS_POSTPAINT
; break;
119 case CDDS_PREERASE
: CD_Stages
|= TEST_CDDS_PREERASE
; break;
120 case CDDS_POSTERASE
: CD_Stages
|= TEST_CDDS_POSTERASE
; break;
121 case CDDS_ITEMPREPAINT
: CD_Stages
|= TEST_CDDS_ITEMPREPAINT
; break;
122 case CDDS_ITEMPOSTPAINT
: CD_Stages
|= TEST_CDDS_ITEMPOSTPAINT
; break;
123 case CDDS_ITEMPREERASE
: CD_Stages
|= TEST_CDDS_ITEMPREERASE
; break;
124 case CDDS_ITEMPOSTERASE
: CD_Stages
|= TEST_CDDS_ITEMPOSTERASE
; break;
125 case CDDS_SUBITEM
: CD_Stages
|= TEST_CDDS_SUBITEM
; break;
126 default: CD_Stages
= -1;
129 if (ttcd
->nmcd
.dwDrawStage
== CDDS_PREPAINT
) return CD_Result
;
134 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
140 static void test_customdraw(void) {
142 LRESULT FirstReturnValue
;
144 } expectedResults
[] = {
145 /* Valid notification responses */
146 {CDRF_DODEFAULT
, TEST_CDDS_PREPAINT
},
147 {CDRF_SKIPDEFAULT
, TEST_CDDS_PREPAINT
},
148 {CDRF_NOTIFYPOSTPAINT
, TEST_CDDS_PREPAINT
| TEST_CDDS_POSTPAINT
},
150 /* Invalid notification responses */
151 {CDRF_NOTIFYITEMDRAW
, TEST_CDDS_PREPAINT
},
152 {CDRF_NOTIFYPOSTERASE
, TEST_CDDS_PREPAINT
},
153 {CDRF_NEWFONT
, TEST_CDDS_PREPAINT
}
156 DWORD iterationNumber
;
160 /* Create a class to use the custom draw wndproc */
161 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
164 wc
.hInstance
= GetModuleHandleA(NULL
);
166 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
167 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
168 wc
.lpszMenuName
= NULL
;
169 wc
.lpszClassName
= "CustomDrawClass";
170 wc
.lpfnWndProc
= custom_draw_wnd_proc
;
173 for (iterationNumber
= 0;
174 iterationNumber
< sizeof(expectedResults
)/sizeof(expectedResults
[0]);
177 HWND parent
, hwndTip
;
179 TTTOOLINFOA toolInfo
= { 0 };
181 /* Create a main window */
182 parent
= CreateWindowExA(0, "CustomDrawClass", NULL
,
183 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
184 WS_MAXIMIZEBOX
| WS_VISIBLE
,
187 NULL
, NULL
, NULL
, 0);
188 ok(parent
!= NULL
, "Creation of main window failed\n");
191 ShowWindow(parent
, SW_SHOWNORMAL
);
195 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
196 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
197 CW_USEDEFAULT
, CW_USEDEFAULT
,
198 CW_USEDEFAULT
, CW_USEDEFAULT
,
199 parent
, NULL
, GetModuleHandleA(NULL
), 0);
200 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
202 /* Set up parms for the wndproc to handle */
204 CD_Result
= expectedResults
[iterationNumber
].FirstReturnValue
;
207 /* Make it topmost, as per the MSDN */
208 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
209 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
212 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
213 toolInfo
.hwnd
= parent
;
214 toolInfo
.hinst
= GetModuleHandleA(NULL
);
215 toolInfo
.uFlags
= TTF_SUBCLASS
;
216 toolInfo
.uId
= 0x1234ABCD;
217 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
218 toolInfo
.lParam
= 0xdeadbeef;
219 GetClientRect (parent
, &toolInfo
.rect
);
220 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
221 ok(lResult
, "Adding the tool to the tooltip failed\n");
223 /* Make tooltip appear quickly */
224 SendMessageA(hwndTip
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
226 /* Put cursor inside window, tooltip will appear immediately */
227 GetWindowRect( parent
, &rect
);
228 SetCursorPos( (rect
.left
+ rect
.right
) / 2, (rect
.top
+ rect
.bottom
) / 2 );
233 /* Check CustomDraw results */
234 ok(CD_Stages
== expectedResults
[iterationNumber
].ExpectedCalls
||
235 broken(CD_Stages
== (expectedResults
[iterationNumber
].ExpectedCalls
& ~TEST_CDDS_POSTPAINT
)), /* nt4 */
236 "CustomDraw run %d stages %x, expected %x\n", iterationNumber
, CD_Stages
,
237 expectedResults
[iterationNumber
].ExpectedCalls
);
241 DestroyWindow(hwndTip
);
242 DestroyWindow(parent
);
248 static const CHAR testcallbackA
[] = "callback";
250 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
252 if (message
== WM_NOTIFY
&& lParam
)
254 NMTTDISPINFOA
*ttnmdi
= (NMTTDISPINFOA
*)lParam
;
256 if (ttnmdi
->hdr
.code
== TTN_GETDISPINFOA
)
257 lstrcpyA(ttnmdi
->lpszText
, testcallbackA
);
260 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
263 static BOOL
register_parent_wnd_class(void)
268 cls
.lpfnWndProc
= parent_wnd_proc
;
271 cls
.hInstance
= GetModuleHandleA(NULL
);
273 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
274 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
275 cls
.lpszMenuName
= NULL
;
276 cls
.lpszClassName
= "Tooltips test parent class";
277 return RegisterClassA(&cls
);
280 static HWND
create_parent_window(void)
282 if (!register_parent_wnd_class())
285 return CreateWindowExA(0, "Tooltips test parent class",
286 "Tooltips test parent window",
287 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
288 WS_MAXIMIZEBOX
| WS_VISIBLE
,
290 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
293 static void test_gettext(void)
296 TTTOOLINFOA toolinfoA
;
297 TTTOOLINFOW toolinfoW
;
300 WCHAR bufW
[10] = { 0 };
301 static const CHAR testtipA
[] = "testtip";
303 notify
= create_parent_window();
304 ok(notify
!= NULL
, "Expected notification window to be created\n");
306 /* For bug 14790 - lpszText is NULL */
307 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
309 NULL
, NULL
, NULL
, 0);
310 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
312 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
313 /* otherwise it crashes on the NULL lpszText */
314 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
315 toolinfoA
.hwnd
= NULL
;
316 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
317 toolinfoA
.uFlags
= 0;
318 toolinfoA
.uId
= 0x1234ABCD;
319 toolinfoA
.lpszText
= NULL
;
320 toolinfoA
.lParam
= 0xdeadbeef;
321 GetClientRect(hwnd
, &toolinfoA
.rect
);
322 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
325 toolinfoA
.hwnd
= NULL
;
326 toolinfoA
.uId
= 0x1234ABCD;
327 toolinfoA
.lpszText
= bufA
;
328 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
329 ok(strcmp(toolinfoA
.lpszText
, "") == 0, "lpszText should be an empty string\n");
331 toolinfoA
.lpszText
= bufA
;
332 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
333 ok(toolinfoA
.lpszText
== NULL
,
334 "expected NULL, got %p\n", toolinfoA
.lpszText
);
336 /* NULL hinst, valid resource id for text */
337 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
338 toolinfoA
.hwnd
= NULL
;
339 toolinfoA
.hinst
= NULL
;
340 toolinfoA
.uFlags
= 0;
341 toolinfoA
.uId
= 0x1233ABCD;
342 toolinfoA
.lpszText
= MAKEINTRESOURCEA(IDS_TBADD1
);
343 toolinfoA
.lParam
= 0xdeadbeef;
344 GetClientRect(hwnd
, &toolinfoA
.rect
);
345 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
346 ok(r
, "failed to add a tool\n");
348 toolinfoA
.hwnd
= NULL
;
349 toolinfoA
.uId
= 0x1233ABCD;
350 toolinfoA
.lpszText
= bufA
;
351 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
352 ok(strcmp(toolinfoA
.lpszText
, "abc") == 0, "lpszText should be an empty string\n");
354 toolinfoA
.hinst
= (HINSTANCE
)0xdeadbee;
355 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
356 ok(toolinfoA
.hinst
== NULL
, "expected NULL, got %p\n", toolinfoA
.hinst
);
358 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&toolinfoA
);
362 win_skip( "Old comctl32, not testing NULL text\n" );
363 DestroyWindow( hwnd
);
367 /* add another tool with text */
368 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
369 toolinfoA
.hwnd
= NULL
;
370 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
371 toolinfoA
.uFlags
= 0;
372 toolinfoA
.uId
= 0x1235ABCD;
373 strcpy(bufA
, testtipA
);
374 toolinfoA
.lpszText
= bufA
;
375 toolinfoA
.lParam
= 0xdeadbeef;
376 GetClientRect(hwnd
, &toolinfoA
.rect
);
377 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
378 ok(r
, "Adding the tool to the tooltip failed\n");
383 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
384 ok(length
== 0, "Expected 0, got %d\n", length
);
386 toolinfoA
.hwnd
= NULL
;
387 toolinfoA
.uId
= 0x1235ABCD;
388 toolinfoA
.lpszText
= bufA
;
389 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
390 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0, "lpszText should be an empty string\n");
392 memset(bufA
, 0x1f, sizeof(bufA
));
393 toolinfoA
.lpszText
= bufA
;
394 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
395 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0,
396 "expected %s, got %p\n", testtipA
, toolinfoA
.lpszText
);
398 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
399 ok(length
== 0, "Expected 0, got %d\n", length
);
402 /* add another with callback text */
403 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
404 toolinfoA
.hwnd
= notify
;
405 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
406 toolinfoA
.uFlags
= 0;
407 toolinfoA
.uId
= 0x1236ABCD;
408 toolinfoA
.lpszText
= LPSTR_TEXTCALLBACKA
;
409 toolinfoA
.lParam
= 0xdeadbeef;
410 GetClientRect(hwnd
, &toolinfoA
.rect
);
411 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
412 ok(r
, "Adding the tool to the tooltip failed\n");
415 toolinfoA
.hwnd
= notify
;
416 toolinfoA
.uId
= 0x1236ABCD;
417 toolinfoA
.lpszText
= bufA
;
418 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
419 ok(strcmp(toolinfoA
.lpszText
, testcallbackA
) == 0,
420 "lpszText should be an (%s) string\n", testcallbackA
);
422 toolinfoA
.lpszText
= bufA
;
423 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
424 ok(toolinfoA
.lpszText
== LPSTR_TEXTCALLBACKA
,
425 "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA
.lpszText
);
429 DestroyWindow(notify
);
431 SetLastError(0xdeadbeef);
432 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
434 NULL
, NULL
, NULL
, 0);
436 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
437 win_skip("CreateWindowExW is not implemented\n");
440 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
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");
453 if (0) /* crashes on NT4 */
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");
465 static void test_ttm_gettoolinfo(void)
472 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
474 NULL
, NULL
, NULL
, 0);
476 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
478 ti
.hinst
= GetModuleHandleA(NULL
);
482 ti
.lParam
= 0x1abe11ed;
483 GetClientRect(hwnd
, &ti
.rect
);
484 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
485 ok(r
, "Adding the tool to the tooltip failed\n");
487 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
488 ti
.lParam
= 0xaaaaaaaa;
489 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
490 ok(r
, "Getting tooltip info failed\n");
491 ok(0x1abe11ed == ti
.lParam
||
492 broken(0x1abe11ed != ti
.lParam
), /* comctl32 < 5.81 */
493 "Expected 0x1abe11ed, got %lx\n", ti
.lParam
);
495 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
497 tiW
.uId
= 0x1234ABCD;
498 tiW
.lParam
= 0xaaaaaaaa;
500 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&tiW
);
501 ok(r
, "Getting tooltip info failed\n");
502 ok(0x1abe11ed == tiW
.lParam
||
503 broken(0x1abe11ed != tiW
.lParam
), /* comctl32 < 5.81 */
504 "Expected 0x1abe11ed, got %lx\n", tiW
.lParam
);
506 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
508 ti
.lParam
= 0x55555555;
509 SendMessageA(hwnd
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&ti
);
511 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
512 ti
.lParam
= 0xdeadbeef;
513 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
514 ok(r
, "Getting tooltip info failed\n");
515 ok(0x55555555 == ti
.lParam
||
516 broken(0x55555555 != ti
.lParam
), /* comctl32 < 5.81 */
517 "Expected 0x55555555, got %lx\n", ti
.lParam
);
521 /* 1. test size parameter validation rules (ansi messages) */
522 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
524 NULL
, NULL
, NULL
, 0);
526 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
528 ti
.hinst
= GetModuleHandleA(NULL
);
532 ti
.lParam
= 0xdeadbeef;
533 GetClientRect(hwnd
, &ti
.rect
);
534 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
535 ok(r
, "Adding the tool to the tooltip failed\n");
536 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
539 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
542 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
543 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
546 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
548 ti
.hinst
= GetModuleHandleA(NULL
);
552 ti
.lParam
= 0xdeadbeef;
553 GetClientRect(hwnd
, &ti
.rect
);
554 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
555 ok(r
, "Adding the tool to the tooltip failed\n");
556 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
559 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
562 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
563 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
566 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
568 ti
.hinst
= GetModuleHandleA(NULL
);
572 ti
.lParam
= 0xdeadbeef;
573 GetClientRect(hwnd
, &ti
.rect
);
574 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
575 ok(r
, "Adding the tool to the tooltip failed\n");
576 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
579 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
582 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
583 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
588 /* 2. test size parameter validation rules (w-messages) */
589 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
591 NULL
, NULL
, NULL
, 0);
594 win_skip("CreateWindowExW() not supported. Skipping.\n");
598 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
600 tiW
.hinst
= GetModuleHandleA(NULL
);
602 tiW
.uId
= 0x1234ABCD;
604 tiW
.lParam
= 0xdeadbeef;
605 GetClientRect(hwnd
, &tiW
.rect
);
606 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
607 ok(r
, "Adding the tool to the tooltip failed\n");
608 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
611 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
613 tiW
.uId
= 0x1234ABCD;
614 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
615 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
618 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
620 tiW
.hinst
= GetModuleHandleA(NULL
);
622 tiW
.uId
= 0x1234ABCD;
624 tiW
.lParam
= 0xdeadbeef;
625 GetClientRect(hwnd
, &tiW
.rect
);
626 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
627 ok(r
, "Adding the tool to the tooltip failed\n");
628 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
631 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
633 tiW
.uId
= 0x1234ABCD;
634 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
635 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
638 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
640 tiW
.hinst
= GetModuleHandleA(NULL
);
642 tiW
.uId
= 0x1234ABCD;
644 tiW
.lParam
= 0xdeadbeef;
645 GetClientRect(hwnd
, &tiW
.rect
);
646 r
= SendMessageW(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&tiW
);
647 ok(r
, "Adding the tool to the tooltip failed\n");
648 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
650 /* looks like TTM_DELTOOLW doesn't work with invalid size */
651 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
653 tiW
.uId
= 0x1234ABCD;
654 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
655 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
658 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
660 tiW
.uId
= 0x1234ABCD;
661 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
662 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
668 static void test_longtextA(void)
670 static const char longtextA
[] =
671 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
672 "80 chars including null. In fact, the buffer is not null-terminated.";
674 TTTOOLINFOA toolinfoA
= { 0 };
678 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
680 NULL
, NULL
, NULL
, 0);
681 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
682 toolinfoA
.hwnd
= NULL
;
683 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
684 toolinfoA
.uFlags
= 0;
685 toolinfoA
.uId
= 0x1234ABCD;
686 strcpy(bufA
, longtextA
);
687 toolinfoA
.lpszText
= bufA
;
688 toolinfoA
.lParam
= 0xdeadbeef;
689 GetClientRect(hwnd
, &toolinfoA
.rect
);
690 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
694 memset(bufA
, 0, sizeof(bufA
));
695 toolinfoA
.hwnd
= NULL
;
696 toolinfoA
.uId
= 0xABCD1234;
697 toolinfoA
.lpszText
= bufA
;
698 SendMessageA(hwnd
, TTM_ENUMTOOLSA
, 0, (LPARAM
)&toolinfoA
);
699 textlen
= lstrlenA(toolinfoA
.lpszText
);
700 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
701 ok(toolinfoA
.uId
== 0x1234ABCD,
702 "uId should be retrieved, got %p\n", (void*)toolinfoA
.uId
);
704 memset(bufA
, 0, sizeof(bufA
));
705 toolinfoA
.hwnd
= NULL
;
706 toolinfoA
.uId
= 0x1234ABCD;
707 toolinfoA
.lpszText
= bufA
;
708 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
709 textlen
= lstrlenA(toolinfoA
.lpszText
);
710 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
712 memset(bufA
, 0, sizeof(bufA
));
713 toolinfoA
.hwnd
= NULL
;
714 toolinfoA
.uId
= 0x1234ABCD;
715 toolinfoA
.lpszText
= bufA
;
716 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
717 textlen
= lstrlenA(toolinfoA
.lpszText
);
718 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
724 static void test_longtextW(void)
726 static const char longtextA
[] =
727 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
728 "80 chars including null. Actually, this is not applied for wide version.";
730 TTTOOLINFOW toolinfoW
= { 0 };
735 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
737 NULL
, NULL
, NULL
, 0);
740 win_skip("CreateWindowExW() not supported. Skipping.\n");
744 toolinfoW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
745 toolinfoW
.hwnd
= NULL
;
746 toolinfoW
.hinst
= GetModuleHandleW(NULL
);
747 toolinfoW
.uFlags
= 0;
748 toolinfoW
.uId
= 0x1234ABCD;
749 MultiByteToWideChar(CP_ACP
, 0, longtextA
, -1, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
750 lenW
= lstrlenW(bufW
);
751 toolinfoW
.lpszText
= bufW
;
752 toolinfoW
.lParam
= 0xdeadbeef;
753 GetClientRect(hwnd
, &toolinfoW
.rect
);
754 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
758 memset(bufW
, 0, sizeof(bufW
));
759 toolinfoW
.hwnd
= NULL
;
760 toolinfoW
.uId
= 0xABCD1234;
761 toolinfoW
.lpszText
= bufW
;
762 SendMessageW(hwnd
, TTM_ENUMTOOLSW
, 0, (LPARAM
)&toolinfoW
);
763 textlen
= lstrlenW(toolinfoW
.lpszText
);
764 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
765 ok(toolinfoW
.uId
== 0x1234ABCD,
766 "uId should be retrieved, got %p\n", (void*)toolinfoW
.uId
);
768 memset(bufW
, 0, sizeof(bufW
));
769 toolinfoW
.hwnd
= NULL
;
770 toolinfoW
.uId
= 0x1234ABCD;
771 toolinfoW
.lpszText
= bufW
;
772 SendMessageW(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&toolinfoW
);
773 textlen
= lstrlenW(toolinfoW
.lpszText
);
774 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
776 memset(bufW
, 0, sizeof(bufW
));
777 toolinfoW
.hwnd
= NULL
;
778 toolinfoW
.uId
= 0x1234ABCD;
779 toolinfoW
.lpszText
= bufW
;
780 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
781 textlen
= lstrlenW(toolinfoW
.lpszText
);
782 ok(textlen
== lenW
||
783 broken(textlen
== 0 && toolinfoW
.lpszText
== NULL
), /* nt4, kb186177 */
784 "lpszText has %d chars\n", textlen
);
790 static BOOL
almost_eq(int a
, int b
)
792 return a
-5<b
&& a
+5>b
;
795 static void test_track(void)
797 WCHAR textW
[] = {'t','e','x','t',0};
798 TTTOOLINFOW info
= { 0 };
803 parent
= CreateWindowExW(0, WC_STATICW
, NULL
, WS_CAPTION
| WS_VISIBLE
,
804 50, 50, 300, 300, NULL
, NULL
, NULL
, 0);
805 ok(parent
!= NULL
, "creation of parent window failed\n");
807 ShowWindow(parent
, SW_SHOWNORMAL
);
810 tt
= CreateWindowExW(WS_EX_TOPMOST
, TOOLTIPS_CLASSW
, NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
811 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
812 parent
, NULL
, GetModuleHandleW(NULL
), 0);
813 ok(tt
!= NULL
, "creation of tooltip window failed\n");
815 info
.cbSize
= TTTOOLINFOW_V1_SIZE
;
816 info
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
818 info
.hinst
= GetModuleHandleW(NULL
);
819 info
.lpszText
= textW
;
820 info
.uId
= (UINT_PTR
)parent
;
821 GetClientRect(parent
, &info
.rect
);
823 res
= SendMessageW(tt
, TTM_ADDTOOLW
, 0, (LPARAM
)&info
);
824 ok(res
, "adding the tool to the tooltip failed\n");
826 SendMessageW(tt
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
827 SendMessageW(tt
, TTM_TRACKACTIVATE
, (WPARAM
)TRUE
, (LPARAM
)&info
);
828 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
830 GetWindowRect(tt
, &pos
);
831 ok(almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
832 ok(almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
834 info
.uFlags
= TTF_IDISHWND
| TTF_ABSOLUTE
;
835 SendMessageW(tt
, TTM_SETTOOLINFOW
, 0, (LPARAM
)&info
);
836 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
838 GetWindowRect(tt
, &pos
);
839 ok(!almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
840 ok(!almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
843 DestroyWindow(parent
);
846 static LRESULT CALLBACK
info_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
855 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
860 static void test_setinfo(void)
864 HWND parent
, parent2
, hwndTip
, hwndTip2
;
865 TTTOOLINFOA toolInfo
= { 0 };
866 TTTOOLINFOA toolInfo2
= { 0 };
869 /* Create a class to use the custom draw wndproc */
870 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
873 wc
.hInstance
= GetModuleHandleA(NULL
);
875 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
876 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
877 wc
.lpszMenuName
= NULL
;
878 wc
.lpszClassName
= "SetInfoClass";
879 wc
.lpfnWndProc
= info_wnd_proc
;
882 /* Create a main window */
883 parent
= CreateWindowExA(0, "SetInfoClass", NULL
,
884 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
885 WS_MAXIMIZEBOX
| WS_VISIBLE
,
888 NULL
, NULL
, NULL
, 0);
889 ok(parent
!= NULL
, "Creation of main window failed\n");
891 parent2
= CreateWindowExA(0, "SetInfoClass", NULL
,
892 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
893 WS_MAXIMIZEBOX
| WS_VISIBLE
,
896 NULL
, NULL
, NULL
, 0);
897 ok(parent2
!= NULL
, "Creation of main window failed\n");
900 ShowWindow(parent2
, SW_SHOWNORMAL
);
904 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
905 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
906 CW_USEDEFAULT
, CW_USEDEFAULT
,
907 CW_USEDEFAULT
, CW_USEDEFAULT
,
908 parent
, NULL
, GetModuleHandleA(NULL
), 0);
909 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
911 hwndTip2
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
912 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
913 CW_USEDEFAULT
, CW_USEDEFAULT
,
914 CW_USEDEFAULT
, CW_USEDEFAULT
,
915 parent
, NULL
, GetModuleHandleA(NULL
), 0);
916 ok(hwndTip2
!= NULL
, "Creation of tooltip window failed\n");
919 /* Make it topmost, as per the MSDN */
920 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
921 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
924 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
925 toolInfo
.hwnd
= parent
;
926 toolInfo
.hinst
= GetModuleHandleA(NULL
);
927 toolInfo
.uFlags
= TTF_SUBCLASS
;
928 toolInfo
.uId
= 0x1234ABCD;
929 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
930 toolInfo
.lParam
= 0xdeadbeef;
931 GetClientRect (parent
, &toolInfo
.rect
);
932 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
933 ok(lResult
, "Adding the tool to the tooltip failed\n");
935 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
936 toolInfo
.hwnd
= parent2
;
937 toolInfo
.hinst
= GetModuleHandleA(NULL
);
939 toolInfo
.uId
= 0x1234ABCE;
940 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
941 toolInfo
.lParam
= 0xdeadbeef;
942 GetClientRect (parent
, &toolInfo
.rect
);
943 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
944 ok(lResult
, "Adding the tool to the tooltip failed\n");
946 /* Try to Remove Subclass */
947 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
948 toolInfo2
.hwnd
= parent
;
949 toolInfo2
.uId
= 0x1234ABCD;
950 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
951 ok(lResult
, "GetToolInfo failed\n");
952 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
, "uFlags does not have subclass\n");
953 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
954 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
956 toolInfo2
.uFlags
&= ~TTF_SUBCLASS
;
957 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
958 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
959 ok(lResult
, "GetToolInfo failed\n");
960 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
961 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent
, GWLP_WNDPROC
);
962 ok (wndProc
!= info_wnd_proc
, "Window Proc is wrong\n");
964 /* Try to Add Subclass */
966 /* Make it topmost, as per the MSDN */
967 SetWindowPos(hwndTip2
, HWND_TOPMOST
, 0, 0, 0, 0,
968 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
970 toolInfo2
.cbSize
= TTTOOLINFOA_V1_SIZE
;
971 toolInfo2
.hwnd
= parent2
;
972 toolInfo2
.uId
= 0x1234ABCE;
973 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
974 ok(lResult
, "GetToolInfo failed\n");
975 ok(!(toolInfo2
.uFlags
& TTF_SUBCLASS
), "uFlags has subclass\n");
976 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
977 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
979 toolInfo2
.uFlags
|= TTF_SUBCLASS
;
980 SendMessageA(hwndTip
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
981 lResult
= SendMessageA(hwndTip
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolInfo2
);
982 ok(lResult
, "GetToolInfo failed\n");
983 ok(toolInfo2
.uFlags
& TTF_SUBCLASS
, "uFlags does not have subclass\n");
984 wndProc
= (WNDPROC
)GetWindowLongPtrA(parent2
, GWLP_WNDPROC
);
985 ok (wndProc
== info_wnd_proc
, "Window Proc is wrong\n");
988 DestroyWindow(hwndTip
);
989 DestroyWindow(hwndTip2
);
990 DestroyWindow(parent
);
991 DestroyWindow(parent2
);
996 InitCommonControls();
998 test_create_tooltip();
1001 test_ttm_gettoolinfo();