comctl32/tooltips: Remove redundant code, let handlers deal with A<->W conversions.
[wine] / dlls / comctl32 / tests / tooltips.c
1 /*
2  * Copyright 2005 Dmitry Timoshkov
3  * Copyright 2008 Jason Edmeades
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <assert.h>
21 #include <windows.h>
22 #include <commctrl.h>
23
24 #include "wine/test.h"
25
26 #define expect(expected, got) ok(got == expected, "Expected %d, got %d\n", expected, got)
27
28 static void test_create_tooltip(void)
29 {
30     HWND parent, hwnd;
31     DWORD style, exp_style;
32
33     parent = CreateWindowEx(0, "static", NULL, WS_POPUP,
34                           0, 0, 0, 0,
35                           NULL, NULL, NULL, 0);
36     assert(parent);
37
38     hwnd = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, 0x7fffffff | WS_POPUP,
39                           10, 10, 300, 100,
40                           parent, NULL, NULL, 0);
41     assert(hwnd);
42
43     style = GetWindowLong(hwnd, GWL_STYLE);
44     trace("style = %08x\n", style);
45     exp_style = 0x7fffffff | WS_POPUP;
46     exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME);
47     ok(style == exp_style || broken(style == (exp_style | WS_BORDER)), /* nt4 */
48        "wrong style %08x/%08x\n", style, exp_style);
49
50     DestroyWindow(hwnd);
51
52     hwnd = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, 0,
53                           10, 10, 300, 100,
54                           parent, NULL, NULL, 0);
55     assert(hwnd);
56
57     style = GetWindowLong(hwnd, GWL_STYLE);
58     trace("style = %08x\n", style);
59     ok(style == (WS_POPUP | WS_CLIPSIBLINGS | WS_BORDER),
60        "wrong style %08x\n", style);
61
62     DestroyWindow(hwnd);
63
64     DestroyWindow(parent);
65 }
66
67 /* try to make sure pending X events have been processed before continuing */
68 static void flush_events(int waitTime)
69 {
70     MSG msg;
71     int diff = waitTime;
72     DWORD time = GetTickCount() + waitTime;
73
74     while (diff > 0)
75     {
76         if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min(100,diff), QS_ALLEVENTS) == WAIT_TIMEOUT) break;
77         while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
78         diff = time - GetTickCount();
79     }
80 }
81
82 static int CD_Stages;
83 static LRESULT CD_Result;
84 static HWND g_hwnd;
85
86 #define TEST_CDDS_PREPAINT           0x00000001
87 #define TEST_CDDS_POSTPAINT          0x00000002
88 #define TEST_CDDS_PREERASE           0x00000004
89 #define TEST_CDDS_POSTERASE          0x00000008
90 #define TEST_CDDS_ITEMPREPAINT       0x00000010
91 #define TEST_CDDS_ITEMPOSTPAINT      0x00000020
92 #define TEST_CDDS_ITEMPREERASE       0x00000040
93 #define TEST_CDDS_ITEMPOSTERASE      0x00000080
94 #define TEST_CDDS_SUBITEM            0x00000100
95
96 static LRESULT CALLBACK CustomDrawWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
97 {
98     switch(msg) {
99
100     case WM_DESTROY:
101         PostQuitMessage(0);
102         break;
103
104     case WM_NOTIFY:
105         if (((NMHDR *)lParam)->code == NM_CUSTOMDRAW) {
106             NMTTCUSTOMDRAW *ttcd = (NMTTCUSTOMDRAW*) lParam;
107             ok(ttcd->nmcd.hdr.hwndFrom == g_hwnd, "Unexpected hwnd source %p (%p)\n",
108                  ttcd->nmcd.hdr.hwndFrom, g_hwnd);
109             ok(ttcd->nmcd.hdr.idFrom == 0x1234ABCD, "Unexpected id %x\n", (int)ttcd->nmcd.hdr.idFrom);
110
111             switch (ttcd->nmcd.dwDrawStage) {
112             case CDDS_PREPAINT     : CD_Stages |= TEST_CDDS_PREPAINT; break;
113             case CDDS_POSTPAINT    : CD_Stages |= TEST_CDDS_POSTPAINT; break;
114             case CDDS_PREERASE     : CD_Stages |= TEST_CDDS_PREERASE; break;
115             case CDDS_POSTERASE    : CD_Stages |= TEST_CDDS_POSTERASE; break;
116             case CDDS_ITEMPREPAINT : CD_Stages |= TEST_CDDS_ITEMPREPAINT; break;
117             case CDDS_ITEMPOSTPAINT: CD_Stages |= TEST_CDDS_ITEMPOSTPAINT; break;
118             case CDDS_ITEMPREERASE : CD_Stages |= TEST_CDDS_ITEMPREERASE; break;
119             case CDDS_ITEMPOSTERASE: CD_Stages |= TEST_CDDS_ITEMPOSTERASE; break;
120             case CDDS_SUBITEM      : CD_Stages |= TEST_CDDS_SUBITEM; break;
121             default: CD_Stages = -1;
122             }
123
124             if (ttcd->nmcd.dwDrawStage == CDDS_PREPAINT) return CD_Result;
125         }
126         /* drop through */
127
128     default:
129         return DefWindowProcA(hWnd, msg, wParam, lParam);
130     }
131
132     return 0L;
133 }
134
135 static void test_customdraw(void) {
136     static struct {
137         LRESULT FirstReturnValue;
138         int ExpectedCalls;
139     } expectedResults[] = {
140         /* Valid notification responses */
141         {CDRF_DODEFAULT, TEST_CDDS_PREPAINT},
142         {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT},
143         {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT},
144
145         /* Invalid notification responses */
146         {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
147         {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
148         {CDRF_NEWFONT, TEST_CDDS_PREPAINT}
149     };
150
151    int       iterationNumber;
152    WNDCLASSA wc;
153    LRESULT   lResult;
154
155    /* Create a class to use the custom draw wndproc */
156    wc.style = CS_HREDRAW | CS_VREDRAW;
157    wc.cbClsExtra = 0;
158    wc.cbWndExtra = 0;
159    wc.hInstance = GetModuleHandleA(NULL);
160    wc.hIcon = NULL;
161    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
162    wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
163    wc.lpszMenuName = NULL;
164    wc.lpszClassName = "CustomDrawClass";
165    wc.lpfnWndProc = CustomDrawWndProc;
166    RegisterClass(&wc);
167
168    for (iterationNumber = 0;
169         iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]);
170         iterationNumber++) {
171
172        HWND parent, hwndTip;
173        RECT rect;
174        TOOLINFO toolInfo = { 0 };
175
176        /* Create a main window */
177        parent = CreateWindowEx(0, "CustomDrawClass", NULL,
178                                WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
179                                WS_MAXIMIZEBOX | WS_VISIBLE,
180                                50, 50,
181                                300, 300,
182                                NULL, NULL, NULL, 0);
183        ok(parent != NULL, "Creation of main window failed\n");
184
185        /* Make it show */
186        ShowWindow(parent, SW_SHOWNORMAL);
187        flush_events(100);
188
189        /* Create Tooltip */
190        hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS,
191                                 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
192                                 CW_USEDEFAULT, CW_USEDEFAULT,
193                                 CW_USEDEFAULT, CW_USEDEFAULT,
194                                 parent, NULL, GetModuleHandleA(NULL), 0);
195        ok(hwndTip != NULL, "Creation of tooltip window failed\n");
196
197        /* Set up parms for the wndproc to handle */
198        CD_Stages = 0;
199        CD_Result = expectedResults[iterationNumber].FirstReturnValue;
200        g_hwnd    = hwndTip;
201
202        /* Make it topmost, as per the MSDN */
203        SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
204              SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
205
206        /* Create a tool */
207        toolInfo.cbSize = TTTOOLINFO_V1_SIZE;
208        toolInfo.hwnd = parent;
209        toolInfo.hinst = GetModuleHandleA(NULL);
210        toolInfo.uFlags = TTF_SUBCLASS;
211        toolInfo.uId = 0x1234ABCD;
212        toolInfo.lpszText = (LPSTR)"This is a test tooltip";
213        toolInfo.lParam = 0xdeadbeef;
214        GetClientRect (parent, &toolInfo.rect);
215        lResult = SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
216        ok(lResult, "Adding the tool to the tooltip failed\n");
217
218        /* Make tooltip appear quickly */
219        SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
220
221        /* Put cursor inside window, tooltip will appear immediately */
222        GetWindowRect( parent, &rect );
223        SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
224        flush_events(200);
225
226        if (CD_Stages)
227        {
228            /* Check CustomDraw results */
229            ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls ||
230               broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */
231               "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
232               expectedResults[iterationNumber].ExpectedCalls);
233        }
234
235        /* Clean up */
236        DestroyWindow(hwndTip);
237        DestroyWindow(parent);
238    }
239
240
241 }
242
243 static const CHAR testcallbackA[]  = "callback";
244
245 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
246 {
247     if (message == WM_NOTIFY && lParam)
248     {
249         NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
250
251         if (ttnmdi->hdr.code == TTN_GETDISPINFOA)
252             lstrcpy(ttnmdi->lpszText, testcallbackA);
253     }
254
255     return DefWindowProcA(hwnd, message, wParam, lParam);
256 }
257
258 static BOOL register_parent_wnd_class(void)
259 {
260     WNDCLASSA cls;
261
262     cls.style = 0;
263     cls.lpfnWndProc = parent_wnd_proc;
264     cls.cbClsExtra = 0;
265     cls.cbWndExtra = 0;
266     cls.hInstance = GetModuleHandleA(NULL);
267     cls.hIcon = 0;
268     cls.hCursor = LoadCursorA(0, IDC_ARROW);
269     cls.hbrBackground = GetStockObject(WHITE_BRUSH);
270     cls.lpszMenuName = NULL;
271     cls.lpszClassName = "Tooltips test parent class";
272     return RegisterClassA(&cls);
273 }
274
275 static HWND create_parent_window(void)
276 {
277     if (!register_parent_wnd_class())
278         return NULL;
279
280     return CreateWindowEx(0, "Tooltips test parent class",
281                           "Tooltips test parent window",
282                           WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
283                           WS_MAXIMIZEBOX | WS_VISIBLE,
284                           0, 0, 100, 100,
285                           GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
286 }
287
288 static void test_gettext(void)
289 {
290     HWND hwnd, notify;
291     TTTOOLINFOA toolinfoA;
292     TTTOOLINFOW toolinfoW;
293     LRESULT r;
294     CHAR bufA[10] = "";
295     WCHAR bufW[10] = { 0 };
296     static const CHAR testtipA[] = "testtip";
297
298     notify = create_parent_window();
299     ok(notify != NULL, "Expected notification window to be created\n");
300
301     /* For bug 14790 - lpszText is NULL */
302     hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
303                            10, 10, 300, 100,
304                            NULL, NULL, NULL, 0);
305     assert(hwnd);
306
307     /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
308     /* otherwise it crashes on the NULL lpszText */
309     toolinfoA.cbSize = sizeof(TTTOOLINFOA);
310     toolinfoA.hwnd = NULL;
311     toolinfoA.hinst = GetModuleHandleA(NULL);
312     toolinfoA.uFlags = 0;
313     toolinfoA.uId = 0x1234ABCD;
314     toolinfoA.lpszText = NULL;
315     toolinfoA.lParam = 0xdeadbeef;
316     GetClientRect(hwnd, &toolinfoA.rect);
317     r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
318     if (r)
319     {
320         toolinfoA.hwnd = NULL;
321         toolinfoA.uId = 0x1234ABCD;
322         toolinfoA.lpszText = bufA;
323         SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
324         ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
325     }
326     else
327     {
328         win_skip( "Old comctl32, not testing NULL text\n" );
329         DestroyWindow( hwnd );
330         return;
331     }
332
333     /* add another tool with text */
334     toolinfoA.cbSize = sizeof(TTTOOLINFOA);
335     toolinfoA.hwnd = NULL;
336     toolinfoA.hinst = GetModuleHandleA(NULL);
337     toolinfoA.uFlags = 0;
338     toolinfoA.uId = 0x1235ABCD;
339     strcpy(bufA, testtipA);
340     toolinfoA.lpszText = bufA;
341     toolinfoA.lParam = 0xdeadbeef;
342     GetClientRect(hwnd, &toolinfoA.rect);
343     r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
344     ok(r, "Adding the tool to the tooltip failed\n");
345     if (r)
346     {
347         DWORD length;
348
349         length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
350         ok(length == 0, "Expected 0, got %d\n", length);
351
352         toolinfoA.hwnd = NULL;
353         toolinfoA.uId = 0x1235ABCD;
354         toolinfoA.lpszText = bufA;
355         SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
356         ok(strcmp(toolinfoA.lpszText, testtipA) == 0, "lpszText should be an empty string\n");
357
358         length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
359         ok(length == 0, "Expected 0, got %d\n", length);
360     }
361
362     /* add another with callback text */
363     toolinfoA.cbSize = sizeof(TTTOOLINFOA);
364     toolinfoA.hwnd = notify;
365     toolinfoA.hinst = GetModuleHandleA(NULL);
366     toolinfoA.uFlags = 0;
367     toolinfoA.uId = 0x1236ABCD;
368     toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
369     toolinfoA.lParam = 0xdeadbeef;
370     GetClientRect(hwnd, &toolinfoA.rect);
371     r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
372     ok(r, "Adding the tool to the tooltip failed\n");
373     if (r)
374     {
375         toolinfoA.hwnd = notify;
376         toolinfoA.uId = 0x1236ABCD;
377         toolinfoA.lpszText = bufA;
378         SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
379         ok(strcmp(toolinfoA.lpszText, testcallbackA) == 0,
380            "lpszText should be an (%s) string\n", testcallbackA);
381     }
382
383     DestroyWindow(hwnd);
384     DestroyWindow(notify);
385
386     SetLastError(0xdeadbeef);
387     hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
388                            10, 10, 300, 100,
389                            NULL, NULL, NULL, 0);
390
391     if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
392         win_skip("CreateWindowExW is not implemented\n");
393         return;
394     }
395
396     assert(hwnd);
397
398     toolinfoW.cbSize = sizeof(TTTOOLINFOW);
399     toolinfoW.hwnd = NULL;
400     toolinfoW.hinst = GetModuleHandleA(NULL);
401     toolinfoW.uFlags = 0;
402     toolinfoW.uId = 0x1234ABCD;
403     toolinfoW.lpszText = NULL;
404     toolinfoW.lParam = 0xdeadbeef;
405     GetClientRect(hwnd, &toolinfoW.rect);
406     r = SendMessageW(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoW);
407     ok(r, "Adding the tool to the tooltip failed\n");
408
409     if (0)  /* crashes on NT4 */
410     {
411         toolinfoW.hwnd = NULL;
412         toolinfoW.uId = 0x1234ABCD;
413         toolinfoW.lpszText = bufW;
414         SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
415         ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n");
416     }
417
418     DestroyWindow(hwnd);
419 }
420
421 static void test_ttm_gettoolinfo(void)
422 {
423     TTTOOLINFOA ti;
424     TTTOOLINFOW tiW;
425     HWND hwnd;
426     DWORD r;
427
428     hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
429                            10, 10, 300, 100,
430                            NULL, NULL, NULL, 0);
431
432     ti.cbSize = TTTOOLINFOA_V2_SIZE;
433     ti.hwnd = NULL;
434     ti.hinst = GetModuleHandleA(NULL);
435     ti.uFlags = 0;
436     ti.uId = 0x1234ABCD;
437     ti.lpszText = NULL;
438     ti.lParam = 0xdeadbeef;
439     GetClientRect(hwnd, &ti.rect);
440     r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
441     ok(r, "Adding the tool to the tooltip failed\n");
442
443     ti.cbSize = TTTOOLINFOA_V2_SIZE;
444     ti.lParam = 0xaaaaaaaa;
445     r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
446     ok(r, "Getting tooltip info failed\n");
447     ok(0xdeadbeef == ti.lParam, "Expected 0xdeadbeef, got %lx\n", ti.lParam);
448
449     tiW.cbSize = TTTOOLINFOW_V2_SIZE;
450     tiW.hwnd = NULL;
451     tiW.uId = 0x1234ABCD;
452     tiW.lParam = 0xaaaaaaaa;
453     r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
454     ok(r, "Getting tooltip info failed\n");
455     ok(0xdeadbeef == tiW.lParam, "Expected 0xdeadbeef, got %lx\n", tiW.lParam);
456
457     ti.cbSize = TTTOOLINFOA_V2_SIZE;
458     ti.uId = 0x1234ABCD;
459     ti.lParam = 0xaaaaaaaa;
460     r = SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
461
462     ti.cbSize = TTTOOLINFOA_V2_SIZE;
463     ti.lParam = 0xdeadbeef;
464     r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
465     ok(r, "Getting tooltip info failed\n");
466     ok(0xaaaaaaaa == ti.lParam, "Expected 0xaaaaaaaa, got %lx\n", ti.lParam);
467
468     DestroyWindow(hwnd);
469
470     /* 1. test size parameter validation rules (ansi messages) */
471     hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
472                            10, 10, 300, 100,
473                            NULL, NULL, NULL, 0);
474
475     ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
476     ti.hwnd = NULL;
477     ti.hinst = GetModuleHandleA(NULL);
478     ti.uFlags = 0;
479     ti.uId = 0x1234ABCD;
480     ti.lpszText = NULL;
481     ti.lParam = 0xdeadbeef;
482     GetClientRect(hwnd, &ti.rect);
483     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
484     ok(r, "Adding the tool to the tooltip failed\n");
485     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
486     expect(1, r);
487
488     ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
489     ti.hwnd = NULL;
490     ti.uId = 0x1234ABCD;
491     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
492     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
493     expect(0, r);
494
495     ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
496     ti.hwnd = NULL;
497     ti.hinst = GetModuleHandleA(NULL);
498     ti.uFlags = 0;
499     ti.uId = 0x1234ABCD;
500     ti.lpszText = NULL;
501     ti.lParam = 0xdeadbeef;
502     GetClientRect(hwnd, &ti.rect);
503     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
504     ok(r, "Adding the tool to the tooltip failed\n");
505     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
506     expect(1, r);
507
508     ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
509     ti.hwnd = NULL;
510     ti.uId = 0x1234ABCD;
511     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
512     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
513     expect(0, r);
514
515     ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
516     ti.hwnd = NULL;
517     ti.hinst = GetModuleHandleA(NULL);
518     ti.uFlags = 0;
519     ti.uId = 0x1234ABCD;
520     ti.lpszText = NULL;
521     ti.lParam = 0xdeadbeef;
522     GetClientRect(hwnd, &ti.rect);
523     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
524     ok(r, "Adding the tool to the tooltip failed\n");
525     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
526     expect(1, r);
527
528     ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
529     ti.hwnd = NULL;
530     ti.uId = 0x1234ABCD;
531     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
532     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
533     expect(0, r);
534
535     DestroyWindow(hwnd);
536
537     /* 2. test size parameter validation rules (w-messages) */
538     hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
539                            10, 10, 300, 100,
540                            NULL, NULL, NULL, 0);
541     if(!hwnd)
542     {
543         win_skip("CreateWindowExW() not supported. Skipping.\n");
544         return;
545     }
546
547     tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
548     tiW.hwnd = NULL;
549     tiW.hinst = GetModuleHandleA(NULL);
550     tiW.uFlags = 0;
551     tiW.uId = 0x1234ABCD;
552     tiW.lpszText = NULL;
553     tiW.lParam = 0xdeadbeef;
554     GetClientRect(hwnd, &tiW.rect);
555     r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
556     ok(r, "Adding the tool to the tooltip failed\n");
557     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
558     expect(1, r);
559
560     tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
561     tiW.hwnd = NULL;
562     tiW.uId = 0x1234ABCD;
563     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
564     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
565     expect(0, r);
566
567     tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
568     tiW.hwnd = NULL;
569     tiW.hinst = GetModuleHandleA(NULL);
570     tiW.uFlags = 0;
571     tiW.uId = 0x1234ABCD;
572     tiW.lpszText = NULL;
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);
578     expect(1, r);
579
580     tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
581     tiW.hwnd = NULL;
582     tiW.uId = 0x1234ABCD;
583     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
584     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
585     expect(0, r);
586
587     tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
588     tiW.hwnd = NULL;
589     tiW.hinst = GetModuleHandleA(NULL);
590     tiW.uFlags = 0;
591     tiW.uId = 0x1234ABCD;
592     tiW.lpszText = NULL;
593     tiW.lParam = 0xdeadbeef;
594     GetClientRect(hwnd, &tiW.rect);
595     r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
596     ok(r, "Adding the tool to the tooltip failed\n");
597     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
598     expect(1, r);
599     /* looks like TTM_DELTOOLW doesn't work with invalid size */
600     tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
601     tiW.hwnd = NULL;
602     tiW.uId = 0x1234ABCD;
603     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
604     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
605     expect(1, r);
606
607     tiW.cbSize = TTTOOLINFOW_V2_SIZE;
608     tiW.hwnd = NULL;
609     tiW.uId = 0x1234ABCD;
610     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
611     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
612     expect(0, r);
613
614     DestroyWindow(hwnd);
615 }
616
617 START_TEST(tooltips)
618 {
619     InitCommonControls();
620
621     test_create_tooltip();
622     test_customdraw();
623     test_gettext();
624     test_ttm_gettoolinfo();
625 }