dplayx: Adjust GetCaps behaviour to documentation
[wine/gsoc_dplay.git] / dlls / comctl32 / tests / tooltips.c
blobb8c46cb52cbc0b9591cfde568f31389e17e65bbf
1 /*
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 <assert.h>
21 #include <windows.h>
22 #include <commctrl.h>
24 #include "wine/test.h"
26 static void test_create_tooltip(void)
28 HWND parent, hwnd;
29 DWORD style, exp_style;
31 parent = CreateWindowEx(0, "static", NULL, WS_POPUP,
32 0, 0, 0, 0,
33 NULL, NULL, NULL, 0);
34 assert(parent);
36 hwnd = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, 0x7fffffff | WS_POPUP,
37 10, 10, 300, 100,
38 parent, NULL, NULL, 0);
39 assert(hwnd);
41 style = GetWindowLong(hwnd, GWL_STYLE);
42 trace("style = %08x\n", style);
43 exp_style = 0x7fffffff | WS_POPUP;
44 exp_style &= ~(WS_CHILD | WS_MAXIMIZE | WS_BORDER | WS_DLGFRAME);
45 ok(style == exp_style || broken(style == (exp_style | WS_BORDER)), /* nt4 */
46 "wrong style %08x/%08x\n", style, exp_style);
48 DestroyWindow(hwnd);
50 hwnd = CreateWindowEx(0, TOOLTIPS_CLASS, NULL, 0,
51 10, 10, 300, 100,
52 parent, NULL, NULL, 0);
53 assert(hwnd);
55 style = GetWindowLong(hwnd, GWL_STYLE);
56 trace("style = %08x\n", style);
57 ok(style == (WS_POPUP | WS_CLIPSIBLINGS | WS_BORDER),
58 "wrong style %08x\n", style);
60 DestroyWindow(hwnd);
62 DestroyWindow(parent);
65 /* try to make sure pending X events have been processed before continuing */
66 static void flush_events(int waitTime)
68 MSG msg;
69 int diff = waitTime;
70 DWORD time = GetTickCount() + waitTime;
72 while (diff > 0)
74 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min(100,diff), QS_ALLEVENTS) == WAIT_TIMEOUT) break;
75 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
76 diff = time - GetTickCount();
80 static int CD_Stages;
81 static LRESULT CD_Result;
82 static HWND g_hwnd;
84 #define TEST_CDDS_PREPAINT 0x00000001
85 #define TEST_CDDS_POSTPAINT 0x00000002
86 #define TEST_CDDS_PREERASE 0x00000004
87 #define TEST_CDDS_POSTERASE 0x00000008
88 #define TEST_CDDS_ITEMPREPAINT 0x00000010
89 #define TEST_CDDS_ITEMPOSTPAINT 0x00000020
90 #define TEST_CDDS_ITEMPREERASE 0x00000040
91 #define TEST_CDDS_ITEMPOSTERASE 0x00000080
92 #define TEST_CDDS_SUBITEM 0x00000100
94 static LRESULT CALLBACK CustomDrawWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
96 switch(msg) {
98 case WM_DESTROY:
99 PostQuitMessage(0);
100 break;
102 case WM_NOTIFY:
103 if (((NMHDR *)lParam)->code == NM_CUSTOMDRAW) {
104 NMTTCUSTOMDRAW *ttcd = (NMTTCUSTOMDRAW*) lParam;
105 ok(ttcd->nmcd.hdr.hwndFrom == g_hwnd, "Unexpected hwnd source %p (%p)\n",
106 ttcd->nmcd.hdr.hwndFrom, g_hwnd);
107 ok(ttcd->nmcd.hdr.idFrom == 0x1234ABCD, "Unexpected id %x\n", (int)ttcd->nmcd.hdr.idFrom);
109 switch (ttcd->nmcd.dwDrawStage) {
110 case CDDS_PREPAINT : CD_Stages |= TEST_CDDS_PREPAINT; break;
111 case CDDS_POSTPAINT : CD_Stages |= TEST_CDDS_POSTPAINT; break;
112 case CDDS_PREERASE : CD_Stages |= TEST_CDDS_PREERASE; break;
113 case CDDS_POSTERASE : CD_Stages |= TEST_CDDS_POSTERASE; break;
114 case CDDS_ITEMPREPAINT : CD_Stages |= TEST_CDDS_ITEMPREPAINT; break;
115 case CDDS_ITEMPOSTPAINT: CD_Stages |= TEST_CDDS_ITEMPOSTPAINT; break;
116 case CDDS_ITEMPREERASE : CD_Stages |= TEST_CDDS_ITEMPREERASE; break;
117 case CDDS_ITEMPOSTERASE: CD_Stages |= TEST_CDDS_ITEMPOSTERASE; break;
118 case CDDS_SUBITEM : CD_Stages |= TEST_CDDS_SUBITEM; break;
119 default: CD_Stages = -1;
122 if (ttcd->nmcd.dwDrawStage == CDDS_PREPAINT) return CD_Result;
124 /* drop through */
126 default:
127 return DefWindowProcA(hWnd, msg, wParam, lParam);
130 return 0L;
133 static void test_customdraw(void) {
134 static struct {
135 LRESULT FirstReturnValue;
136 int ExpectedCalls;
137 } expectedResults[] = {
138 /* Valid notification responses */
139 {CDRF_DODEFAULT, TEST_CDDS_PREPAINT},
140 {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT},
141 {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT},
143 /* Invalid notification responses */
144 {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
145 {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
146 {CDRF_NEWFONT, TEST_CDDS_PREPAINT}
149 int iterationNumber;
150 WNDCLASSA wc;
151 LRESULT lResult;
153 /* Create a class to use the custom draw wndproc */
154 wc.style = CS_HREDRAW | CS_VREDRAW;
155 wc.cbClsExtra = 0;
156 wc.cbWndExtra = 0;
157 wc.hInstance = GetModuleHandleA(NULL);
158 wc.hIcon = NULL;
159 wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
160 wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
161 wc.lpszMenuName = NULL;
162 wc.lpszClassName = "CustomDrawClass";
163 wc.lpfnWndProc = CustomDrawWndProc;
164 RegisterClass(&wc);
166 for (iterationNumber = 0;
167 iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]);
168 iterationNumber++) {
170 HWND parent, hwndTip;
171 RECT rect;
172 TOOLINFO toolInfo = { 0 };
174 /* Create a main window */
175 parent = CreateWindowEx(0, "CustomDrawClass", NULL,
176 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
177 WS_MAXIMIZEBOX | WS_VISIBLE,
178 50, 50,
179 300, 300,
180 NULL, NULL, NULL, 0);
181 ok(parent != NULL, "Creation of main window failed\n");
183 /* Make it show */
184 ShowWindow(parent, SW_SHOWNORMAL);
185 flush_events(100);
187 /* Create Tooltip */
188 hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS,
189 NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
190 CW_USEDEFAULT, CW_USEDEFAULT,
191 CW_USEDEFAULT, CW_USEDEFAULT,
192 parent, NULL, GetModuleHandleA(NULL), 0);
193 ok(hwndTip != NULL, "Creation of tooltip window failed\n");
195 /* Set up parms for the wndproc to handle */
196 CD_Stages = 0;
197 CD_Result = expectedResults[iterationNumber].FirstReturnValue;
198 g_hwnd = hwndTip;
200 /* Make it topmost, as per the MSDN */
201 SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
202 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
204 /* Create a tool */
205 toolInfo.cbSize = TTTOOLINFO_V1_SIZE;
206 toolInfo.hwnd = parent;
207 toolInfo.hinst = GetModuleHandleA(NULL);
208 toolInfo.uFlags = TTF_SUBCLASS;
209 toolInfo.uId = 0x1234ABCD;
210 toolInfo.lpszText = (LPSTR)"This is a test tooltip";
211 toolInfo.lParam = 0xdeadbeef;
212 GetClientRect (parent, &toolInfo.rect);
213 lResult = SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
214 ok(lResult, "Adding the tool to the tooltip failed\n");
216 /* Make tooltip appear quickly */
217 SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));
219 /* Put cursor inside window, tooltip will appear immediately */
220 GetWindowRect( parent, &rect );
221 SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
222 flush_events(200);
224 if (CD_Stages)
226 /* Check CustomDraw results */
227 ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls ||
228 broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */
229 "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
230 expectedResults[iterationNumber].ExpectedCalls);
233 /* Clean up */
234 DestroyWindow(hwndTip);
235 DestroyWindow(parent);
241 static const CHAR testcallbackA[] = "callback";
243 static LRESULT WINAPI parent_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
245 if (message == WM_NOTIFY && lParam)
247 NMTTDISPINFOA *ttnmdi = (NMTTDISPINFOA*)lParam;
249 if (ttnmdi->hdr.code == TTN_GETDISPINFOA)
250 lstrcpy(ttnmdi->lpszText, testcallbackA);
253 return DefWindowProcA(hwnd, message, wParam, lParam);
256 static BOOL register_parent_wnd_class(void)
258 WNDCLASSA cls;
260 cls.style = 0;
261 cls.lpfnWndProc = parent_wnd_proc;
262 cls.cbClsExtra = 0;
263 cls.cbWndExtra = 0;
264 cls.hInstance = GetModuleHandleA(NULL);
265 cls.hIcon = 0;
266 cls.hCursor = LoadCursorA(0, IDC_ARROW);
267 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
268 cls.lpszMenuName = NULL;
269 cls.lpszClassName = "Tooltips test parent class";
270 return RegisterClassA(&cls);
273 static HWND create_parent_window(void)
275 if (!register_parent_wnd_class())
276 return NULL;
278 return CreateWindowEx(0, "Tooltips test parent class",
279 "Tooltips test parent window",
280 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
281 WS_MAXIMIZEBOX | WS_VISIBLE,
282 0, 0, 100, 100,
283 GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
286 static void test_gettext(void)
288 HWND hwnd, notify;
289 TTTOOLINFOA toolinfoA;
290 TTTOOLINFOW toolinfoW;
291 LRESULT r;
292 CHAR bufA[10] = "";
293 WCHAR bufW[10] = { 0 };
294 static const CHAR testtipA[] = "testtip";
296 notify = create_parent_window();
297 ok(notify != NULL, "Expected notification window to be created\n");
299 /* For bug 14790 - lpszText is NULL */
300 hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
301 10, 10, 300, 100,
302 NULL, NULL, NULL, 0);
303 assert(hwnd);
305 /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
306 /* otherwise it crashes on the NULL lpszText */
307 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
308 toolinfoA.hwnd = NULL;
309 toolinfoA.hinst = GetModuleHandleA(NULL);
310 toolinfoA.uFlags = 0;
311 toolinfoA.uId = 0x1234ABCD;
312 toolinfoA.lpszText = NULL;
313 toolinfoA.lParam = 0xdeadbeef;
314 GetClientRect(hwnd, &toolinfoA.rect);
315 r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
316 if (r)
318 toolinfoA.hwnd = NULL;
319 toolinfoA.uId = 0x1234ABCD;
320 toolinfoA.lpszText = bufA;
321 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
322 ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
324 else
326 win_skip( "Old comctl32, not testing NULL text\n" );
327 DestroyWindow( hwnd );
328 return;
331 /* add another tool with text */
332 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
333 toolinfoA.hwnd = NULL;
334 toolinfoA.hinst = GetModuleHandleA(NULL);
335 toolinfoA.uFlags = 0;
336 toolinfoA.uId = 0x1235ABCD;
337 strcpy(bufA, testtipA);
338 toolinfoA.lpszText = bufA;
339 toolinfoA.lParam = 0xdeadbeef;
340 GetClientRect(hwnd, &toolinfoA.rect);
341 r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
342 ok(r, "Adding the tool to the tooltip failed\n");
343 if (r)
345 DWORD length;
347 length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
348 ok(length == 0, "Expected 0, got %d\n", length);
350 toolinfoA.hwnd = NULL;
351 toolinfoA.uId = 0x1235ABCD;
352 toolinfoA.lpszText = bufA;
353 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
354 ok(strcmp(toolinfoA.lpszText, testtipA) == 0, "lpszText should be an empty string\n");
356 length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
357 ok(length == 0, "Expected 0, got %d\n", length);
360 /* add another with callback text */
361 toolinfoA.cbSize = sizeof(TTTOOLINFOA);
362 toolinfoA.hwnd = notify;
363 toolinfoA.hinst = GetModuleHandleA(NULL);
364 toolinfoA.uFlags = 0;
365 toolinfoA.uId = 0x1236ABCD;
366 toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
367 toolinfoA.lParam = 0xdeadbeef;
368 GetClientRect(hwnd, &toolinfoA.rect);
369 r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
370 ok(r, "Adding the tool to the tooltip failed\n");
371 if (r)
373 toolinfoA.hwnd = notify;
374 toolinfoA.uId = 0x1236ABCD;
375 toolinfoA.lpszText = bufA;
376 SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
377 ok(strcmp(toolinfoA.lpszText, testcallbackA) == 0,
378 "lpszText should be an (%s) string\n", testcallbackA);
381 DestroyWindow(hwnd);
382 DestroyWindow(notify);
384 SetLastError(0xdeadbeef);
385 hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
386 10, 10, 300, 100,
387 NULL, NULL, NULL, 0);
389 if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
390 win_skip("CreateWindowExW is not implemented\n");
391 return;
394 assert(hwnd);
396 toolinfoW.cbSize = sizeof(TTTOOLINFOW);
397 toolinfoW.hwnd = NULL;
398 toolinfoW.hinst = GetModuleHandleA(NULL);
399 toolinfoW.uFlags = 0;
400 toolinfoW.uId = 0x1234ABCD;
401 toolinfoW.lpszText = NULL;
402 toolinfoW.lParam = 0xdeadbeef;
403 GetClientRect(hwnd, &toolinfoW.rect);
404 r = SendMessageW(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoW);
405 ok(r, "Adding the tool to the tooltip failed\n");
407 if (0) /* crashes on NT4 */
409 toolinfoW.hwnd = NULL;
410 toolinfoW.uId = 0x1234ABCD;
411 toolinfoW.lpszText = bufW;
412 SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
413 ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n");
416 DestroyWindow(hwnd);
419 START_TEST(tooltips)
421 InitCommonControls();
423 test_create_tooltip();
424 test_customdraw();
425 test_gettext();