{ WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_ERASEBKGND, sent|optional },
- { HCBT_ACTIVATE, hook },
+ { HCBT_ACTIVATE, hook|optional },
{ EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
{ WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
{ WM_NCPAINT, sent|wparam|optional, 1 },
- { WM_ACTIVATEAPP, sent|wparam, 1 },
- { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
+ { WM_NCACTIVATE, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
- { WM_ACTIVATE, sent|wparam, 1 },
- { HCBT_SETFOCUS, hook },
+ { WM_ACTIVATE, sent|wparam|optional, 1 },
+ { HCBT_SETFOCUS, hook|optional },
{ WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
{ WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
- { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 },
{ WM_GETTEXT, sent|optional },
{ WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_GETMINMAXINFO, sent|defwinproc },
{ WM_NCCALCSIZE, sent|wparam, TRUE },
{ EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 },
- { HCBT_ACTIVATE, hook },
+ { HCBT_ACTIVATE, hook|optional },
{ EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 },
{ WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
- { WM_ACTIVATEAPP, sent|wparam, 1 },
- { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
+ { WM_NCACTIVATE, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
- { WM_ACTIVATE, sent|wparam, 1 },
- { HCBT_SETFOCUS, hook },
+ { WM_ACTIVATE, sent|wparam|optional, 1 },
+ { HCBT_SETFOCUS, hook|optional },
{ WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
{ WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
- { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 },
{ WM_GETTEXT, sent|optional },
{ WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
{ HCBT_MINMAX, hook|lparam, 0, SW_RESTORE },
{ WM_QUERYOPEN, sent|optional },
{ WM_GETTEXT, sent|optional },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS },
- { WM_GETMINMAXINFO, sent|defwinproc },
- { WM_NCCALCSIZE, sent|wparam, TRUE },
- { HCBT_ACTIVATE, hook },
+ { WM_NCACTIVATE, sent|wparam|optional, 1 },
+ { WM_WINDOWPOSCHANGING, sent|optional }, /* SWP_NOSIZE|SWP_NOMOVE */
+ { WM_WINDOWPOSCHANGED, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE },
+ { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
+ { WM_MOVE, sent|optional },
+ { WM_SIZE, sent|wparam|optional, SIZE_RESTORED },
+ { WM_GETTEXT, sent|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_FRAMECHANGED|SWP_STATECHANGED|SWP_NOCOPYBITS },
+ { WM_GETMINMAXINFO, sent|defwinproc|optional },
+ { WM_NCCALCSIZE, sent|wparam|optional, TRUE },
+ { HCBT_ACTIVATE, hook|optional },
{ WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 },
{ WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
- { WM_ACTIVATEAPP, sent|wparam, 1 },
- { WM_NCACTIVATE, sent|wparam, 1 },
+ { WM_ACTIVATEAPP, sent|wparam|optional, 1 },
+ { WM_NCACTIVATE, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
- { WM_ACTIVATE, sent|wparam, 1 },
- { HCBT_SETFOCUS, hook },
+ { WM_ACTIVATE, sent|wparam|optional, 1 },
+ { HCBT_SETFOCUS, hook|optional },
{ WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 },
{ WM_IME_NOTIFY, sent|wparam|defwinproc|optional, 2 },
- { WM_SETFOCUS, sent|wparam|defwinproc, 0 },
+ { WM_SETFOCUS, sent|wparam|defwinproc|optional, 0 },
{ WM_GETTEXT, sent|optional },
{ WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_GETTEXT, sent|defwinproc|optional },
{ WM_WINDOWPOSCHANGED, sent|wparam, SWP_STATECHANGED|SWP_FRAMECHANGED|SWP_NOCOPYBITS },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_SETFOCUS, sent|wparam|optional, 0 },
{ WM_NCCALCSIZE, sent|wparam|optional, TRUE },
{ WM_NCPAINT, sent|wparam|optional, 1 },
{ WM_ERASEBKGND, sent|optional },
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_SETFOCUS, sent|wparam|optional, 0 },
{ WM_ACTIVATE, sent|wparam, 1 },
{ WM_GETTEXT, sent|optional },
{ WM_PAINT, sent|optional },
/* ShowWindow(SW_SHOWMINIMIZED) for a not visible overlapped window */
static const struct message WmShowMinOverlappedSeq[] = {
{ HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
- { HCBT_SETFOCUS, hook },
+ { HCBT_SETFOCUS, hook|optional },
{ EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 },
- { WM_KILLFOCUS, sent },
+ { WM_KILLFOCUS, sent|optional },
{ WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
{ WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
{ WM_GETTEXT, sent|optional },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ EVENT_SYSTEM_MINIMIZESTART, winevent_hook|wparam|lparam, 0, 0 },
- { WM_NCACTIVATE, sent|wparam, 0 },
+ { WM_NCACTIVATE, sent|wparam|optional, 0 },
{ WM_GETTEXT, sent|defwinproc|optional },
- { WM_ACTIVATE, sent },
- { WM_ACTIVATEAPP, sent|wparam, 0 },
+ { WM_ACTIVATE, sent|optional },
+ { WM_ACTIVATEAPP, sent|wparam|optional, 0 },
/* Vista sometimes restores the window right away... */
{ WM_SYSCOMMAND, sent|optional|wparam, SC_RESTORE },
{ WM_ACTIVATE, sent|wparam|optional, 0 },
{ WM_ACTIVATEAPP, sent|wparam|optional, 0 },
{ HCBT_SETFOCUS, hook|optional },
- { WM_KILLFOCUS, sent|wparam, 0 },
+ { WM_KILLFOCUS, sent|wparam|optional, 0 },
{ WM_IME_SETCONTEXT, sent|wparam|optional, 0 },
{ WM_IME_NOTIFY, sent|wparam|optional|defwinproc, 1 },
{ 0 }
{ WM_NCDESTROY, sent },
{ 0 }
};
-/* Moving the mouse in nonclient area */
-static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */
- { WM_NCHITTEST, sent },
- { WM_SETCURSOR, sent },
- { WM_NCMOUSEMOVE, posted },
- { 0 }
-};
-/* Moving the mouse in client area */
-static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */
- { WM_NCHITTEST, sent },
- { WM_SETCURSOR, sent },
- { WM_MOUSEMOVE, posted },
- { 0 }
-};
-/* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
-static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */
- { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION },
- { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 },
- { WM_GETMINMAXINFO, sent|defwinproc },
- { WM_ENTERSIZEMOVE, sent|defwinproc },
- { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
- { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
- { WM_MOVE, sent|defwinproc },
- { WM_EXITSIZEMOVE, sent|defwinproc },
- { 0 }
-};
-/* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */
-static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */
- { WM_NCLBUTTONDOWN, sent|wparam, 0xd },
- { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 },
- { WM_GETMINMAXINFO, sent|defwinproc },
- { WM_ENTERSIZEMOVE, sent|defwinproc },
- { WM_SIZING, sent|defwinproc|wparam, 4}, /* one for each mouse movement */
- { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, 0 },
- { WM_GETMINMAXINFO, sent|defwinproc },
- { WM_NCCALCSIZE, sent|defwinproc|wparam, 1 },
- { WM_NCPAINT, sent|defwinproc|wparam, 1 },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ERASEBKGND, sent|defwinproc },
- { WM_WINDOWPOSCHANGED, sent|wparam|defwinproc, 0 },
- { WM_MOVE, sent|defwinproc },
- { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
- { WM_EXITSIZEMOVE, sent|defwinproc },
- { 0 }
-};
/* Resizing child window with MoveWindow (32) */
static const struct message WmResizingChildWithMoveWindowSeq[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOACTIVATE },
{ EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 },
{ 0 }
};
-/* Clicking on inactive button */
-static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */
- { WM_NCHITTEST, sent },
- { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN },
- { WM_MOUSEACTIVATE, sent },
- { WM_MOUSEACTIVATE, sent|parent|defwinproc },
- { WM_SETCURSOR, sent },
- { WM_SETCURSOR, sent|parent|defwinproc },
- { WM_LBUTTONDOWN, posted },
- { WM_KILLFOCUS, posted|parent },
- { WM_SETFOCUS, posted },
- { WM_CTLCOLORBTN, posted|parent },
- { BM_SETSTATE, posted },
- { WM_CTLCOLORBTN, posted|parent },
- { WM_LBUTTONUP, posted },
- { BM_SETSTATE, posted },
- { WM_CTLCOLORBTN, posted|parent },
- { WM_COMMAND, posted|parent },
- { 0 }
-};
-/* Reparenting a button (16/32) */
-/* The last child (button) reparented gets topmost for its new parent. */
-static const struct message WmReparentButtonSeq[] = { /* FIXME: add */
- { WM_SHOWWINDOW, sent|wparam, 0 },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
- { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 },
- { WM_ERASEBKGND, sent|parent },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE },
- { WM_CHILDACTIVATE, sent },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW },
- { WM_MOVE, sent|defwinproc },
- { WM_SHOWWINDOW, sent|wparam, 1 },
- { 0 }
-};
/* Creation of a custom dialog (32) */
static const struct message WmCreateCustomDialogSeq[] = {
{ HCBT_CREATEWND, hook },
{ WM_NCDESTROY, sent },
{ 0 }
};
-/* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */
-static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */
- /* (inside dialog proc, handling WM_INITDIALOG) */
- { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
- { WM_NCCALCSIZE, sent },
- { WM_NCACTIVATE, sent|parent|wparam, 0 },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ACTIVATE, sent|parent|wparam, 0 },
- { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
- { WM_WINDOWPOSCHANGING, sent|parent },
- { WM_NCACTIVATE, sent|wparam, 1 },
- { WM_ACTIVATE, sent|wparam, 1 },
- { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
- { WM_SIZE, sent|defwinproc|wparam, SIZE_RESTORED },
- /* (setting focus) */
- { WM_SHOWWINDOW, sent|wparam, 1 },
- { WM_WINDOWPOSCHANGING, sent|wparam, 0 },
- { WM_NCPAINT, sent },
- { WM_GETTEXT, sent|defwinproc },
- { WM_ERASEBKGND, sent },
- { WM_CTLCOLORDLG, sent|defwinproc },
- { WM_WINDOWPOSCHANGED, sent|wparam, 0 },
- { WM_PAINT, sent },
- /* (bunch of WM_CTLCOLOR* for each control) */
- { WM_PAINT, sent|parent },
- { WM_ENTERIDLE, sent|parent|wparam, 0 },
- { WM_SETCURSOR, sent|parent },
- { 0 }
-};
/* SetMenu for NonVisible windows with size change*/
static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = {
{ WM_WINDOWPOSCHANGING, sent|wparam, SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOMOVE },
{ 0 }
};
-static int after_end_dialog, test_def_id;
+static const struct message WmTrackPopupMenu[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 },
+ { WM_INITMENU, sent|lparam, 0, 0 },
+ { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
+ { 0x0093, sent|optional },
+ { 0x0094, sent|optional },
+ { 0x0094, sent|optional },
+ { WM_ENTERIDLE, sent|wparam, 2 },
+ { WM_CAPTURECHANGED, sent },
+ { HCBT_DESTROYWND, hook },
+ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
+ { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
+ { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
+ { 0 }
+};
+
+static const struct message WmTrackPopupMenuCapture[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 },
+ { WM_CAPTURECHANGED, sent },
+ { WM_INITMENU, sent|lparam, 0, 0 },
+ { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
+ { 0x0093, sent|optional },
+ { 0x0094, sent|optional },
+ { 0x0094, sent|optional },
+ { WM_ENTERIDLE, sent|wparam, 2 },
+ { WM_CAPTURECHANGED, sent },
+ { HCBT_DESTROYWND, hook },
+ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
+ { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
+ { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
+ { 0 }
+};
+
+static const struct message WmTrackPopupMenuEmpty[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 },
+ { WM_INITMENU, sent|lparam, 0, 0 },
+ { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
+ { 0x0093, sent|optional },
+ { 0x0094, sent|optional },
+ { 0x0094, sent|optional },
+ { WM_CAPTURECHANGED, sent },
+ { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
+ { HCBT_DESTROYWND, hook },
+ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
+ { 0 }
+};
+
+static const struct message WmTrackPopupMenuAbort[] = {
+ { HCBT_CREATEWND, hook },
+ { WM_ENTERMENULOOP, sent|wparam|lparam, TRUE, 0 },
+ { WM_INITMENU, sent|lparam, 0, 0 },
+ { WM_INITMENUPOPUP, sent|lparam, 0, 0 },
+ { 0x0093, sent|optional },
+ { 0x0094, sent|optional },
+ { 0x0094, sent|optional },
+ { WM_CAPTURECHANGED, sent },
+ { HCBT_DESTROYWND, hook },
+ { WM_UNINITMENUPOPUP, sent|lparam, 0, 0 },
+ { WM_MENUSELECT, sent|wparam|lparam, 0xffff0000, 0 },
+ { WM_EXITMENULOOP, sent|wparam|lparam, 1, 0 },
+ { 0 }
+};
+
+static BOOL after_end_dialog, test_def_id, paint_loop_done;
static int sequence_cnt, sequence_size;
static struct recvd_message* sequence;
static int log_all_parent_messages;
-static int paint_loop_done;
+static CRITICAL_SECTION sequence_cs;
/* user32 functions */
static HWND (WINAPI *pGetAncestor)(HWND,UINT);
{
struct recvd_message *seq;
- if (!sequence)
+ EnterCriticalSection( &sequence_cs );
+ if (!sequence)
{
sequence_size = 10;
sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof(*sequence) );
}
assert(sequence);
- seq = &sequence[sequence_cnt];
+ seq = &sequence[sequence_cnt++];
seq->hwnd = msg->hwnd;
seq->message = msg->message;
seq->flags = msg->flags;
seq->line = line;
seq->descr = msg->descr;
seq->output[0] = 0;
+ LeaveCriticalSection( &sequence_cs );
if (msg->descr)
{
sprintf( seq->output + strlen(seq->output), " (flags %x)", msg->flags );
}
}
-
- sequence_cnt++;
}
/* try to make sure pending X events have been processed before continuing */
static void flush_sequence(void)
{
+ EnterCriticalSection( &sequence_cs );
HeapFree(GetProcessHeap(), 0, sequence);
sequence = 0;
sequence_cnt = sequence_size = 0;
+ LeaveCriticalSection( &sequence_cs );
}
static void dump_sequence(const struct message *expected, const char *context, const char *file, int line)
ok_sequence_( (exp), (contx), (todo), __FILE__, __LINE__)
-static void ok_sequence_(const struct message *expected_list, const char *context, int todo,
+static void ok_sequence_(const struct message *expected_list, const char *context, BOOL todo,
const char *file, int line)
{
static const struct recvd_message end_of_sequence;
{ 0 }
};
+static void CALLBACK apc_test_proc(ULONG_PTR param)
+{
+ /* nothing */
+}
+
static void test_MsgWaitForMultipleObjects(HWND hwnd)
{
DWORD ret;
ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
+
+ /* MWMO_INPUTAVAILABLE should succeed even if the message was already seen */
+ PostMessageA( hwnd, WM_USER, 0, 0 );
+ ok(PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ), "PeekMessage should succeed\n");
+ ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
+
+ ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_INPUTAVAILABLE );
+ ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
+
+ ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
+ ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
+
+ /* without MWMO_ALERTABLE the result is never WAIT_IO_COMPLETION */
+ ret = QueueUserAPC( apc_test_proc, GetCurrentThread(), 0 );
+ ok(ret, "QueueUserAPC failed %u\n", GetLastError());
+
+ ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, 0 );
+ ok(ret == WAIT_TIMEOUT, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
+
+ /* but even with MWMO_ALERTABLE window events are preferred */
+ PostMessageA( hwnd, WM_USER, 0, 0 );
+
+ ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE );
+ ok(ret == WAIT_OBJECT_0, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
+
+ ok(PeekMessageA( &msg, 0, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n");
+ ok(msg.message == WM_USER, "got %04x instead of WM_USER\n", msg.message);
+
+ /* the APC call is still queued */
+ ret = MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_POSTMESSAGE, MWMO_ALERTABLE );
+ ok(ret == WAIT_IO_COMPLETION, "MsgWaitForMultipleObjectsEx returned %x\n", ret);
+}
+
+static DWORD CALLBACK show_window_thread(LPVOID arg)
+{
+ HWND hwnd = arg;
+
+ /* function will not return if ShowWindow(SW_HIDE) calls SendMessage() */
+ ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
+
+ return 0;
}
/* test if we receive the right sequence of messages */
static void test_messages(void)
{
+ DWORD tid;
+ HANDLE hthread;
HWND hwnd, hparent, hchild;
HWND hchild2, hbutton;
HMENU hmenu;
MSG msg;
LRESULT res;
+ POINT pos;
+ BOOL ret;
flush_sequence();
flush_events();
ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
+ /* test ShowWindow(SW_HIDE) on a hidden window - single threaded */
+ ok(ShowWindow(hwnd, SW_HIDE) == FALSE, "ShowWindow(SW_HIDE) expected FALSE\n");
+ flush_events();
+ ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
+
+ /* test ShowWindow(SW_HIDE) on a hidden window - multi-threaded */
+ hthread = CreateThread(NULL, 0, show_window_thread, hwnd, 0, &tid);
+ ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
+ ok(WaitForSingleObject(hthread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+ CloseHandle(hthread);
+ flush_events();
+ ok_sequence(WmEmptySeq, "ShowWindow(SW_HIDE):overlapped", FALSE);
+
ShowWindow(hwnd, SW_SHOW);
flush_events();
ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped", TRUE);
flush_sequence();
- test_def_id = 1;
+ test_def_id = TRUE;
SendMessageA(hwnd, WM_NULL, 0, 0);
flush_sequence();
- after_end_dialog = 1;
+ after_end_dialog = TRUE;
EndDialog( hwnd, 0 );
ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog", FALSE);
DestroyWindow(hwnd);
- after_end_dialog = 0;
- test_def_id = 0;
+ after_end_dialog = FALSE;
+ test_def_id = FALSE;
- hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP,
+ ok(GetCursorPos(&pos), "GetCursorPos failed\n");
+ ok(SetCursorPos(109, 109), "SetCursorPos failed\n");
+
+ hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_POPUP|WS_CHILD,
0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL);
ok(hwnd != 0, "Failed to create custom dialog window\n");
flush_sequence();
trace("call ShowWindow(%p, SW_SHOW)\n", hwnd);
ShowWindow(hwnd, SW_SHOW);
ok_sequence(WmShowCustomDialogSeq, "ShowCustomDialog", TRUE);
+
+ flush_events();
+ flush_sequence();
+ ret = DrawMenuBar(hwnd);
+ ok(ret, "DrawMenuBar failed: %d\n", GetLastError());
+ flush_events();
+ ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar", FALSE);
+ ok(SetCursorPos(pos.x, pos.y), "SetCursorPos failed\n");
+
+ DestroyWindow(hwnd);
+
+ hwnd = CreateWindowExA(0, "TestDialogClass", NULL, WS_CHILD|WS_VISIBLE,
+ 0, 0, 100, 100, hparent, 0, GetModuleHandleA(0), NULL);
+ ok(hwnd != 0, "Failed to create custom dialog window\n");
+ flush_events();
+ flush_sequence();
+ ret = DrawMenuBar(hwnd);
+ ok(ret, "DrawMenuBar failed: %d\n", GetLastError());
+ flush_events();
+ ok_sequence(WmEmptySeq, "DrawMenuBar for a child window", FALSE);
+
DestroyWindow(hwnd);
flush_sequence();
flush_sequence();
/* Message sequence for SetMenu */
- ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a window without a menu\n");
+ ok(!DrawMenuBar(hwnd), "DrawMenuBar should return FALSE for a destroyed window\n");
+ ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "last error is %d\n", GetLastError());
ok_sequence(WmEmptySeq, "DrawMenuBar for a window without a menu", FALSE);
hmenu = CreateMenu();
ret = pGetCurrentActCtx(&handle);
ok(ret, "GetCurentActCtx failed: %u\n", GetLastError());
ok(handle != 0, "active context %p\n", handle);
+ pReleaseActCtx(handle);
/* destination window will test for active context */
ret = SendMessageA(wnd_event.hwnd, WM_USER+10, 0, 0);
}
else ok(broken(1), "infinite loop\n");
if ( i == 0)
- paint_loop_done = 1;
+ paint_loop_done = TRUE;
return DefWindowProcA(hWnd,msg,wParam,lParam);
}
}
}
#define TIMER_ID 0x19
-#define TIMER_COUNT_EXPECTED 64
-#define TIMER_COUNT_TOLERANCE 9
+#define TIMER_COUNT_EXPECTED 100
+#define TIMER_COUNT_TOLERANCE 10
static int count = 0;
static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
count++;
}
+static DWORD exception;
+static void CALLBACK callback_exception(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+ count++;
+ RaiseException(exception, 0, 0, NULL);
+}
+
static DWORD WINAPI timer_thread_proc(LPVOID x)
{
struct timer_info *info = x;
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
- * but testing indicates that the minimum timeout is actually about 15.6 ms. Since there is
- * some measurement error between test runs we're allowing for ±8 counts (~2 ms).
+ * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
+ * 15.6 ms. Since there is some measurement error between test runs we are allowing for
+ * ±9 counts (~4 ms) around the expected value.
*/
count = 0;
id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
start = GetTickCount();
while (GetTickCount()-start < 1001 && GetMessageA(&msg, info.hWnd, 0, 0))
DispatchMessageA(&msg);
- ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE
- || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3 */,
+ ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */
+ || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */
+ || broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3, win8 */,
"did not get expected count for minimum timeout (%d != ~%d).\n",
count, TIMER_COUNT_EXPECTED);
ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
syscount++;
DispatchMessageA(&msg);
}
- ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE,
+ ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE
+ || broken(abs(syscount-64) < TIMER_COUNT_TOLERANCE) /* most common */
+ || broken(syscount > 4000 && syscount < 12000) /* win2k3sp0 */,
"did not get expected count for minimum timeout (%d != ~%d).\n",
syscount, TIMER_COUNT_EXPECTED);
todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n",
ok(count == 1, "killing replaced timer did not work (%i).\n", count);
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
- * but testing indicates that the minimum timeout is actually about 15.6 ms. Since there is
- * some measurement error between test runs we're allowing for ±8 counts (~2 ms).
+ * which occurs sometimes, but most testing on the VMs indicates a minimum timeout closer to
+ * 15.6 ms. Since there is some measurement error between test runs we are allowing for
+ * ±9 counts (~4 ms) around the expected value.
*/
count = 0;
id = SetTimer(NULL, 0, 0, callback_count);
start = GetTickCount();
while (GetTickCount()-start < 1001 && GetMessageA(&msg, NULL, 0, 0))
DispatchMessageA(&msg);
- ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE,
+ ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE /* xp */
+ || broken(abs(count-64) < TIMER_COUNT_TOLERANCE) /* most common */,
"did not get expected count for minimum timeout (%d != ~%d).\n",
count, TIMER_COUNT_EXPECTED);
KillTimer(NULL, id);
/* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
}
+static void test_timers_exception(DWORD code)
+{
+ UINT_PTR id;
+ MSG msg;
+
+ exception = code;
+ id = SetTimer(NULL, 0, 1000, callback_exception);
+ ok(id != 0, "did not get id from SetTimer.\n");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.message = WM_TIMER;
+ msg.wParam = id;
+ msg.lParam = (LPARAM)callback_exception;
+
+ count = 0;
+ DispatchMessageA(&msg);
+ ok(count == 1, "did not get one count as expected (%i).\n", count);
+
+ KillTimer(NULL, id);
+}
+
+static void test_timers_exceptions(void)
+{
+ test_timers_exception(EXCEPTION_ACCESS_VIOLATION);
+ test_timers_exception(EXCEPTION_DATATYPE_MISALIGNMENT);
+ test_timers_exception(EXCEPTION_BREAKPOINT);
+ test_timers_exception(EXCEPTION_SINGLE_STEP);
+ test_timers_exception(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
+ test_timers_exception(EXCEPTION_FLT_DENORMAL_OPERAND);
+ test_timers_exception(EXCEPTION_FLT_DIVIDE_BY_ZERO);
+ test_timers_exception(EXCEPTION_FLT_INEXACT_RESULT);
+ test_timers_exception(EXCEPTION_ILLEGAL_INSTRUCTION);
+ test_timers_exception(0xE000BEEF); /* customer exception */
+}
+
/* Various win events with arbitrary parameters */
static const struct message WmWinEventsSeq[] = {
{ EVENT_SYSTEM_SOUND, winevent_hook|wparam|lparam, OBJID_WINDOW, 0 },
trace("start scroll\n");
ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL,
SW_ERASE|SW_INVALIDATE);
- ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
+ ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE);
trace("end scroll\n");
flush_sequence();
flush_events();
- ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
+ ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE);
flush_events();
flush_sequence();
/* Now without the SW_ERASE flag */
trace("start scroll\n");
ScrollWindowEx( hwnd, 10, 10, &rect, NULL, NULL, NULL, SW_INVALIDATE);
- ok_sequence(WmEmptySeq, "ScrollWindowEx", 0);
+ ok_sequence(WmEmptySeq, "ScrollWindowEx", FALSE);
trace("end scroll\n");
flush_sequence();
flush_events();
- ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", 0);
+ ok_sequence(ScrollWindowPaint2, "ScrollWindowEx", FALSE);
flush_events();
flush_sequence();
trace("end scroll\n");
flush_sequence();
flush_events();
- ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", 0);
+ ok_sequence(ScrollWindowPaint1, "ScrollWindowEx", FALSE);
flush_events();
flush_sequence();
trace("end scroll\n");
flush_sequence();
flush_events();
- ok_sequence(ScrollWindowPaint1, "ScrollWindow", 0);
+ ok_sequence(ScrollWindowPaint1, "ScrollWindow", FALSE);
ok(DestroyWindow(hchild), "failed to destroy window\n");
ok(DestroyWindow(hwnd), "failed to destroy window\n");
ret = DestroyWindow(parent);
ok( ret, "DestroyWindow() error %d\n", GetLastError());
test_DestroyWindow_flag = FALSE;
- ok_sequence(destroy_window_with_children, "destroy window with children", 0);
+ ok_sequence(destroy_window_with_children, "destroy window with children", FALSE);
ok(!IsWindow(parent), "parent still exists\n");
ok(!IsWindow(child1), "child1 still exists\n");
{
MSG msg;
DWORD time;
- BOOL ret;
- int go = 0;
+ BOOL ret, go = FALSE;
time = GetTickCount();
while (GetTickCount() - time < 200 && !go) {
flush_events();
}
+static void test_PeekMessage3(void)
+{
+ HWND hwnd;
+ BOOL ret;
+ MSG msg;
+
+ hwnd = CreateWindowA("TestWindowClass", "PeekMessage3", WS_OVERLAPPEDWINDOW,
+ 10, 10, 800, 800, NULL, NULL, NULL, NULL);
+ ok(hwnd != NULL, "expected hwnd != NULL\n");
+ flush_events();
+
+ /* GetMessage() and PeekMessage(..., PM_REMOVE) should prefer messages which
+ * were already seen. */
+
+ SetTimer(hwnd, 1, 0, NULL);
+ while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ SetTimer(hwnd, 1, 0, NULL);
+ while (!PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ /* It doesn't matter if a message range is specified or not. */
+
+ SetTimer(hwnd, 1, 0, NULL);
+ while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ /* But not if the post messages were added before the PeekMessage() call. */
+
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ SetTimer(hwnd, 1, 0, NULL);
+ while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ /* More complicated test with multiple messages. */
+
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ SetTimer(hwnd, 1, 0, NULL);
+ while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ PostMessageA(hwnd, WM_USER + 1, 0, 0);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER + 1, "msg.message = %u instead of WM_USER + 1\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ /* Also works for posted messages, but the situation is a bit different,
+ * because both messages are in the same queue. */
+
+ PostMessageA(hwnd, WM_TIMER, 0, 0);
+ while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ PostMessageA(hwnd, WM_USER, 0, 0);
+ PostMessageA(hwnd, WM_TIMER, 0, 0);
+ while (!PeekMessageA(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE));
+ ok(msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_USER, "msg.message = %u instead of WM_USER\n", msg.message);
+ ret = GetMessageA(&msg, NULL, 0, 0);
+ ok(ret && msg.message == WM_TIMER, "msg.message = %u instead of WM_TIMER\n", msg.message);
+ ret = PeekMessageA(&msg, NULL, 0, 0, 0);
+ ok(!ret, "expected PeekMessage to return FALSE, got %u\n", ret);
+
+ DestroyWindow(hwnd);
+ flush_events();
+}
+
static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
{
struct recvd_message msg;
flush_events();
PostQuitMessage(0xbeef);
+ msg.message = 0;
+ ret = PeekMessageA(&msg, 0, 0, 0, PM_QS_SENDMESSAGE);
+ ok(!ret, "got %x message\n", msg.message);
+
ret = PeekMessageA(&msg, NULL, 0, 0, PM_NOREMOVE);
ok(ret, "PeekMessage failed with error %d\n", GetLastError());
ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message);
};
static const struct message WmShowNoActivate_2[] = {
{ HCBT_MINMAX, hook|lparam, 0, SW_SHOWNOACTIVATE },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
+ { HCBT_ACTIVATE, hook|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+ { HCBT_SETFOCUS, hook|optional },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|defwinproc, SIZE_RESTORED },
{ HCBT_SETFOCUS, hook|optional },
static const struct message WmMinimize_2[] = {
{ HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
{ HCBT_SETFOCUS, hook|optional },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
};
static const struct message WmMinimize_3[] = {
{ HCBT_MINMAX, hook|lparam, 0, SW_MINIMIZE },
- { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
- { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED },
+ { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
+ { HCBT_ACTIVATE, hook|optional },
+ { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE },
+ { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOCOPYBITS|SWP_STATECHANGED, 0, SWP_NOACTIVATE },
{ WM_MOVE, sent|defwinproc },
{ WM_SIZE, sent|wparam|lparam|defwinproc, SIZE_MINIMIZED, 0 },
{ 0 }
win_rc.left, win_rc.top, win_rc.right, win_rc.bottom,
wp.rcNormalPosition.left, wp.rcNormalPosition.top,
wp.rcNormalPosition.right, wp.rcNormalPosition.bottom);
-
- flush_events();
- flush_sequence();
}
-
DestroyWindow(hwnd);
+ flush_events();
}
static INT_PTR WINAPI test_dlg_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
PostMessageW( hwnd, WM_CHAR, 0x3b1, 0 );
- ok( GetMessageW( &msg, hwnd, 0, 0 ), "no message\n" );
- ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
+ while (GetMessageW( &msg, hwnd, 0, 0 ))
+ {
+ if (!ignore_message( msg.message )) break;
+ }
+
+ ok( msg.hwnd == hwnd, "unexpected hwnd %p\n", msg.hwnd );
ok( msg.message == WM_CHAR, "unexpected message %x\n", msg.message );
ok( msg.wParam == 0x3b1, "bad wparam %lx\n", msg.wParam );
ok( msg.lParam == 0, "bad lparam %lx\n", msg.lParam );
SetMenu(hwnd, hmenu);
SetForegroundWindow( hwnd );
+ flush_events();
set_menu_style(hmenu, MNS_NOTIFYBYPOS);
style = get_menu_style(hmenu);
{
HWND hwnd;
- paint_loop_done = 0;
+ paint_loop_done = FALSE;
hwnd = CreateWindowExA(0x0,"PaintLoopWindowClass",
"PaintLoopWindowClass",WS_OVERLAPPEDWINDOW,
100, 100, 100, 100, 0, 0, 0, NULL );
{
HWND hwnd;
MSG msg;
- int gotwmquit = FALSE;
+ BOOL gotwmquit = FALSE;
hwnd = CreateWindowExA(0, "static", "test_defwndproc", WS_POPUP, 0,0,0,0,0,0,0, NULL);
assert(hwnd);
DefWindowProcA( hwnd, WM_ENDSESSION, 1, 0);
if( msg.message == WM_QUIT) gotwmquit = TRUE;
DispatchMessageA( &msg );
}
- ok( gotwmquit == FALSE, "Unexpected WM_QUIT message!\n");
+ ok(!gotwmquit, "Unexpected WM_QUIT message!\n");
DestroyWindow( hwnd);
}
{
ResetEvent( start_event );
ResetEvent( end_event );
+#ifndef __REACTOS__
sprintf( path, "%s msg %u", argv0, i );
+#else
+ sprintf( path, "%s msg_queue %u", argv0, i );
+#endif
ret = CreateProcessA( NULL, path, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi );
ok( ret, "CreateProcess '%s' failed err %u.\n", path, GetLastError() );
if (ret)
{ HCBT_SETFOCUS, hook }, /* child */
{ 0 }
};
-static const struct message WmSetFocus_4[] = {
- { 0 }
-};
static void test_SetFocus(void)
{
ret = AttachThreadInput(GetCurrentThreadId(), tid, TRUE);
ok(ret, "AttachThreadInput error %d\n", GetLastError());
-todo_wine {
ok(GetActiveWindow() == parent, "expected active %p, got %p\n", parent, GetActiveWindow());
ok(GetFocus() == parent, "expected focus %p, got %p\n", parent, GetFocus());
-}
+
flush_events();
flush_sequence();
DeleteObject( bmp );
}
+static HMENU hpopupmenu;
+
+static LRESULT WINAPI cancel_popup_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (ignore_message( message )) return 0;
+
+ switch (message) {
+ case WM_ENTERIDLE:
+ todo_wine ok(GetCapture() == hwnd, "expected %p, got %p\n", hwnd, GetCapture());
+ EndMenu();
+ break;
+ case WM_INITMENU:
+ case WM_INITMENUPOPUP:
+ case WM_UNINITMENUPOPUP:
+ ok((HMENU)wParam == hpopupmenu, "expected %p, got %lx\n", hpopupmenu, wParam);
+ break;
+ case WM_CAPTURECHANGED:
+ todo_wine ok(!lParam || (HWND)lParam == hwnd, "lost capture to %lx\n", lParam);
+ break;
+ }
+
+ return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
+}
+
+static LRESULT WINAPI cancel_init_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ if (ignore_message( message )) return 0;
+
+ switch (message) {
+ case WM_ENTERMENULOOP:
+ ok(EndMenu() == TRUE, "EndMenu() failed\n");
+ break;
+ }
+
+ return MsgCheckProc (FALSE, hwnd, message, wParam, lParam);
+}
+
+static void test_TrackPopupMenu(void)
+{
+ HWND hwnd;
+ BOOL ret;
+
+ hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0,
+ 0, 0, 1, 1, 0,
+ NULL, NULL, 0);
+ ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
+
+ SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
+
+ hpopupmenu = CreatePopupMenu();
+ ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+
+ AppendMenuA(hpopupmenu, MF_STRING, 100, "item 1");
+ AppendMenuA(hpopupmenu, MF_STRING, 100, "item 2");
+
+ flush_events();
+ flush_sequence();
+ ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL);
+ ok_sequence(WmTrackPopupMenu, "TrackPopupMenu", TRUE);
+ ok(ret == 1, "TrackPopupMenu failed with error %i\n", GetLastError());
+
+ SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_init_proc);
+
+ flush_events();
+ flush_sequence();
+ ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL);
+ ok_sequence(WmTrackPopupMenuAbort, "WmTrackPopupMenuAbort", TRUE);
+ ok(ret == TRUE, "TrackPopupMenu failed\n");
+
+ SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
+
+ SetCapture(hwnd);
+
+ flush_events();
+ flush_sequence();
+ ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL);
+ ok_sequence(WmTrackPopupMenuCapture, "TrackPopupMenuCapture", TRUE);
+ ok(ret == 1, "TrackPopupMenuCapture failed with error %i\n", GetLastError());
+
+ DestroyMenu(hpopupmenu);
+ DestroyWindow(hwnd);
+}
+
+static void test_TrackPopupMenuEmpty(void)
+{
+ HWND hwnd;
+ BOOL ret;
+
+ hwnd = CreateWindowExA(0, "TestWindowClass", NULL, 0,
+ 0, 0, 1, 1, 0,
+ NULL, NULL, 0);
+ ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
+
+ SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (LONG_PTR)cancel_popup_proc);
+
+ hpopupmenu = CreatePopupMenu();
+ ok(hpopupmenu != NULL, "CreateMenu failed with error %d\n", GetLastError());
+
+ flush_events();
+ flush_sequence();
+ ret = TrackPopupMenu(hpopupmenu, 0, 100,100, 0, hwnd, NULL);
+ ok_sequence(WmTrackPopupMenuEmpty, "TrackPopupMenuEmpty", TRUE);
+ todo_wine ok(ret == 0, "TrackPopupMenu succeeded\n");
+
+ DestroyMenu(hpopupmenu);
+ DestroyWindow(hwnd);
+}
+
+static const struct message send_message_1[] = {
+ { WM_USER+2, sent|wparam|lparam, 0, 0 },
+ { WM_USER, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+static const struct message send_message_2[] = {
+ { WM_USER+4, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+static const struct message send_message_3[] = {
+ { WM_USER+3, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+static const struct message send_message_4[] = {
+ { WM_USER+1, sent|wparam|lparam, 0, 0 },
+ { 0 }
+};
+
+static DWORD WINAPI SendMessage_thread_1(void *param)
+{
+ struct wnd_event *wnd_event = param;
+
+ trace("thread: starting\n");
+ WaitForSingleObject(wnd_event->start_event, INFINITE);
+
+ trace("thread: call PostMessage\n");
+ PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
+
+ trace("thread: call PostMessage\n");
+ PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
+
+ trace("thread: call SendMessage\n");
+ SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
+
+ trace("thread: call SendMessage\n");
+ SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
+
+ return 0;
+}
+
+static DWORD WINAPI SendMessage_thread_2(void *param)
+{
+ struct wnd_event *wnd_event = param;
+
+ trace("thread: starting\n");
+ WaitForSingleObject(wnd_event->start_event, INFINITE);
+
+ trace("thread: call PostMessage\n");
+ PostMessageA(wnd_event->hwnd, WM_USER, 0, 0);
+
+ trace("thread: call PostMessage\n");
+ PostMessageA(wnd_event->hwnd, WM_USER+1, 0, 0);
+
+ /* this leads to sending an internal message under Wine */
+ trace("thread: call EnableWindow\n");
+ EnableWindow(wnd_event->hwnd, TRUE);
+
+ trace("thread: call SendMessage\n");
+ SendMessageA(wnd_event->hwnd, WM_USER+2, 0, 0);
+
+ trace("thread: call SendMessage\n");
+ SendMessageA(wnd_event->hwnd, WM_USER+3, 0, 0);
+
+ return 0;
+}
+
+static void test_SendMessage_other_thread(int thread_n)
+{
+ DWORD qs_all_input = QS_ALLINPUT & ~QS_RAWINPUT;
+ HANDLE hthread;
+ struct wnd_event wnd_event;
+ DWORD tid, ret;
+ MSG msg;
+
+ wnd_event.start_event = CreateEventA(NULL, 0, 0, NULL);
+
+ wnd_event.hwnd = CreateWindowExA(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+ ok(wnd_event.hwnd != 0, "CreateWindowEx failed\n");
+
+ hthread = CreateThread(NULL, 0, thread_n == 1 ? SendMessage_thread_1 : SendMessage_thread_2, &wnd_event, 0, &tid);
+ ok(hthread != NULL, "CreateThread failed, error %d\n", GetLastError());
+ CloseHandle(hthread);
+
+ flush_events();
+ flush_sequence();
+
+ ret = GetQueueStatus(QS_SENDMESSAGE);
+ ok(ret == 0, "wrong status %08x\n", ret);
+
+ SetEvent(wnd_event.start_event);
+
+ /* wait for other thread's SendMessage */
+ for (;;)
+ {
+ ret = GetQueueStatus(QS_SENDMESSAGE);
+ if (ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE)) break;
+ Sleep(50);
+ }
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ ok(ret == MAKELONG(QS_POSTMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
+
+ trace("main: call GetMessage\n");
+ GetMessageA(&msg, 0, 0, 0);
+ ok(msg.message == WM_USER, "expected WM_USER, got %04x\n", msg.message);
+ DispatchMessageA(&msg);
+ ok_sequence(send_message_1, "SendMessage from other thread 1", thread_n == 2);
+
+ /* intentionally yield */
+ MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
+
+ trace("main: call SendMessage\n");
+ SendMessageA(wnd_event.hwnd, WM_USER+4, 0, 0);
+ ok_sequence(send_message_2, "SendMessage from other thread 2", FALSE);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ ok(ret == MAKELONG(QS_SENDMESSAGE, QS_SENDMESSAGE|QS_POSTMESSAGE), "wrong status %08x\n", ret);
+
+ trace("main: call PeekMessage\n");
+ ok(PeekMessageA(&msg, 0, 0, 0, PM_NOREMOVE), "PeekMessage should not fail\n");
+ ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message);
+ ok_sequence(send_message_3, "SendMessage from other thread 3", thread_n == 2);
+
+ trace("main: call PeekMessage\n");
+ ok(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should not fail\n");
+ ok(msg.message == WM_USER+1, "expected WM_USER+1, got %04x\n", msg.message);
+ DispatchMessageA(&msg);
+ ok_sequence(send_message_4, "SendMessage from other thread 4", FALSE);
+
+ /* intentionally yield */
+ MsgWaitForMultipleObjects(0, NULL, FALSE, 100, qs_all_input);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ /* FIXME: remove once Wine is fixed */
+if (thread_n == 2) todo_wine
+ ok(ret == 0, "wrong status %08x\n", ret);
+else
+ ok(ret == 0, "wrong status %08x\n", ret);
+
+ trace("main: call PeekMessage\n");
+ ok(!PeekMessageA(&msg, 0, 0, 0, PM_REMOVE), "PeekMessage should fail\n");
+ ok_sequence(WmEmptySeq, "SendMessage from other thread 5", thread_n == 2);
+
+ ret = GetQueueStatus(QS_SENDMESSAGE|QS_POSTMESSAGE);
+ ok(ret == 0, "wrong status %08x\n", ret);
+
+ trace("main: call DestroyWindow\n");
+ DestroyWindow(msg.hwnd);
+
+ flush_events();
+ flush_sequence();
+}
+
static void init_funcs(void)
{
HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
#undef X
}
+#ifndef __REACTOS__
START_TEST(msg)
{
char **test_argv;
return;
}
+ InitializeCriticalSection( &sequence_cs );
init_procs();
hModuleImm32 = LoadLibraryA("imm32.dll");
test_winevents();
/* Fix message sequences before removing 4 lines below */
-#if 1
if (pUnhookWinEvent && hEvent_hook)
{
ret = pUnhookWinEvent(hEvent_hook);
pUnhookWinEvent = 0;
}
hEvent_hook = 0;
-#endif
+ test_SendMessage_other_thread(1);
+ test_SendMessage_other_thread(2);
test_SetFocus();
test_SetParent();
test_PostMessage();
test_ShowWindow();
test_PeekMessage();
test_PeekMessage2();
+ test_PeekMessage3();
test_WaitForInputIdle( test_argv[0] );
test_scrollwindowex();
test_messages();
test_accelerators();
test_timers();
test_timers_no_wnd();
+ test_timers_exceptions();
if (hCBT_hook) test_set_hook();
test_DestroyWindow();
test_DispatchMessage();
test_keyflags();
test_hotkey();
test_layered_window();
+ if(!winetest_interactive)
+ skip("CORE-8299 : Skip Tracking popup menu tests.\n");
+ else
+ {
+ test_TrackPopupMenu();
+ test_TrackPopupMenuEmpty();
+ }
/* keep it the last test, under Windows it tends to break the tests
* which rely on active/foreground windows being correct.
*/
GetLastError() == 0xdeadbeef, /* Win9x */
"unexpected error %d\n", GetLastError());
}
+ DeleteCriticalSection( &sequence_cs );
+}
+#endif /* __REACTOS__ */
+
+static void init_tests()
+{
+ HMODULE hModuleImm32;
+ BOOL (WINAPI *pImmDisableIME)(DWORD);
+
+ init_funcs();
+
+ InitializeCriticalSection( &sequence_cs );
+ init_procs();
+
+ hModuleImm32 = LoadLibraryA("imm32.dll");
+ if (hModuleImm32) {
+ pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME");
+ if (pImmDisableIME)
+ pImmDisableIME(0);
+ }
+ pImmDisableIME = NULL;
+ FreeLibrary(hModuleImm32);
+
+ if (!RegisterWindowClasses()) assert(0);
+
+ cbt_hook_thread_id = GetCurrentThreadId();
+ hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
+ if (!hCBT_hook) win_skip( "cannot set global hook, will skip hook tests\n" );
+}
+
+static void cleanup_tests()
+{
+ BOOL ret;
+ UnhookWindowsHookEx(hCBT_hook);
+ if (pUnhookWinEvent && hEvent_hook)
+ {
+ ret = pUnhookWinEvent(hEvent_hook);
+ ok( ret, "UnhookWinEvent error %d\n", GetLastError());
+ SetLastError(0xdeadbeef);
+ ok(!pUnhookWinEvent(hEvent_hook), "UnhookWinEvent succeeded\n");
+ ok(GetLastError() == ERROR_INVALID_HANDLE || /* Win2k */
+ GetLastError() == 0xdeadbeef, /* Win9x */
+ "unexpected error %d\n", GetLastError());
+ }
+ DeleteCriticalSection( &sequence_cs );
+
+}
+
+START_TEST(msg_queue)
+{
+ int argc;
+ char **test_argv;
+ argc = winetest_get_mainargs( &test_argv );
+ if (argc >= 3)
+ {
+ unsigned int arg;
+ /* Child process. */
+ sscanf (test_argv[2], "%d", (unsigned int *) &arg);
+ do_wait_idle_child( arg );
+ return;
+ }
+
+ init_tests();
+ test_SendMessage_other_thread(1);
+ test_SendMessage_other_thread(2);
+ test_PostMessage();
+ test_PeekMessage();
+ test_PeekMessage2();
+ test_PeekMessage3();
+ test_interthread_messages();
+ test_DispatchMessage();
+ test_SendMessageTimeout();
+ test_quit_message();
+ test_WaitForInputIdle( test_argv[0] );
+ test_DestroyWindow();
+ cleanup_tests();
+}
+
+START_TEST(msg_messages)
+{
+ init_tests();
+ test_message_conversion();
+ test_messages();
+ test_wmime_keydown_message();
+ test_nullCallback();
+ test_dbcs_wm_char();
+ test_unicode_wm_char();
+ test_defwinproc();
+ cleanup_tests();
+}
+
+START_TEST(msg_focus)
+{
+ init_tests();
+
+ test_SetFocus();
+
+ /* HACK: For some reason the tests fail on Windows if run consecutively.
+ * Putting these in between helps, and is essentially what happens in the
+ * "normal" msg test. */
+ keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
+ flush_events();
+
+ test_SetActiveWindow();
+
+ /* HACK */
+ keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
+ flush_events();
+
+ /* keep it the last test, under Windows it tends to break the tests
+ * which rely on active/foreground windows being correct.
+ */
+ test_SetForegroundWindow();
+ cleanup_tests();
+}
+
+START_TEST(msg_winpos)
+{
+ init_tests();
+ test_SetParent();
+ test_ShowWindow();
+ test_setwindowpos();
+ test_showwindow();
+ test_SetWindowRgn();
+ invisible_parent_tests();
+ cleanup_tests();
+}
+
+START_TEST(msg_paint)
+{
+ init_tests();
+ test_scrollwindowex();
+ test_paint_messages();
+#ifdef __REACTOS__
+ if (!winetest_interactive &&
+ !strcmp(winetest_platform, "windows"))
+ {
+ skip("ROSTESTS-185: Skipping user32_winetest:msg_paint test_paintingloop because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
+ }
+ else
+#endif
+ test_paintingloop();
+ cleanup_tests();
+}
+
+START_TEST(msg_input)
+{
+ init_tests();
+ test_accelerators();
+ if (!pTrackMouseEvent)
+ win_skip("TrackMouseEvent is not available\n");
+ else
+ test_TrackMouseEvent();
+
+ test_keyflags();
+ test_hotkey();
+ cleanup_tests();
+}
+
+START_TEST(msg_timer)
+{
+ init_tests();
+ test_timers();
+ test_timers_no_wnd();
+ test_timers_exceptions();
+ cleanup_tests();
+}
+
+typedef BOOL (WINAPI *IS_WINEVENT_HOOK_INSTALLED)(DWORD);
+
+START_TEST(msg_hook)
+{
+// HMODULE user32 = GetModuleHandleA("user32.dll");
+// IS_WINEVENT_HOOK_INSTALLED pIsWinEventHookInstalled = (IS_WINEVENT_HOOK_INSTALLED)GetProcAddress(user32, "IsWinEventHookInstalled");
+ BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/
+
+ init_tests();
+
+ if (pSetWinEventHook)
+ {
+ hEvent_hook = pSetWinEventHook(EVENT_MIN, EVENT_MAX,
+ GetModuleHandleA(0), win_event_proc,
+ 0, GetCurrentThreadId(),
+ WINEVENT_INCONTEXT);
+ if (pIsWinEventHookInstalled && hEvent_hook)
+ {
+ UINT event;
+ for (event = EVENT_MIN; event <= EVENT_MAX; event++)
+ ok(pIsWinEventHookInstalled(event), "IsWinEventHookInstalled(%u) failed\n", event);
+ }
+ }
+ if (!hEvent_hook) win_skip( "no win event hook support\n" );
+
+ test_winevents();
+
+ /* Fix message sequences before removing 4 lines below */
+ if (pUnhookWinEvent && hEvent_hook)
+ {
+ BOOL ret;
+ ret = pUnhookWinEvent(hEvent_hook);
+ ok( ret, "UnhookWinEvent error %d\n", GetLastError());
+ pUnhookWinEvent = 0;
+ }
+ hEvent_hook = 0;
+ if (hCBT_hook) test_set_hook();
+ cleanup_tests();
+}
+
+START_TEST(msg_menu)
+{
+ init_tests();
+ test_sys_menu();
+ test_menu_messages();
+ if(!winetest_interactive)
+ skip("CORE-8299 : Skip Tracking popup menu tests.\n");
+ else
+ {
+ test_TrackPopupMenu();
+ test_TrackPopupMenuEmpty();
+ }
+ cleanup_tests();
+}
+
+START_TEST(msg_mdi)
+{
+ init_tests();
+ test_mdi_messages();
+ cleanup_tests();
+}
+
+START_TEST(msg_controls)
+{
+ init_tests();
+ test_button_messages();
+ test_static_messages();
+ test_listbox_messages();
+ test_combobox_messages();
+ test_edit_messages();
+ cleanup_tests();
+}
+
+START_TEST(msg_layered_window)
+{
+ init_tests();
+ test_layered_window();
+ cleanup_tests();
+}
+
+START_TEST(msg_dialog)
+{
+ init_tests();
+ test_dialog_messages();
+ test_EndDialog();
+ cleanup_tests();
+}
+
+START_TEST(msg_clipboard)
+{
+ init_tests();
+ test_clipboard_viewers();
+ cleanup_tests();
}