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 "wine/test.h"
25 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
27 static void test_create_tooltip(void)
30 DWORD style
, exp_style
;
32 parent
= CreateWindowExA(0, "static", NULL
, WS_POPUP
,
35 ok(parent
!= NULL
, "failed to create parent wnd\n");
37 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0x7fffffff | WS_POPUP
,
39 parent
, NULL
, NULL
, 0);
40 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
42 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
43 trace("style = %08x\n", style
);
44 exp_style
= 0x7fffffff | WS_POPUP
;
45 exp_style
&= ~(WS_CHILD
| WS_MAXIMIZE
| WS_BORDER
| WS_DLGFRAME
);
46 ok(style
== exp_style
|| broken(style
== (exp_style
| WS_BORDER
)), /* nt4 */
47 "wrong style %08x/%08x\n", style
, exp_style
);
51 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
53 parent
, NULL
, NULL
, 0);
54 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
56 style
= GetWindowLongA(hwnd
, GWL_STYLE
);
57 trace("style = %08x\n", style
);
58 ok(style
== (WS_POPUP
| WS_CLIPSIBLINGS
| WS_BORDER
),
59 "wrong style %08x\n", style
);
63 DestroyWindow(parent
);
66 /* try to make sure pending X events have been processed before continuing */
67 static void flush_events(int waitTime
)
71 DWORD time
= GetTickCount() + waitTime
;
75 if (MsgWaitForMultipleObjects( 0, NULL
, FALSE
, min(100,diff
), QS_ALLEVENTS
) == WAIT_TIMEOUT
) break;
76 while (PeekMessageA( &msg
, 0, 0, 0, PM_REMOVE
)) DispatchMessageA( &msg
);
77 diff
= time
- GetTickCount();
82 static LRESULT CD_Result
;
85 #define TEST_CDDS_PREPAINT 0x00000001
86 #define TEST_CDDS_POSTPAINT 0x00000002
87 #define TEST_CDDS_PREERASE 0x00000004
88 #define TEST_CDDS_POSTERASE 0x00000008
89 #define TEST_CDDS_ITEMPREPAINT 0x00000010
90 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
91 #define TEST_CDDS_ITEMPREERASE 0x00000040
92 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
93 #define TEST_CDDS_SUBITEM 0x00000100
95 static LRESULT CALLBACK
custom_draw_wnd_proc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
104 if (((NMHDR
*)lParam
)->code
== NM_CUSTOMDRAW
) {
105 NMTTCUSTOMDRAW
*ttcd
= (NMTTCUSTOMDRAW
*) lParam
;
106 ok(ttcd
->nmcd
.hdr
.hwndFrom
== g_hwnd
, "Unexpected hwnd source %p (%p)\n",
107 ttcd
->nmcd
.hdr
.hwndFrom
, g_hwnd
);
108 ok(ttcd
->nmcd
.hdr
.idFrom
== 0x1234ABCD, "Unexpected id %x\n", (int)ttcd
->nmcd
.hdr
.idFrom
);
110 switch (ttcd
->nmcd
.dwDrawStage
) {
111 case CDDS_PREPAINT
: CD_Stages
|= TEST_CDDS_PREPAINT
; break;
112 case CDDS_POSTPAINT
: CD_Stages
|= TEST_CDDS_POSTPAINT
; break;
113 case CDDS_PREERASE
: CD_Stages
|= TEST_CDDS_PREERASE
; break;
114 case CDDS_POSTERASE
: CD_Stages
|= TEST_CDDS_POSTERASE
; break;
115 case CDDS_ITEMPREPAINT
: CD_Stages
|= TEST_CDDS_ITEMPREPAINT
; break;
116 case CDDS_ITEMPOSTPAINT
: CD_Stages
|= TEST_CDDS_ITEMPOSTPAINT
; break;
117 case CDDS_ITEMPREERASE
: CD_Stages
|= TEST_CDDS_ITEMPREERASE
; break;
118 case CDDS_ITEMPOSTERASE
: CD_Stages
|= TEST_CDDS_ITEMPOSTERASE
; break;
119 case CDDS_SUBITEM
: CD_Stages
|= TEST_CDDS_SUBITEM
; break;
120 default: CD_Stages
= -1;
123 if (ttcd
->nmcd
.dwDrawStage
== CDDS_PREPAINT
) return CD_Result
;
128 return DefWindowProcA(hWnd
, msg
, wParam
, lParam
);
134 static void test_customdraw(void) {
136 LRESULT FirstReturnValue
;
138 } expectedResults
[] = {
139 /* Valid notification responses */
140 {CDRF_DODEFAULT
, TEST_CDDS_PREPAINT
},
141 {CDRF_SKIPDEFAULT
, TEST_CDDS_PREPAINT
},
142 {CDRF_NOTIFYPOSTPAINT
, TEST_CDDS_PREPAINT
| TEST_CDDS_POSTPAINT
},
144 /* Invalid notification responses */
145 {CDRF_NOTIFYITEMDRAW
, TEST_CDDS_PREPAINT
},
146 {CDRF_NOTIFYPOSTERASE
, TEST_CDDS_PREPAINT
},
147 {CDRF_NEWFONT
, TEST_CDDS_PREPAINT
}
150 DWORD iterationNumber
;
154 /* Create a class to use the custom draw wndproc */
155 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
158 wc
.hInstance
= GetModuleHandleA(NULL
);
160 wc
.hCursor
= LoadCursorA(NULL
, (LPCSTR
)IDC_ARROW
);
161 wc
.hbrBackground
= GetSysColorBrush(COLOR_WINDOW
);
162 wc
.lpszMenuName
= NULL
;
163 wc
.lpszClassName
= "CustomDrawClass";
164 wc
.lpfnWndProc
= custom_draw_wnd_proc
;
167 for (iterationNumber
= 0;
168 iterationNumber
< sizeof(expectedResults
)/sizeof(expectedResults
[0]);
171 HWND parent
, hwndTip
;
173 TTTOOLINFOA toolInfo
= { 0 };
175 /* Create a main window */
176 parent
= CreateWindowExA(0, "CustomDrawClass", NULL
,
177 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
178 WS_MAXIMIZEBOX
| WS_VISIBLE
,
181 NULL
, NULL
, NULL
, 0);
182 ok(parent
!= NULL
, "Creation of main window failed\n");
185 ShowWindow(parent
, SW_SHOWNORMAL
);
189 hwndTip
= CreateWindowExA(WS_EX_TOPMOST
, TOOLTIPS_CLASSA
,
190 NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
191 CW_USEDEFAULT
, CW_USEDEFAULT
,
192 CW_USEDEFAULT
, CW_USEDEFAULT
,
193 parent
, NULL
, GetModuleHandleA(NULL
), 0);
194 ok(hwndTip
!= NULL
, "Creation of tooltip window failed\n");
196 /* Set up parms for the wndproc to handle */
198 CD_Result
= expectedResults
[iterationNumber
].FirstReturnValue
;
201 /* Make it topmost, as per the MSDN */
202 SetWindowPos(hwndTip
, HWND_TOPMOST
, 0, 0, 0, 0,
203 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
206 toolInfo
.cbSize
= TTTOOLINFOA_V1_SIZE
;
207 toolInfo
.hwnd
= parent
;
208 toolInfo
.hinst
= GetModuleHandleA(NULL
);
209 toolInfo
.uFlags
= TTF_SUBCLASS
;
210 toolInfo
.uId
= 0x1234ABCD;
211 toolInfo
.lpszText
= (LPSTR
)"This is a test tooltip";
212 toolInfo
.lParam
= 0xdeadbeef;
213 GetClientRect (parent
, &toolInfo
.rect
);
214 lResult
= SendMessageA(hwndTip
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolInfo
);
215 ok(lResult
, "Adding the tool to the tooltip failed\n");
217 /* Make tooltip appear quickly */
218 SendMessageA(hwndTip
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
220 /* Put cursor inside window, tooltip will appear immediately */
221 GetWindowRect( parent
, &rect
);
222 SetCursorPos( (rect
.left
+ rect
.right
) / 2, (rect
.top
+ rect
.bottom
) / 2 );
227 /* Check CustomDraw results */
228 ok(CD_Stages
== expectedResults
[iterationNumber
].ExpectedCalls
||
229 broken(CD_Stages
== (expectedResults
[iterationNumber
].ExpectedCalls
& ~TEST_CDDS_POSTPAINT
)), /* nt4 */
230 "CustomDraw run %d stages %x, expected %x\n", iterationNumber
, CD_Stages
,
231 expectedResults
[iterationNumber
].ExpectedCalls
);
235 DestroyWindow(hwndTip
);
236 DestroyWindow(parent
);
242 static const CHAR testcallbackA
[] = "callback";
244 static LRESULT WINAPI
parent_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
246 if (message
== WM_NOTIFY
&& lParam
)
248 NMTTDISPINFOA
*ttnmdi
= (NMTTDISPINFOA
*)lParam
;
250 if (ttnmdi
->hdr
.code
== TTN_GETDISPINFOA
)
251 lstrcpyA(ttnmdi
->lpszText
, testcallbackA
);
254 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
257 static BOOL
register_parent_wnd_class(void)
262 cls
.lpfnWndProc
= parent_wnd_proc
;
265 cls
.hInstance
= GetModuleHandleA(NULL
);
267 cls
.hCursor
= LoadCursorA(0, (LPCSTR
)IDC_ARROW
);
268 cls
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
269 cls
.lpszMenuName
= NULL
;
270 cls
.lpszClassName
= "Tooltips test parent class";
271 return RegisterClassA(&cls
);
274 static HWND
create_parent_window(void)
276 if (!register_parent_wnd_class())
279 return CreateWindowExA(0, "Tooltips test parent class",
280 "Tooltips test parent window",
281 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
|
282 WS_MAXIMIZEBOX
| WS_VISIBLE
,
284 GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
287 static void test_gettext(void)
290 TTTOOLINFOA toolinfoA
;
291 TTTOOLINFOW toolinfoW
;
294 WCHAR bufW
[10] = { 0 };
295 static const CHAR testtipA
[] = "testtip";
297 notify
= create_parent_window();
298 ok(notify
!= NULL
, "Expected notification window to be created\n");
300 /* For bug 14790 - lpszText is NULL */
301 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
303 NULL
, NULL
, NULL
, 0);
304 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
306 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
307 /* otherwise it crashes on the NULL lpszText */
308 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
309 toolinfoA
.hwnd
= NULL
;
310 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
311 toolinfoA
.uFlags
= 0;
312 toolinfoA
.uId
= 0x1234ABCD;
313 toolinfoA
.lpszText
= NULL
;
314 toolinfoA
.lParam
= 0xdeadbeef;
315 GetClientRect(hwnd
, &toolinfoA
.rect
);
316 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
319 toolinfoA
.hwnd
= NULL
;
320 toolinfoA
.uId
= 0x1234ABCD;
321 toolinfoA
.lpszText
= bufA
;
322 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
323 ok(strcmp(toolinfoA
.lpszText
, "") == 0, "lpszText should be an empty string\n");
325 toolinfoA
.lpszText
= bufA
;
326 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
327 ok(toolinfoA
.lpszText
== NULL
,
328 "expected NULL, got %p\n", toolinfoA
.lpszText
);
332 win_skip( "Old comctl32, not testing NULL text\n" );
333 DestroyWindow( hwnd
);
337 /* add another tool with text */
338 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
339 toolinfoA
.hwnd
= NULL
;
340 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
341 toolinfoA
.uFlags
= 0;
342 toolinfoA
.uId
= 0x1235ABCD;
343 strcpy(bufA
, testtipA
);
344 toolinfoA
.lpszText
= bufA
;
345 toolinfoA
.lParam
= 0xdeadbeef;
346 GetClientRect(hwnd
, &toolinfoA
.rect
);
347 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
348 ok(r
, "Adding the tool to the tooltip failed\n");
353 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
354 ok(length
== 0, "Expected 0, got %d\n", length
);
356 toolinfoA
.hwnd
= NULL
;
357 toolinfoA
.uId
= 0x1235ABCD;
358 toolinfoA
.lpszText
= bufA
;
359 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
360 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0, "lpszText should be an empty string\n");
362 memset(bufA
, 0x1f, sizeof(bufA
));
363 toolinfoA
.lpszText
= bufA
;
364 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
365 ok(strcmp(toolinfoA
.lpszText
, testtipA
) == 0,
366 "expected %s, got %p\n", testtipA
, toolinfoA
.lpszText
);
368 length
= SendMessageA(hwnd
, WM_GETTEXTLENGTH
, 0, 0);
369 ok(length
== 0, "Expected 0, got %d\n", length
);
372 /* add another with callback text */
373 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
374 toolinfoA
.hwnd
= notify
;
375 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
376 toolinfoA
.uFlags
= 0;
377 toolinfoA
.uId
= 0x1236ABCD;
378 toolinfoA
.lpszText
= LPSTR_TEXTCALLBACKA
;
379 toolinfoA
.lParam
= 0xdeadbeef;
380 GetClientRect(hwnd
, &toolinfoA
.rect
);
381 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
382 ok(r
, "Adding the tool to the tooltip failed\n");
385 toolinfoA
.hwnd
= notify
;
386 toolinfoA
.uId
= 0x1236ABCD;
387 toolinfoA
.lpszText
= bufA
;
388 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
389 ok(strcmp(toolinfoA
.lpszText
, testcallbackA
) == 0,
390 "lpszText should be an (%s) string\n", testcallbackA
);
392 toolinfoA
.lpszText
= bufA
;
393 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
394 ok(toolinfoA
.lpszText
== LPSTR_TEXTCALLBACKA
,
395 "expected LPSTR_TEXTCALLBACKA, got %p\n", toolinfoA
.lpszText
);
399 DestroyWindow(notify
);
401 SetLastError(0xdeadbeef);
402 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
404 NULL
, NULL
, NULL
, 0);
406 if (!hwnd
&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED
) {
407 win_skip("CreateWindowExW is not implemented\n");
410 ok(hwnd
!= NULL
, "failed to create tooltip wnd\n");
412 toolinfoW
.cbSize
= sizeof(TTTOOLINFOW
);
413 toolinfoW
.hwnd
= NULL
;
414 toolinfoW
.hinst
= GetModuleHandleA(NULL
);
415 toolinfoW
.uFlags
= 0;
416 toolinfoW
.uId
= 0x1234ABCD;
417 toolinfoW
.lpszText
= NULL
;
418 toolinfoW
.lParam
= 0xdeadbeef;
419 GetClientRect(hwnd
, &toolinfoW
.rect
);
420 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
421 ok(!r
, "Adding the tool to the tooltip succeeded!\n");
423 if (0) /* crashes on NT4 */
425 toolinfoW
.hwnd
= NULL
;
426 toolinfoW
.uId
= 0x1234ABCD;
427 toolinfoW
.lpszText
= bufW
;
428 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
429 ok(toolinfoW
.lpszText
[0] == 0, "lpszText should be an empty string\n");
435 static void test_ttm_gettoolinfo(void)
442 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
444 NULL
, NULL
, NULL
, 0);
446 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
448 ti
.hinst
= GetModuleHandleA(NULL
);
452 ti
.lParam
= 0x1abe11ed;
453 GetClientRect(hwnd
, &ti
.rect
);
454 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
455 ok(r
, "Adding the tool to the tooltip failed\n");
457 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
458 ti
.lParam
= 0xaaaaaaaa;
459 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
460 ok(r
, "Getting tooltip info failed\n");
461 ok(0x1abe11ed == ti
.lParam
||
462 broken(0x1abe11ed != ti
.lParam
), /* comctl32 < 5.81 */
463 "Expected 0x1abe11ed, got %lx\n", ti
.lParam
);
465 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
467 tiW
.uId
= 0x1234ABCD;
468 tiW
.lParam
= 0xaaaaaaaa;
469 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&tiW
);
470 ok(r
, "Getting tooltip info failed\n");
471 ok(0x1abe11ed == tiW
.lParam
||
472 broken(0x1abe11ed != tiW
.lParam
), /* comctl32 < 5.81 */
473 "Expected 0x1abe11ed, got %lx\n", tiW
.lParam
);
475 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
477 ti
.lParam
= 0x55555555;
478 SendMessageA(hwnd
, TTM_SETTOOLINFOA
, 0, (LPARAM
)&ti
);
480 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
;
481 ti
.lParam
= 0xdeadbeef;
482 r
= SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&ti
);
483 ok(r
, "Getting tooltip info failed\n");
484 ok(0x55555555 == ti
.lParam
||
485 broken(0x55555555 != ti
.lParam
), /* comctl32 < 5.81 */
486 "Expected 0x55555555, got %lx\n", ti
.lParam
);
490 /* 1. test size parameter validation rules (ansi messages) */
491 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
493 NULL
, NULL
, NULL
, 0);
495 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
497 ti
.hinst
= GetModuleHandleA(NULL
);
501 ti
.lParam
= 0xdeadbeef;
502 GetClientRect(hwnd
, &ti
.rect
);
503 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
504 ok(r
, "Adding the tool to the tooltip failed\n");
505 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
508 ti
.cbSize
= TTTOOLINFOA_V1_SIZE
- 1;
511 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
512 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
515 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
517 ti
.hinst
= GetModuleHandleA(NULL
);
521 ti
.lParam
= 0xdeadbeef;
522 GetClientRect(hwnd
, &ti
.rect
);
523 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
524 ok(r
, "Adding the tool to the tooltip failed\n");
525 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
528 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
- 1;
531 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
532 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
535 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
537 ti
.hinst
= GetModuleHandleA(NULL
);
541 ti
.lParam
= 0xdeadbeef;
542 GetClientRect(hwnd
, &ti
.rect
);
543 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&ti
);
544 ok(r
, "Adding the tool to the tooltip failed\n");
545 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
548 ti
.cbSize
= TTTOOLINFOA_V2_SIZE
+ 1;
551 SendMessageA(hwnd
, TTM_DELTOOLA
, 0, (LPARAM
)&ti
);
552 r
= SendMessageA(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
557 /* 2. test size parameter validation rules (w-messages) */
558 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
560 NULL
, NULL
, NULL
, 0);
563 win_skip("CreateWindowExW() not supported. Skipping.\n");
567 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
569 tiW
.hinst
= GetModuleHandleA(NULL
);
571 tiW
.uId
= 0x1234ABCD;
573 tiW
.lParam
= 0xdeadbeef;
574 GetClientRect(hwnd
, &tiW
.rect
);
575 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
576 ok(r
, "Adding the tool to the tooltip failed\n");
577 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
580 tiW
.cbSize
= TTTOOLINFOW_V1_SIZE
- 1;
582 tiW
.uId
= 0x1234ABCD;
583 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
584 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
587 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
589 tiW
.hinst
= GetModuleHandleA(NULL
);
591 tiW
.uId
= 0x1234ABCD;
593 tiW
.lParam
= 0xdeadbeef;
594 GetClientRect(hwnd
, &tiW
.rect
);
595 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&tiW
);
596 ok(r
, "Adding the tool to the tooltip failed\n");
597 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
600 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
- 1;
602 tiW
.uId
= 0x1234ABCD;
603 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
604 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
607 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
609 tiW
.hinst
= GetModuleHandleA(NULL
);
611 tiW
.uId
= 0x1234ABCD;
613 tiW
.lParam
= 0xdeadbeef;
614 GetClientRect(hwnd
, &tiW
.rect
);
615 r
= SendMessageW(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&tiW
);
616 ok(r
, "Adding the tool to the tooltip failed\n");
617 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
619 /* looks like TTM_DELTOOLW doesn't work with invalid size */
620 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
+ 1;
622 tiW
.uId
= 0x1234ABCD;
623 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
624 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
627 tiW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
629 tiW
.uId
= 0x1234ABCD;
630 SendMessageW(hwnd
, TTM_DELTOOLW
, 0, (LPARAM
)&tiW
);
631 r
= SendMessageW(hwnd
, TTM_GETTOOLCOUNT
, 0, 0);
637 static void test_longtextA(void)
639 static const char longtextA
[] =
640 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
641 "80 chars including null. In fact, the buffer is not null-terminated.";
643 TTTOOLINFOA toolinfoA
= { 0 };
647 hwnd
= CreateWindowExA(0, TOOLTIPS_CLASSA
, NULL
, 0,
649 NULL
, NULL
, NULL
, 0);
650 toolinfoA
.cbSize
= sizeof(TTTOOLINFOA
);
651 toolinfoA
.hwnd
= NULL
;
652 toolinfoA
.hinst
= GetModuleHandleA(NULL
);
653 toolinfoA
.uFlags
= 0;
654 toolinfoA
.uId
= 0x1234ABCD;
655 strcpy(bufA
, longtextA
);
656 toolinfoA
.lpszText
= bufA
;
657 toolinfoA
.lParam
= 0xdeadbeef;
658 GetClientRect(hwnd
, &toolinfoA
.rect
);
659 r
= SendMessageA(hwnd
, TTM_ADDTOOLA
, 0, (LPARAM
)&toolinfoA
);
663 memset(bufA
, 0, sizeof(bufA
));
664 toolinfoA
.hwnd
= NULL
;
665 toolinfoA
.uId
= 0xABCD1234;
666 toolinfoA
.lpszText
= bufA
;
667 SendMessageA(hwnd
, TTM_ENUMTOOLSA
, 0, (LPARAM
)&toolinfoA
);
668 textlen
= lstrlenA(toolinfoA
.lpszText
);
669 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
670 ok(toolinfoA
.uId
== 0x1234ABCD,
671 "uId should be retrieved, got %p\n", (void*)toolinfoA
.uId
);
673 memset(bufA
, 0, sizeof(bufA
));
674 toolinfoA
.hwnd
= NULL
;
675 toolinfoA
.uId
= 0x1234ABCD;
676 toolinfoA
.lpszText
= bufA
;
677 SendMessageA(hwnd
, TTM_GETTOOLINFOA
, 0, (LPARAM
)&toolinfoA
);
678 textlen
= lstrlenA(toolinfoA
.lpszText
);
679 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
681 memset(bufA
, 0, sizeof(bufA
));
682 toolinfoA
.hwnd
= NULL
;
683 toolinfoA
.uId
= 0x1234ABCD;
684 toolinfoA
.lpszText
= bufA
;
685 SendMessageA(hwnd
, TTM_GETTEXTA
, 0, (LPARAM
)&toolinfoA
);
686 textlen
= lstrlenA(toolinfoA
.lpszText
);
687 ok(textlen
== 80, "lpszText has %d chars\n", textlen
);
693 static void test_longtextW(void)
695 static const char longtextA
[] =
696 "According to MSDN, TTM_ENUMTOOLS claims that TOOLINFO's lpszText is maximum "
697 "80 chars including null. Actually, this is not applied for wide version.";
699 TTTOOLINFOW toolinfoW
= { 0 };
704 hwnd
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
706 NULL
, NULL
, NULL
, 0);
709 win_skip("CreateWindowExW() not supported. Skipping.\n");
713 toolinfoW
.cbSize
= TTTOOLINFOW_V2_SIZE
;
714 toolinfoW
.hwnd
= NULL
;
715 toolinfoW
.hinst
= GetModuleHandleW(NULL
);
716 toolinfoW
.uFlags
= 0;
717 toolinfoW
.uId
= 0x1234ABCD;
718 MultiByteToWideChar(CP_ACP
, 0, longtextA
, -1, bufW
, sizeof(bufW
)/sizeof(bufW
[0]));
719 lenW
= lstrlenW(bufW
);
720 toolinfoW
.lpszText
= bufW
;
721 toolinfoW
.lParam
= 0xdeadbeef;
722 GetClientRect(hwnd
, &toolinfoW
.rect
);
723 r
= SendMessageW(hwnd
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfoW
);
727 memset(bufW
, 0, sizeof(bufW
));
728 toolinfoW
.hwnd
= NULL
;
729 toolinfoW
.uId
= 0xABCD1234;
730 toolinfoW
.lpszText
= bufW
;
731 SendMessageW(hwnd
, TTM_ENUMTOOLSW
, 0, (LPARAM
)&toolinfoW
);
732 textlen
= lstrlenW(toolinfoW
.lpszText
);
733 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
734 ok(toolinfoW
.uId
== 0x1234ABCD,
735 "uId should be retrieved, got %p\n", (void*)toolinfoW
.uId
);
737 memset(bufW
, 0, sizeof(bufW
));
738 toolinfoW
.hwnd
= NULL
;
739 toolinfoW
.uId
= 0x1234ABCD;
740 toolinfoW
.lpszText
= bufW
;
741 SendMessageW(hwnd
, TTM_GETTOOLINFOW
, 0, (LPARAM
)&toolinfoW
);
742 textlen
= lstrlenW(toolinfoW
.lpszText
);
743 ok(textlen
== lenW
, "lpszText has %d chars\n", textlen
);
745 memset(bufW
, 0, sizeof(bufW
));
746 toolinfoW
.hwnd
= NULL
;
747 toolinfoW
.uId
= 0x1234ABCD;
748 toolinfoW
.lpszText
= bufW
;
749 SendMessageW(hwnd
, TTM_GETTEXTW
, 0, (LPARAM
)&toolinfoW
);
750 textlen
= lstrlenW(toolinfoW
.lpszText
);
751 ok(textlen
== lenW
||
752 broken(textlen
== 0 && toolinfoW
.lpszText
== NULL
), /* nt4, kb186177 */
753 "lpszText has %d chars\n", textlen
);
759 static BOOL
almost_eq(int a
, int b
)
761 return a
-5<b
&& a
+5>b
;
764 static void test_track(void)
766 WCHAR textW
[] = {'t','e','x','t',0};
767 TTTOOLINFOW info
= { 0 };
772 parent
= CreateWindowExW(0, WC_STATICW
, NULL
, WS_CAPTION
| WS_VISIBLE
,
773 50, 50, 300, 300, NULL
, NULL
, NULL
, 0);
774 ok(parent
!= NULL
, "creation of parent window failed\n");
776 ShowWindow(parent
, SW_SHOWNORMAL
);
779 tt
= CreateWindowExW(WS_EX_TOPMOST
, TOOLTIPS_CLASSW
, NULL
, TTS_NOPREFIX
| TTS_ALWAYSTIP
,
780 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
781 parent
, NULL
, GetModuleHandleW(NULL
), 0);
782 ok(tt
!= NULL
, "creation of tooltip window failed\n");
784 info
.cbSize
= TTTOOLINFOW_V1_SIZE
;
785 info
.uFlags
= TTF_IDISHWND
| TTF_TRACK
| TTF_ABSOLUTE
;
787 info
.hinst
= GetModuleHandleW(NULL
);
788 info
.lpszText
= textW
;
789 info
.uId
= (UINT_PTR
)parent
;
790 GetClientRect(parent
, &info
.rect
);
792 res
= SendMessageW(tt
, TTM_ADDTOOLW
, 0, (LPARAM
)&info
);
793 ok(res
, "adding the tool to the tooltip failed\n");
795 SendMessageW(tt
, TTM_SETDELAYTIME
, TTDT_INITIAL
, MAKELPARAM(1,0));
796 SendMessageW(tt
, TTM_TRACKACTIVATE
, (WPARAM
)TRUE
, (LPARAM
)&info
);
797 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
799 GetWindowRect(tt
, &pos
);
800 ok(almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
801 ok(almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
803 info
.uFlags
= TTF_IDISHWND
| TTF_ABSOLUTE
;
804 SendMessageW(tt
, TTM_SETTOOLINFOW
, 0, (LPARAM
)&info
);
805 SendMessageW(tt
, TTM_TRACKPOSITION
, 0, MAKELPARAM(10, 10));
807 GetWindowRect(tt
, &pos
);
808 ok(!almost_eq(pos
.left
, 10), "pos.left = %d\n", pos
.left
);
809 ok(!almost_eq(pos
.top
, 10), "pos.top = %d\n", pos
.top
);
812 DestroyWindow(parent
);
817 InitCommonControls();
819 test_create_tooltip();
822 test_ttm_gettoolinfo();