libwine: Generate Unicode data for Arabic shaping.
[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 ||
448        broken(0xdeadbeef != ti.lParam), /* comctl32 < 5.81 */
449        "Expected 0xdeadbeef, got %lx\n", ti.lParam);
450
451     tiW.cbSize = TTTOOLINFOW_V2_SIZE;
452     tiW.hwnd = NULL;
453     tiW.uId = 0x1234ABCD;
454     tiW.lParam = 0xaaaaaaaa;
455     r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
456     ok(r, "Getting tooltip info failed\n");
457     ok(0xdeadbeef == tiW.lParam ||
458        broken(0xdeadbeef != tiW.lParam), /* comctl32 < 5.81 */
459        "Expected 0xdeadbeef, got %lx\n", tiW.lParam);
460
461     ti.cbSize = TTTOOLINFOA_V2_SIZE;
462     ti.uId = 0x1234ABCD;
463     ti.lParam = 0xaaaaaaaa;
464     SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);
465
466     ti.cbSize = TTTOOLINFOA_V2_SIZE;
467     ti.lParam = 0xdeadbeef;
468     r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
469     ok(r, "Getting tooltip info failed\n");
470     ok(0xaaaaaaaa == ti.lParam ||
471        broken(0xaaaaaaaa != ti.lParam), /* comctl32 < 5.81 */
472        "Expected 0xaaaaaaaa, got %lx\n", ti.lParam);
473
474     DestroyWindow(hwnd);
475
476     /* 1. test size parameter validation rules (ansi messages) */
477     hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
478                            10, 10, 300, 100,
479                            NULL, NULL, NULL, 0);
480
481     ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
482     ti.hwnd = NULL;
483     ti.hinst = GetModuleHandleA(NULL);
484     ti.uFlags = 0;
485     ti.uId = 0x1234ABCD;
486     ti.lpszText = NULL;
487     ti.lParam = 0xdeadbeef;
488     GetClientRect(hwnd, &ti.rect);
489     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
490     ok(r, "Adding the tool to the tooltip failed\n");
491     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
492     expect(1, r);
493
494     ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
495     ti.hwnd = NULL;
496     ti.uId = 0x1234ABCD;
497     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
498     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
499     expect(0, r);
500
501     ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
502     ti.hwnd = NULL;
503     ti.hinst = GetModuleHandleA(NULL);
504     ti.uFlags = 0;
505     ti.uId = 0x1234ABCD;
506     ti.lpszText = NULL;
507     ti.lParam = 0xdeadbeef;
508     GetClientRect(hwnd, &ti.rect);
509     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
510     ok(r, "Adding the tool to the tooltip failed\n");
511     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
512     expect(1, r);
513
514     ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
515     ti.hwnd = NULL;
516     ti.uId = 0x1234ABCD;
517     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
518     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
519     expect(0, r);
520
521     ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
522     ti.hwnd = NULL;
523     ti.hinst = GetModuleHandleA(NULL);
524     ti.uFlags = 0;
525     ti.uId = 0x1234ABCD;
526     ti.lpszText = NULL;
527     ti.lParam = 0xdeadbeef;
528     GetClientRect(hwnd, &ti.rect);
529     r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
530     ok(r, "Adding the tool to the tooltip failed\n");
531     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
532     expect(1, r);
533
534     ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
535     ti.hwnd = NULL;
536     ti.uId = 0x1234ABCD;
537     SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
538     r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
539     expect(0, r);
540
541     DestroyWindow(hwnd);
542
543     /* 2. test size parameter validation rules (w-messages) */
544     hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
545                            10, 10, 300, 100,
546                            NULL, NULL, NULL, 0);
547     if(!hwnd)
548     {
549         win_skip("CreateWindowExW() not supported. Skipping.\n");
550         return;
551     }
552
553     tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
554     tiW.hwnd = NULL;
555     tiW.hinst = GetModuleHandleA(NULL);
556     tiW.uFlags = 0;
557     tiW.uId = 0x1234ABCD;
558     tiW.lpszText = NULL;
559     tiW.lParam = 0xdeadbeef;
560     GetClientRect(hwnd, &tiW.rect);
561     r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
562     ok(r, "Adding the tool to the tooltip failed\n");
563     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
564     expect(1, r);
565
566     tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
567     tiW.hwnd = NULL;
568     tiW.uId = 0x1234ABCD;
569     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
570     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
571     expect(0, r);
572
573     tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
574     tiW.hwnd = NULL;
575     tiW.hinst = GetModuleHandleA(NULL);
576     tiW.uFlags = 0;
577     tiW.uId = 0x1234ABCD;
578     tiW.lpszText = NULL;
579     tiW.lParam = 0xdeadbeef;
580     GetClientRect(hwnd, &tiW.rect);
581     r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
582     ok(r, "Adding the tool to the tooltip failed\n");
583     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
584     expect(1, r);
585
586     tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
587     tiW.hwnd = NULL;
588     tiW.uId = 0x1234ABCD;
589     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
590     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
591     expect(0, r);
592
593     tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
594     tiW.hwnd = NULL;
595     tiW.hinst = GetModuleHandleA(NULL);
596     tiW.uFlags = 0;
597     tiW.uId = 0x1234ABCD;
598     tiW.lpszText = NULL;
599     tiW.lParam = 0xdeadbeef;
600     GetClientRect(hwnd, &tiW.rect);
601     r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
602     ok(r, "Adding the tool to the tooltip failed\n");
603     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
604     expect(1, r);
605     /* looks like TTM_DELTOOLW doesn't work with invalid size */
606     tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
607     tiW.hwnd = NULL;
608     tiW.uId = 0x1234ABCD;
609     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
610     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
611     expect(1, r);
612
613     tiW.cbSize = TTTOOLINFOW_V2_SIZE;
614     tiW.hwnd = NULL;
615     tiW.uId = 0x1234ABCD;
616     SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
617     r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
618     expect(0, r);
619
620     DestroyWindow(hwnd);
621 }
622
623 START_TEST(tooltips)
624 {
625     InitCommonControls();
626
627     test_create_tooltip();
628     test_customdraw();
629     test_gettext();
630     test_ttm_gettoolinfo();
631 }