[REACTOS] Fix MSVC printf format warnings
[reactos.git] / modules / rostests / apitests / user32 / TrackMouseEvent.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL - See COPYING in the top level directory
4 * PURPOSE: Test for TrackMouseEvent
5 * PROGRAMMERS: Giannis Adamopoulos
6 */
7
8 #include "precomp.h"
9
10 HWND hWnd1, hWnd2, hWnd3;
11 HHOOK hMouseHookLL, hMouseHook;
12 int ignore_timer = 0, ignore_mouse = 0, ignore_mousell = 0;
13
14 static int get_iwnd(HWND hWnd)
15 {
16 if(hWnd == hWnd1) return 1;
17 else if(hWnd == hWnd2) return 2;
18 else if(hWnd == hWnd3) return 3;
19 else return 0;
20 }
21
22 LRESULT CALLBACK TmeTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
23 {
24 int iwnd = get_iwnd(hWnd);
25
26 if(message == WM_PAINT)
27 {
28 PAINTSTRUCT ps;
29 BeginPaint(hWnd, &ps);
30 Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
31 EndPaint(hWnd, &ps);
32 }
33
34 if(message > WM_USER || !iwnd || IsDWmMsg(message) || IseKeyMsg(message))
35 return DefWindowProc(hWnd, message, wParam, lParam);
36
37 switch(message)
38 {
39 case WM_IME_SETCONTEXT:
40 case WM_IME_NOTIFY :
41 case WM_GETICON :
42 case WM_GETTEXT:
43 break;
44 case WM_SYSTIMER:
45 ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam);
46 break;
47 default:
48 RECORD_MESSAGE(iwnd, message, SENT, 0,0);
49 }
50 return DefWindowProc(hWnd, message, wParam, lParam);
51 }
52
53 static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam)
54 {
55 LRESULT ret;
56 RECORD_MESSAGE(0, WH_MOUSE_LL, HOOK, wParam, 0);
57 ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam);
58 if(ignore_mousell)
59 return TRUE;
60 return ret;
61 }
62
63 static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam)
64 {
65 MOUSEHOOKSTRUCT *hs = (MOUSEHOOKSTRUCT*) lParam;
66 LRESULT ret;
67 RECORD_MESSAGE(get_iwnd(hs->hwnd), WH_MOUSE, HOOK, wParam, hs->wHitTestCode);
68 ret = CallNextHookEx(hMouseHook, nCode, wParam, lParam);
69 if(ignore_mouse)
70 return TRUE;
71 return ret;
72 }
73
74 static void FlushMessages()
75 {
76 MSG msg;
77
78 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
79 {
80 int iwnd = get_iwnd(msg.hwnd);
81 if(iwnd)
82 {
83 if(msg.message == WM_SYSTIMER)
84 {
85 RECORD_MESSAGE(iwnd, msg.message, POST,msg.wParam,0);
86 if(ignore_timer)
87 continue;
88 }
89 else if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message)))
90 RECORD_MESSAGE(iwnd, msg.message, POST,0,0);
91 }
92 DispatchMessageA( &msg );
93 }
94 }
95
96 #define FLUSH_MESSAGES(expected, notexpected) \
97 { EXPECT_QUEUE_STATUS(expected, notexpected);\
98 FlushMessages();\
99 }
100
101 static void create_test_windows()
102 {
103 hMouseHookLL = SetWindowsHookExW(WH_MOUSE_LL, MouseLLHookProc, GetModuleHandleW( NULL ), 0);
104 hMouseHook = SetWindowsHookExW(WH_MOUSE, MouseHookProc, GetModuleHandleW( NULL ), GetCurrentThreadId());
105 ok(hMouseHook!=NULL,"failed to set hook\n");
106 ok(hMouseHookLL!=NULL,"failed to set hook\n");
107
108 RegisterSimpleClass(TmeTestProc, L"testClass");
109
110 hWnd1 = CreateWindowW(L"testClass", L"test", WS_OVERLAPPEDWINDOW,
111 100, 100, 500, 500, NULL, NULL, 0, NULL);
112 hWnd2 = CreateWindowW(L"testClass", L"test", WS_CHILD,
113 50, 50, 200, 200, hWnd1, NULL, 0, NULL);
114 hWnd3 = CreateWindowW(L"testClass", L"test", WS_CHILD,
115 150, 150, 200, 200, hWnd1, NULL, 0, NULL);
116
117 ShowWindow(hWnd1, SW_SHOW);
118 UpdateWindow(hWnd1);
119 ShowWindow(hWnd2, SW_SHOW);
120 UpdateWindow(hWnd2);
121 ShowWindow(hWnd3, SW_SHOWNORMAL);
122 UpdateWindow(hWnd3);
123 //SetWindowPos (hWnd3, HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOREDRAW);
124 }
125
126 static void destroy_test_window()
127 {
128 DestroyWindow(hWnd1);
129 UnregisterClassW(L"testClass", 0);
130 UnhookWindowsHookEx(hMouseHookLL);
131 UnhookWindowsHookEx(hMouseHook);
132 }
133
134 static void TmeStartTracking(HWND hwnd, DWORD Flags)
135 {
136 TRACKMOUSEEVENT tme;
137 tme.cbSize = sizeof(tme);
138 tme.dwFlags = Flags;
139 tme.hwndTrack = hwnd;
140 tme.dwHoverTime = 1;
141 if(!TrackMouseEvent(&tme))
142 {
143 trace("failed!\n");
144 }
145 }
146
147 DWORD TmeQuery(HWND hwnd)
148 {
149 TRACKMOUSEEVENT tme;
150 tme.cbSize = sizeof(tme);
151 tme.dwFlags = TME_QUERY|TME_HOVER|TME_LEAVE;
152 tme.hwndTrack = hwnd;
153 TrackMouseEvent(&tme);
154 return tme.dwFlags;
155 }
156
157 #define EXPECT_TME_FLAGS(hWnd, expected) \
158 { DWORD flags = TmeQuery(hWnd); \
159 ok(flags == (expected),"wrong tme flags. expected %li, and got %li\n", (DWORD)(expected), flags); \
160 }
161
162 #define MOVE_CURSOR(x,y) mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE , \
163 x*(65535/GetSystemMetrics(SM_CXVIRTUALSCREEN)), \
164 y*(65535/GetSystemMetrics(SM_CYVIRTUALSCREEN)) , 0,0);
165
166 /* the mouse moves over hwnd2 */
167 MSG_ENTRY mousemove2_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
168 {2, WM_NCHITTEST},
169 {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
170 {2, WM_SETCURSOR},
171 {1, WM_SETCURSOR},
172 {2, WM_MOUSEMOVE, POST},
173 {0,0}};
174
175 /* the mouse hovers hwnd2 */
176 MSG_ENTRY mousehover2_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
177 {2, WM_NCHITTEST},
178 {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
179 {2, WM_SETCURSOR},
180 {1, WM_SETCURSOR},
181 {2, WM_MOUSEMOVE, POST},
182 {2, WM_SYSTIMER, POST, ID_TME_TIMER},
183 {2, WM_MOUSEHOVER, POST},
184 {0,0}};
185
186 /* the mouse leaves hwnd2 and moves to hwnd1 */
187 MSG_ENTRY mouseleave2to1_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
188 {1, WM_NCHITTEST},
189 {1, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
190 {1, WM_SETCURSOR},
191 {1, WM_MOUSEMOVE, POST},
192 {2, WM_MOUSELEAVE, POST},
193 {0,0}};
194
195 /* the mouse leaves hwnd2 and moves to hwnd3 */
196 MSG_ENTRY mouseleave2to3_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
197 {3, WM_NCHITTEST},
198 {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
199 {3, WM_SETCURSOR},
200 {1, WM_SETCURSOR},
201 {3, WM_MOUSEMOVE, POST},
202 {2, WM_MOUSELEAVE, POST},
203 {0,0}};
204
205 /* the mouse hovers hwnd3 */
206 MSG_ENTRY mousehover3_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
207 {3, WM_NCHITTEST},
208 {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
209 {3, WM_SETCURSOR},
210 {1, WM_SETCURSOR},
211 {3, WM_MOUSEMOVE, POST},
212 {3, WM_SYSTIMER, POST, ID_TME_TIMER},
213 {3, WM_MOUSEHOVER, POST},
214 {0,0}};
215
216 /* the mouse hovers hwnd3 without moving */
217 MSG_ENTRY mousehover3_nomove_chain[]={{3, WM_SYSTIMER, POST, ID_TME_TIMER},
218 {3, WM_MOUSEHOVER, POST},
219 {0,0}};
220
221 /* the mouse hovers hwnd3 and the timer is not dispatched */
222 MSG_ENTRY mousehover3_droptimer_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
223 {3, WM_NCHITTEST},
224 {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
225 {3, WM_SETCURSOR},
226 {1, WM_SETCURSOR},
227 {3, WM_MOUSEMOVE, POST},
228 {3, WM_SYSTIMER, POST, ID_TME_TIMER},
229 {0,0}};
230
231 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
232 MSG_ENTRY mousehover3_dropmouse_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
233 {3, WM_NCHITTEST},
234 {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
235 {3, WM_SYSTIMER, POST, ID_TME_TIMER},
236 {3, WM_MOUSEHOVER, POST},
237 {0,0}};
238
239 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
240 MSG_ENTRY mousehover3_dropmousell_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
241 {3, WM_SYSTIMER, POST, ID_TME_TIMER},
242 {3, WM_MOUSEHOVER, POST},
243 {0,0}};
244
245 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
246 MSG_ENTRY mouseleave3to2_dropmouse_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
247 {2, WM_NCHITTEST},
248 {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT},
249 {0,0}};
250
251 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
252 MSG_ENTRY mouseleave3to2_dropmousell_chain[]={{0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE},
253 {0,0}};
254
255 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
256 MSG_ENTRY mouseleave3_remainging_chain[]={{3, WM_MOUSELEAVE, POST},
257 {0,0}};
258
259 void Test_TrackMouseEvent()
260 {
261 MOVE_CURSOR(0,0);
262 create_test_windows();
263 FlushMessages();
264 EMPTY_CACHE();
265
266 /* the mouse moves over hwnd2 */
267 MOVE_CURSOR(220,220);
268 FlushMessages();
269 COMPARE_CACHE(mousemove2_chain);
270 EXPECT_TME_FLAGS(hWnd2, 0);
271
272 /* Begin tracking mouse events for hWnd2 */
273 TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE);
274 EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
275 FlushMessages();
276 COMPARE_CACHE(empty_chain);
277
278 /* the mouse hovers hwnd2 */
279 MOVE_CURSOR(221, 221);
280 Sleep(100);
281 EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
282 FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0);
283 EXPECT_TME_FLAGS(hWnd2, TME_LEAVE);
284 COMPARE_CACHE(mousehover2_chain);
285
286 /* the mouse leaves hwnd2 and moves to hwnd1 */
287 MOVE_CURSOR(150, 150);
288 EXPECT_TME_FLAGS(hWnd2, TME_LEAVE);
289 FLUSH_MESSAGES(QS_MOUSEMOVE,QS_TIMER );
290 EXPECT_TME_FLAGS(hWnd2, 0);
291 COMPARE_CACHE(mouseleave2to1_chain);
292
293 FlushMessages();
294 COMPARE_CACHE(empty_chain);
295
296 /* the mouse moves over hwnd2 */
297 MOVE_CURSOR(220,220);
298 FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER);
299 COMPARE_CACHE(mousemove2_chain);
300 EXPECT_TME_FLAGS(hWnd2, 0);
301
302 FlushMessages();
303 COMPARE_CACHE(empty_chain);
304
305 /* Begin tracking mouse events for hWnd2 */
306 TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE);
307 TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE);
308 TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE);
309 TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE);
310 FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE);
311 COMPARE_CACHE(empty_chain);
312 EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
313
314 /* the mouse moves from hwnd2 to the intersection of hwnd2 and hwnd3 */
315 MOVE_CURSOR(300,300);
316 FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER);
317 EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
318 COMPARE_CACHE(mousemove2_chain);
319
320 FlushMessages();
321 COMPARE_CACHE(empty_chain);
322
323 /* the mouse moves from hwnd2 to hwnd3 */
324 MOVE_CURSOR(400,400);
325 FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER);
326 EXPECT_TME_FLAGS(hWnd2, 0);
327 COMPARE_CACHE(mouseleave2to3_chain);
328
329 FlushMessages();
330 COMPARE_CACHE(empty_chain);
331
332 /* Begin tracking mouse events for hWnd3 */
333 TmeStartTracking(hWnd3, TME_HOVER|TME_LEAVE);
334 FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE);
335 COMPARE_CACHE(empty_chain);
336 EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
337
338 /* the mouse hovers hwnd3 */
339 MOVE_CURSOR(401,401);
340 Sleep(100);
341 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
342 FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0);
343 EXPECT_TME_FLAGS(hWnd3, TME_LEAVE);
344 COMPARE_CACHE(mousehover3_chain);
345
346 FlushMessages();
347 COMPARE_CACHE(empty_chain);
348
349 /* Begin tracking mouse events for hWnd3 */
350 TmeStartTracking(hWnd3, TME_HOVER );
351 FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE);
352 COMPARE_CACHE(empty_chain);
353 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
354
355 /* make sure that the timer will fire before the mouse moves */
356 Sleep(100);
357 FlushMessages();
358 COMPARE_CACHE(mousehover3_nomove_chain);
359 EXPECT_TME_FLAGS(hWnd3, TME_LEAVE);
360
361 Sleep(100);
362 FlushMessages();
363 COMPARE_CACHE(empty_chain);
364
365 /* the mouse hovers hwnd3 and the timer is not dispatched*/
366 TmeStartTracking(hWnd3, TME_HOVER );
367 ignore_timer = TRUE;
368 MOVE_CURSOR(400,400);
369 Sleep(100);
370 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
371 FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); /* the loop drops WM_SYSTIMER */
372 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); /* TME_HOVER is still active */
373 COMPARE_CACHE(mousehover3_droptimer_chain); /* we get no WM_MOUSEHOVER */
374 ignore_timer = FALSE;
375
376 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */
377 ignore_mousell = TRUE;
378 MOVE_CURSOR(402,402);
379 Sleep(100);
380 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
381 FLUSH_MESSAGES(QS_TIMER, QS_MOUSEMOVE); /* WH_MOUSE_LL drops WM_MOUSEMOVE */
382 EXPECT_TME_FLAGS(hWnd3, TME_LEAVE);
383 COMPARE_CACHE(mousehover3_dropmousell_chain); /* we get WM_MOUSEHOVER normaly */
384 ignore_mousell = FALSE;
385
386 FlushMessages();
387 COMPARE_CACHE(empty_chain);
388
389 /* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */
390 ignore_mouse = TRUE;
391 TmeStartTracking(hWnd3, TME_HOVER );
392 MOVE_CURSOR(401,401);
393 Sleep(100);
394 EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
395 FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); /* WH_MOUSE drops WM_MOUSEMOVE */
396 EXPECT_TME_FLAGS(hWnd3, TME_LEAVE);
397 COMPARE_CACHE(mousehover3_dropmouse_chain); /* we get WM_MOUSEHOVER normaly */
398 ignore_mouse = FALSE;
399
400 FlushMessages();
401 COMPARE_CACHE(empty_chain);
402
403 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */
404 ignore_mousell = TRUE;
405 TmeStartTracking(hWnd3, TME_LEAVE );
406 MOVE_CURSOR(220,220);
407 FLUSH_MESSAGES(0, QS_MOUSEMOVE|QS_TIMER); /* WH_MOUSE drops WM_MOUSEMOVE */
408 EXPECT_TME_FLAGS(hWnd3, TME_LEAVE); /* all flags are removed */
409 COMPARE_CACHE(mouseleave3to2_dropmousell_chain); /* we get no WM_MOUSELEAVE */
410 ignore_mousell = FALSE;
411
412 FlushMessages();
413 COMPARE_CACHE(empty_chain);
414
415 /* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */
416 ignore_mouse = TRUE;
417 MOVE_CURSOR(220,220);
418 FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER); /* WH_MOUSE drops WM_MOUSEMOVE */
419 EXPECT_TME_FLAGS(hWnd3, 0); /* all flags are removed */
420 COMPARE_CACHE(mouseleave3to2_dropmouse_chain); /* we get no WM_MOUSELEAVE */
421 ignore_mouse = FALSE;
422
423 /* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */
424 FLUSH_MESSAGES(QS_POSTMESSAGE, QS_TIMER|QS_MOUSEMOVE);
425 COMPARE_CACHE(mouseleave3_remainging_chain);
426
427 FlushMessages();
428 COMPARE_CACHE(empty_chain);
429
430 destroy_test_window();
431 }
432
433 START_TEST(TrackMouseEvent)
434 {
435 Test_TrackMouseEvent();
436 }