Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449/* * PROJECT: ReactOS api tests * LICENSE: GPL - See COPYING in the top level directory * PURPOSE: Test for TrackMouseEvent * PROGRAMMERS: Giannis Adamopoulos */
#include "precomp.h"
static HWND hWnd1, hWnd2, hWnd3;static HHOOK hMouseHookLL, hMouseHook;static int ignore_timer = 0, ignore_mouse = 0, ignore_mousell = 0;
static int get_iwnd(HWND hWnd){ if(hWnd == hWnd1) return 1; else if(hWnd == hWnd2) return 2; else if(hWnd == hWnd3) return 3; else return 0;}
LRESULT CALLBACK TmeTestProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){ int iwnd = get_iwnd(hWnd);
if(message == WM_PAINT) { PAINTSTRUCT ps; BeginPaint(hWnd, &ps); Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom); EndPaint(hWnd, &ps); }
if(message > WM_USER || !iwnd || IsDWmMsg(message) || IseKeyMsg(message)) return DefWindowProc(hWnd, message, wParam, lParam);
switch(message) { case WM_IME_SETCONTEXT: case WM_IME_NOTIFY : case WM_GETICON : case WM_GETTEXT: break; case WM_SYSTIMER: ok(0, "Got unexpected WM_SYSTIMER in the winproc. wParam=%d\n", wParam); break; default: RECORD_MESSAGE(iwnd, message, SENT, 0,0); } return DefWindowProc(hWnd, message, wParam, lParam);}
static LRESULT CALLBACK MouseLLHookProc(int nCode, WPARAM wParam, LPARAM lParam){ LRESULT ret; RECORD_MESSAGE(0, WH_MOUSE_LL, HOOK, wParam, 0); ret = CallNextHookEx(hMouseHookLL, nCode, wParam, lParam); if(ignore_mousell) return TRUE; return ret;}
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam){ MOUSEHOOKSTRUCT *hs = (MOUSEHOOKSTRUCT*) lParam; LRESULT ret; RECORD_MESSAGE(get_iwnd(hs->hwnd), WH_MOUSE, HOOK, wParam, hs->wHitTestCode); ret = CallNextHookEx(hMouseHook, nCode, wParam, lParam); if(ignore_mouse) return TRUE; return ret;}
static void FlushMessages(){ MSG msg;
while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) { int iwnd = get_iwnd(msg.hwnd); if(iwnd) { if(msg.message == WM_SYSTIMER) { RECORD_MESSAGE(iwnd, msg.message, POST,msg.wParam,0); if(ignore_timer) continue; } else if(!(msg.message > WM_USER || !iwnd || IsDWmMsg(msg.message) || IseKeyMsg(msg.message))) RECORD_MESSAGE(iwnd, msg.message, POST,0,0); } DispatchMessageA( &msg ); }}
#define FLUSH_MESSAGES(expected, notexpected) \ { EXPECT_QUEUE_STATUS(expected, notexpected);\ FlushMessages();\ }
static void create_test_windows(){ hMouseHookLL = SetWindowsHookExW(WH_MOUSE_LL, MouseLLHookProc, GetModuleHandleW( NULL ), 0); hMouseHook = SetWindowsHookExW(WH_MOUSE, MouseHookProc, GetModuleHandleW( NULL ), GetCurrentThreadId()); ok(hMouseHook!=NULL,"failed to set hook\n"); ok(hMouseHookLL!=NULL,"failed to set hook\n");
RegisterSimpleClass(TmeTestProc, L"testClass");
hWnd1 = CreateWindowW(L"testClass", L"test", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, 0, NULL); hWnd2 = CreateWindowW(L"testClass", L"test", WS_CHILD, 50, 50, 200, 200, hWnd1, NULL, 0, NULL); hWnd3 = CreateWindowW(L"testClass", L"test", WS_CHILD, 150, 150, 200, 200, hWnd1, NULL, 0, NULL);
ShowWindow(hWnd1, SW_SHOW); UpdateWindow(hWnd1); ShowWindow(hWnd2, SW_SHOW); UpdateWindow(hWnd2); ShowWindow(hWnd3, SW_SHOWNORMAL); UpdateWindow(hWnd3); //SetWindowPos (hWnd3, HWND_TOP, 0,0,0,0, SWP_NOMOVE|SWP_NOREDRAW);}
static void destroy_test_window(){ DestroyWindow(hWnd1); UnregisterClassW(L"testClass", 0); UnhookWindowsHookEx(hMouseHookLL); UnhookWindowsHookEx(hMouseHook);}
static void TmeStartTracking(HWND hwnd, DWORD Flags){ TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = Flags; tme.hwndTrack = hwnd; tme.dwHoverTime = 1; if(!TrackMouseEvent(&tme)) { trace("failed!\n"); }}
DWORD TmeQuery(HWND hwnd){ TRACKMOUSEEVENT tme; tme.cbSize = sizeof(tme); tme.dwFlags = TME_QUERY|TME_HOVER|TME_LEAVE; tme.hwndTrack = hwnd; TrackMouseEvent(&tme); return tme.dwFlags;}
#define EXPECT_TME_FLAGS(hWnd, expected) \ { DWORD flags = TmeQuery(hWnd); \ ok(flags == (expected),"wrong tme flags. expected %li, and got %li\n", (DWORD)(expected), flags); \ }
#define MOVE_CURSOR(x,y) mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE , \ x*(65535/GetSystemMetrics(SM_CXVIRTUALSCREEN)), \ y*(65535/GetSystemMetrics(SM_CYVIRTUALSCREEN)) , 0,0);
/* the mouse moves over hwnd2 */static MSG_ENTRY mousemove2_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {2, WM_NCHITTEST}, {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {2, WM_SETCURSOR}, {1, WM_SETCURSOR}, {2, WM_MOUSEMOVE, POST}, {0,0}};
/* the mouse hovers hwnd2 */static MSG_ENTRY mousehover2_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {2, WM_NCHITTEST}, {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {2, WM_SETCURSOR}, {1, WM_SETCURSOR}, {2, WM_MOUSEMOVE, POST}, {2, WM_SYSTIMER, POST, ID_TME_TIMER}, {2, WM_MOUSEHOVER, POST}, {0,0}};
/* the mouse leaves hwnd2 and moves to hwnd1 */static MSG_ENTRY mouseleave2to1_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {1, WM_NCHITTEST}, {1, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {1, WM_SETCURSOR}, {1, WM_MOUSEMOVE, POST}, {2, WM_MOUSELEAVE, POST}, {0,0}};
/* the mouse leaves hwnd2 and moves to hwnd3 */static MSG_ENTRY mouseleave2to3_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {3, WM_NCHITTEST}, {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {3, WM_SETCURSOR}, {1, WM_SETCURSOR}, {3, WM_MOUSEMOVE, POST}, {2, WM_MOUSELEAVE, POST}, {0,0}};
/* the mouse hovers hwnd3 */static MSG_ENTRY mousehover3_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {3, WM_NCHITTEST}, {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {3, WM_SETCURSOR}, {1, WM_SETCURSOR}, {3, WM_MOUSEMOVE, POST}, {3, WM_SYSTIMER, POST, ID_TME_TIMER}, {3, WM_MOUSEHOVER, POST}, {0,0}};
/* the mouse hovers hwnd3 without moving */static MSG_ENTRY mousehover3_nomove_chain[]={ {3, WM_SYSTIMER, POST, ID_TME_TIMER}, {3, WM_MOUSEHOVER, POST}, {0,0}};
/* the mouse hovers hwnd3 and the timer is not dispatched */static MSG_ENTRY mousehover3_droptimer_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {3, WM_NCHITTEST}, {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {3, WM_SETCURSOR}, {1, WM_SETCURSOR}, {3, WM_MOUSEMOVE, POST}, {3, WM_SYSTIMER, POST, ID_TME_TIMER}, {0,0}};
/* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */static MSG_ENTRY mousehover3_dropmouse_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {3, WM_NCHITTEST}, {3, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {3, WM_SYSTIMER, POST, ID_TME_TIMER}, {3, WM_MOUSEHOVER, POST}, {0,0}};
/* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */static MSG_ENTRY mousehover3_dropmousell_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {3, WM_SYSTIMER, POST, ID_TME_TIMER}, {3, WM_MOUSEHOVER, POST}, {0,0}};
/* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */static MSG_ENTRY mouseleave3to2_dropmouse_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {2, WM_NCHITTEST}, {2, WH_MOUSE,HOOK, WM_MOUSEMOVE, HTCLIENT}, {0,0}};
/* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */static MSG_ENTRY mouseleave3to2_dropmousell_chain[]={ {0, WH_MOUSE_LL, HOOK, WM_MOUSEMOVE}, {0,0}};
/* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */static MSG_ENTRY mouseleave3_remainging_chain[]={ {3, WM_MOUSELEAVE, POST}, {0,0}};
void Test_TrackMouseEvent(){ MOVE_CURSOR(0,0); create_test_windows(); FlushMessages(); EMPTY_CACHE();
/* the mouse moves over hwnd2 */ MOVE_CURSOR(220,220); FlushMessages(); COMPARE_CACHE(mousemove2_chain); EXPECT_TME_FLAGS(hWnd2, 0);
/* Begin tracking mouse events for hWnd2 */ TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE); EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE); FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse hovers hwnd2 */ MOVE_CURSOR(221, 221); Sleep(100); EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); EXPECT_TME_FLAGS(hWnd2, TME_LEAVE); COMPARE_CACHE(mousehover2_chain);
/* the mouse leaves hwnd2 and moves to hwnd1 */ MOVE_CURSOR(150, 150); EXPECT_TME_FLAGS(hWnd2, TME_LEAVE); FLUSH_MESSAGES(QS_MOUSEMOVE,QS_TIMER ); EXPECT_TME_FLAGS(hWnd2, 0); COMPARE_CACHE(mouseleave2to1_chain);
FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse moves over hwnd2 */ MOVE_CURSOR(220,220); FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER); COMPARE_CACHE(mousemove2_chain); EXPECT_TME_FLAGS(hWnd2, 0);
FlushMessages(); COMPARE_CACHE(empty_chain);
/* Begin tracking mouse events for hWnd2 */ TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE); TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE); TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE); TmeStartTracking(hWnd2, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE); COMPARE_CACHE(empty_chain); EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
/* the mouse moves from hwnd2 to the intersection of hwnd2 and hwnd3 */ MOVE_CURSOR(300,300); FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER); EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE); COMPARE_CACHE(mousemove2_chain);
FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse moves from hwnd2 to hwnd3 */ MOVE_CURSOR(400,400); FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER); EXPECT_TME_FLAGS(hWnd2, 0); COMPARE_CACHE(mouseleave2to3_chain);
FlushMessages(); COMPARE_CACHE(empty_chain);
/* Begin tracking mouse events for hWnd3 */ TmeStartTracking(hWnd3, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE); COMPARE_CACHE(empty_chain); EXPECT_TME_FLAGS(hWnd2, TME_HOVER|TME_LEAVE);
/* the mouse hovers hwnd3 */ MOVE_CURSOR(401,401); Sleep(100); EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); EXPECT_TME_FLAGS(hWnd3, TME_LEAVE); COMPARE_CACHE(mousehover3_chain);
FlushMessages(); COMPARE_CACHE(empty_chain);
/* Begin tracking mouse events for hWnd3 */ TmeStartTracking(hWnd3, TME_HOVER ); FLUSH_MESSAGES(0, QS_TIMER|QS_MOUSEMOVE); COMPARE_CACHE(empty_chain); EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE);
/* make sure that the timer will fire before the mouse moves */ Sleep(100); FlushMessages(); COMPARE_CACHE(mousehover3_nomove_chain); EXPECT_TME_FLAGS(hWnd3, TME_LEAVE);
Sleep(100); FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse hovers hwnd3 and the timer is not dispatched*/ TmeStartTracking(hWnd3, TME_HOVER ); ignore_timer = TRUE; MOVE_CURSOR(400,400); Sleep(100); EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); /* the loop drops WM_SYSTIMER */ EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); /* TME_HOVER is still active */ COMPARE_CACHE(mousehover3_droptimer_chain); /* we get no WM_MOUSEHOVER */ ignore_timer = FALSE;
/* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE_LL */ ignore_mousell = TRUE; MOVE_CURSOR(402,402); Sleep(100); EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(QS_TIMER, QS_MOUSEMOVE); /* WH_MOUSE_LL drops WM_MOUSEMOVE */ EXPECT_TME_FLAGS(hWnd3, TME_LEAVE); COMPARE_CACHE(mousehover3_dropmousell_chain); /* we get WM_MOUSEHOVER normaly */ ignore_mousell = FALSE;
FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse hovers hwnd3 and mouse message is dropped by WH_MOUSE */ ignore_mouse = TRUE; TmeStartTracking(hWnd3, TME_HOVER ); MOVE_CURSOR(401,401); Sleep(100); EXPECT_TME_FLAGS(hWnd3, TME_HOVER|TME_LEAVE); FLUSH_MESSAGES(QS_TIMER|QS_MOUSEMOVE, 0); /* WH_MOUSE drops WM_MOUSEMOVE */ EXPECT_TME_FLAGS(hWnd3, TME_LEAVE); COMPARE_CACHE(mousehover3_dropmouse_chain); /* we get WM_MOUSEHOVER normaly */ ignore_mouse = FALSE;
FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE_LL */ ignore_mousell = TRUE; TmeStartTracking(hWnd3, TME_LEAVE ); MOVE_CURSOR(220,220); FLUSH_MESSAGES(0, QS_MOUSEMOVE|QS_TIMER); /* WH_MOUSE drops WM_MOUSEMOVE */ EXPECT_TME_FLAGS(hWnd3, TME_LEAVE); /* all flags are removed */ COMPARE_CACHE(mouseleave3to2_dropmousell_chain); /* we get no WM_MOUSELEAVE */ ignore_mousell = FALSE;
FlushMessages(); COMPARE_CACHE(empty_chain);
/* the mouse leaves hwnd3 and moves to hwnd2 and mouse message is dropped by WH_MOUSE */ ignore_mouse = TRUE; MOVE_CURSOR(220,220); FLUSH_MESSAGES(QS_MOUSEMOVE, QS_TIMER); /* WH_MOUSE drops WM_MOUSEMOVE */ EXPECT_TME_FLAGS(hWnd3, 0); /* all flags are removed */ COMPARE_CACHE(mouseleave3to2_dropmouse_chain); /* we get no WM_MOUSELEAVE */ ignore_mouse = FALSE;
/* after WH_MOUSE drops WM_MOUSEMOVE, WM_MOUSELEAVE is still in the queue */ FLUSH_MESSAGES(QS_POSTMESSAGE, QS_TIMER|QS_MOUSEMOVE); COMPARE_CACHE(mouseleave3_remainging_chain);
FlushMessages(); COMPARE_CACHE(empty_chain);
destroy_test_window();}
START_TEST(TrackMouseEvent){ Test_TrackMouseEvent();}