#define SPI_GETDESKWALLPAPER 0x0073
#endif
+#ifndef WM_SYSTIMER
+#define WM_SYSTIMER 0x0118
+#endif
+
#define LONG_PTR INT_PTR
#define ULONG_PTR UINT_PTR
static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*);
static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout );
static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout );
+static BOOL (WINAPI *pFlashWindow)( HWND hwnd, BOOL bInvert );
static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi );
static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
static DWORD (WINAPI *pGetLayout)(HDC hdc);
static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn);
static BOOL test_lbuttondown_flag;
+static DWORD num_gettext_msgs;
+static DWORD num_settext_msgs;
static HWND hwndMessage;
static HWND hwndMain, hwndMain2;
static HHOOK hhook;
+static BOOL app_activated, app_deactivated;
static const char* szAWRClass = "Winsize";
static HMENU hmenu;
}
}
+static BOOL wait_for_event(HANDLE event, int timeout)
+{
+ DWORD end_time = GetTickCount() + timeout;
+ MSG msg;
+
+ do {
+ if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
+ return TRUE;
+ while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ DispatchMessageA(&msg);
+ timeout = end_time - GetTickCount();
+ }while(timeout > 0);
+
+ return FALSE;
+}
+
/* check the values returned by the various parent/owner functions on a given window */
static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
HWND gw_owner, HWND ga_root, HWND ga_root_owner )
return (message >= 0xc000 ||
message == WM_GETICON ||
message == WM_GETOBJECT ||
+ message == WM_TIMER ||
+ message == WM_SYSTIMER ||
message == WM_TIMECHANGE ||
message == WM_DEVICECHANGE);
}
DestroyWindow( child );
DestroyWindow( test );
DestroyWindow( owner );
+
+ /* Test that owner window takes into account WS_CHILD flag even if parent is set by SetParent. */
+ owner = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, desktop );
+ SetParent(owner, hwndMain);
+ check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
+ test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
+ check_parents( test, desktop, owner, NULL, owner, test, test );
+ DestroyWindow( owner );
+ DestroyWindow( test );
+
+ owner = create_tool_window( WS_VISIBLE | WS_CHILD, desktop );
+ SetParent(owner, hwndMain);
+ check_parents( owner, hwndMain, hwndMain, hwndMain, NULL, hwndMain, hwndMain );
+ test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
+ check_parents( test, desktop, hwndMain, NULL, hwndMain, test, test );
+ DestroyWindow( owner );
+ DestroyWindow( test );
+
+ owner = create_tool_window( WS_VISIBLE | WS_POPUP | WS_CHILD, desktop );
+ SetParent(owner, hwndMain);
+ check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
+ test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
+ check_parents( test, desktop, owner, NULL, owner, test, test );
+ DestroyWindow( owner );
+ DestroyWindow( test );
}
static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam)
CloseHandle( handle );
}
+static struct wm_gettext_override_data
+{
+ BOOL enabled; /* when 1 bypasses default procedure */
+ char *buff; /* expected text buffer pointer */
+ WCHAR *buffW; /* same, for W test */
+} g_wm_gettext_override;
+
static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
case WM_GETMINMAXINFO:
{
- MINMAXINFO* minmax = (MINMAXINFO *)lparam;
-
- trace("WM_GETMINMAXINFO: hwnd %p, %08lx, %08lx\n", hwnd, wparam, lparam);
- dump_minmax_info( minmax );
SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
break;
}
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS *winpos = (WINDOWPOS *)lparam;
- trace("main: WM_WINDOWPOSCHANGING %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
- winpos->hwnd, winpos->hwndInsertAfter,
- winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
if (!(winpos->flags & SWP_NOMOVE))
{
ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
{
RECT rc1, rc2;
WINDOWPOS *winpos = (WINDOWPOS *)lparam;
- trace("main: WM_WINDOWPOSCHANGED %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
- winpos->hwnd, winpos->hwndInsertAfter,
- winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
- trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
- if (got_getminmaxinfo)
- trace("%p got WM_GETMINMAXINFO\n", hwnd);
-
if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
else
flush_events( FALSE );
}
break;
+ case WM_GETTEXT:
+ num_gettext_msgs++;
+ if (g_wm_gettext_override.enabled)
+ {
+ char *text = (char*)lparam;
+ ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text);
+ ok(*text == 0, "expected empty string buffer %x\n", *text);
+ return 0;
+ }
+ break;
+ case WM_SETTEXT:
+ num_settext_msgs++;
+ break;
+ case WM_ACTIVATEAPP:
+ if (wparam) app_activated = TRUE;
+ else app_deactivated = TRUE;
+ break;
+ }
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static LRESULT WINAPI main_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg)
+ {
+ case WM_GETTEXT:
+ num_gettext_msgs++;
+ if (g_wm_gettext_override.enabled)
+ {
+ WCHAR *text = (WCHAR*)lparam;
+ ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text);
+ ok(*text == 0, "expected empty string buffer %x\n", *text);
+ return 0;
+ }
+ break;
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
{
case WM_GETMINMAXINFO:
{
- MINMAXINFO* minmax = (MINMAXINFO *)lparam;
-
- trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
- dump_minmax_info( minmax );
SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
break;
}
BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
- trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
- if (got_getminmaxinfo)
- trace("%p got WM_GETMINMAXINFO\n", hwnd);
-
if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
else
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
+static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0};
+
static BOOL RegisterWindowClasses(void)
{
+ WNDCLASSW clsW;
WNDCLASSA cls;
cls.style = CS_DBLCLKS;
if(!RegisterClassA(&cls)) return FALSE;
+ clsW.style = CS_DBLCLKS;
+ clsW.lpfnWndProc = main_window_procW;
+ clsW.cbClsExtra = 0;
+ clsW.cbWndExtra = 0;
+ clsW.hInstance = GetModuleHandleA(0);
+ clsW.hIcon = 0;
+ clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+ clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
+ clsW.lpszMenuName = NULL;
+ clsW.lpszClassName = mainclassW;
+
+ if(!RegisterClassW(&clsW)) return FALSE;
+
cls.style = 0;
cls.lpfnWndProc = tool_window_procA;
cls.cbClsExtra = 0;
rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
}
+/* reimplement it to check that the Wine algorithm gives the correct result */
+static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle )
+{
+ int adjust;
+
+ if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
+ WS_EX_STATICEDGE)
+ {
+ adjust = 1; /* for the outer frame always present */
+ }
+ else
+ {
+ adjust = 0;
+ if ((exStyle & WS_EX_DLGMODALFRAME) ||
+ (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
+ }
+ if (style & WS_THICKFRAME)
+ adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */
+ if ((style & (WS_BORDER|WS_DLGFRAME)) ||
+ (exStyle & WS_EX_DLGMODALFRAME))
+ adjust++; /* The other border */
+
+ InflateRect (rect, adjust, adjust);
+
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ {
+ if (exStyle & WS_EX_TOOLWINDOW)
+ rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
+ else
+ rect->top -= GetSystemMetrics(SM_CYCAPTION);
+ }
+ if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
+
+ if (exStyle & WS_EX_CLIENTEDGE)
+ InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
+
+ if (style & WS_VSCROLL)
+ {
+ if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
+ rect->left -= GetSystemMetrics(SM_CXVSCROLL);
+ else
+ rect->right += GetSystemMetrics(SM_CXVSCROLL);
+ }
+ if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
+}
+
static void test_nonclient_area(HWND hwnd)
{
DWORD style, exstyle;
style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
rc.left, rc.top, rc.right, rc.bottom);
+ CopyRect(&rc, &rc_client);
+ MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
+ wine_AdjustWindowRectEx(&rc, style, menu, exstyle);
+ ok(EqualRect(&rc, &rc_window),
+ "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
+ style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
+ rc.left, rc.top, rc.right, rc.bottom);
+
CopyRect(&rc, &rc_window);
DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id)
{
MDICREATESTRUCTA mdi_cs;
- HWND mdi_child;
+ HWND mdi_child, hwnd, exp_hwnd;
INT_PTR id;
static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
{
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
{
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
{
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == first_id, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
+ ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
}
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == 0, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
DestroyWindow(mdi_child);
mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == 0, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
DestroyWindow(mdi_child);
/* maximized child */
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == 0, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
DestroyWindow(mdi_child);
trace("Creating maximized child with a caption\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == 0, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
DestroyWindow(mdi_child);
trace("Creating maximized child with a caption and a thick frame\n");
ok(mdi_child != 0, "MDI child creation failed\n");
id = GetWindowLongPtrA(mdi_child, GWLP_ID);
ok(id == 0, "wrong child id %ld\n", id);
+ hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
+ ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
DestroyWindow(mdi_child);
}
style = GetWindowLongA(hwnd, GWL_STYLE);
exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
- GetWindowRect(client, &rc);
- trace("MDI client %p window size = (%d x %d)\n", client, rc.right-rc.left, rc.bottom-rc.top);
GetClientRect(client, &rc);
- trace("MDI client %p client size = (%d x %d)\n", client, rc.right, rc.bottom);
- trace("screen size: %d x %d\n", GetSystemMetrics(SM_CXSCREEN),
- GetSystemMetrics(SM_CYSCREEN));
GetClientRect(client, &rc);
if ((style & WS_CAPTION) == WS_CAPTION)
switch (msg)
{
case WM_CREATE:
- {
- CLIENTCREATESTRUCT client_cs;
- RECT rc;
-
- GetClientRect(hwnd, &rc);
-
- client_cs.hWindowMenu = 0;
- client_cs.idFirstChild = 1;
-
- /* MDIClient without MDIS_ALLCHILDSTYLES */
- mdi_client = CreateWindowExA(0, "mdiclient",
- NULL,
- WS_CHILD /*| WS_VISIBLE*/,
- /* tests depend on a not zero MDIClient size */
- 0, 0, rc.right, rc.bottom,
- hwnd, 0, GetModuleHandleA(NULL),
- &client_cs);
- assert(mdi_client);
- test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
- DestroyWindow(mdi_client);
-
- /* MDIClient with MDIS_ALLCHILDSTYLES */
- mdi_client = CreateWindowExA(0, "mdiclient",
- NULL,
- WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
- /* tests depend on a not zero MDIClient size */
- 0, 0, rc.right, rc.bottom,
- hwnd, 0, GetModuleHandleA(NULL),
- &client_cs);
- assert(mdi_client);
- test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
- DestroyWindow(mdi_client);
-
- /* Test child window stack management */
- mdi_client = CreateWindowExA(0, "mdiclient",
- NULL,
- WS_CHILD,
- 0, 0, rc.right, rc.bottom,
- hwnd, 0, GetModuleHandleA(NULL),
- &client_cs);
- assert(mdi_client);
- test_MDI_child_stack(mdi_client);
- DestroyWindow(mdi_client);
- break;
- }
+ return 1;
case WM_WINDOWPOSCHANGED:
{
static void test_mdi(void)
{
- HWND mdi_hwndMain;
- /*MSG msg;*/
+ static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL };
+ HWND mdi_hwndMain, mdi_client;
+ CLIENTCREATESTRUCT client_cs;
+ RECT rc;
+ DWORD i;
+ MSG msg;
if (!mdi_RegisterWindowClasses()) assert(0);
GetDesktopWindow(), 0,
GetModuleHandleA(NULL), NULL);
assert(mdi_hwndMain);
+
+ GetClientRect(mdi_hwndMain, &rc);
+
+ client_cs.hWindowMenu = 0;
+ client_cs.idFirstChild = 1;
+
+ for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
+ {
+ HWND mdi_child;
+ SCROLLINFO si;
+ BOOL ret, gotit;
+
+ mdi_client = CreateWindowExA(0, "mdiclient", NULL,
+ WS_CHILD | style[i],
+ 0, 0, rc.right, rc.bottom,
+ mdi_hwndMain, 0, 0, &client_cs);
+ ok(mdi_client != 0, "MDI client creation failed\n");
+
+ mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
+ 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ mdi_client, 0, 0,
+ mdi_lParam_test_message);
+ ok(mdi_child != 0, "MDI child creation failed\n");
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
+ ok(si.nPage == 0, "expected 0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin == 0, "expected 0\n");
+ ok(si.nMax == 100, "expected 100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
+
+ ret = GetScrollInfo(mdi_client, SB_VERT, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
+ ok(si.nPage == 0, "expected 0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin == 0, "expected 0\n");
+ ok(si.nMax == 100, "expected 100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
+
+ SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
+ ok(si.nPage == 0, "expected 0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin == 0, "expected 0\n");
+ ok(si.nMax == 100, "expected 100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
+
+ ret = GetScrollInfo(mdi_client, SB_VERT, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
+ ok(si.nPage == 0, "expected 0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin == 0, "expected 0\n");
+ ok(si.nMax == 100, "expected 100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
+
+ gotit = FALSE;
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT)
+ {
+ DispatchMessageA(&msg);
+ continue;
+ }
+
+ if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */
+ {
+ ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n");
+ gotit = TRUE;
+ }
+ else
+ ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message);
+ DispatchMessageA(&msg);
+ }
+ ok(gotit, "message 0x003f should appear after SetWindowPos\n");
+
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_ALL;
+ ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
+todo_wine
+ ok(si.nPage != 0, "expected !0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin != 0, "expected !0\n");
+ ok(si.nMax != 100, "expected !100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
+
+ ret = GetScrollInfo(mdi_client, SB_VERT, &si);
+ if (style[i] & (WS_HSCROLL | WS_VSCROLL))
+ {
+ ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
+todo_wine
+ ok(si.nPage != 0, "expected !0\n");
+ ok(si.nPos == 0, "expected 0\n");
+ ok(si.nTrackPos == 0, "expected 0\n");
+ ok(si.nMin != 0, "expected !0\n");
+ ok(si.nMax != 100, "expected !100\n");
+ }
+ else
+ ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
+
+ DestroyWindow(mdi_child);
+ DestroyWindow(mdi_client);
+ }
+
+ /* MDIClient without MDIS_ALLCHILDSTYLES */
+ mdi_client = CreateWindowExA(0, "mdiclient",
+ NULL,
+ WS_CHILD /*| WS_VISIBLE*/,
+ /* tests depend on a not zero MDIClient size */
+ 0, 0, rc.right, rc.bottom,
+ mdi_hwndMain, 0, GetModuleHandleA(NULL),
+ &client_cs);
+ assert(mdi_client);
+ test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
+ DestroyWindow(mdi_client);
+
+ /* MDIClient with MDIS_ALLCHILDSTYLES */
+ mdi_client = CreateWindowExA(0, "mdiclient",
+ NULL,
+ WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
+ /* tests depend on a not zero MDIClient size */
+ 0, 0, rc.right, rc.bottom,
+ mdi_hwndMain, 0, GetModuleHandleA(NULL),
+ &client_cs);
+ assert(mdi_client);
+ test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
+ DestroyWindow(mdi_client);
+
+ /* Test child window stack management */
+ mdi_client = CreateWindowExA(0, "mdiclient",
+ NULL,
+ WS_CHILD,
+ 0, 0, rc.right, rc.bottom,
+ mdi_hwndMain, 0, GetModuleHandleA(NULL),
+ &client_cs);
+ assert(mdi_client);
+ test_MDI_child_stack(mdi_client);
+ DestroyWindow(mdi_client);
/*
while(GetMessage(&msg, 0, 0, 0))
{
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == 0, "wrong small icon %p/0\n", res );
- /* this test is XP specific */
- /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res != 0, "wrong small icon %p\n", res );*/
+ res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
ok( res == 0, "wrong previous small icon %p/0\n", res );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
- /* this test is XP specific */
- /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
+ res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
- /* this test is XP specific */
- /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
- ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
+ res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+ ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
/* make sure the big icon hasn't changed */
res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
}
cap_wnd = GetCapture();
+ ok(cap_wnd == (HWND)lParam, "capture window %p does not match lparam %lx\n", cap_wnd, lParam);
+ todo_wine ok(cap_wnd == hWnd, "capture window %p does not match hwnd %p\n", cap_wnd, hWnd);
+
/* check that re-setting the capture for the menu fails */
set_cap_wnd = SetCapture(cap_wnd);
ok(!set_cap_wnd || broken(set_cap_wnd == cap_wnd), /* nt4 */
do
{
ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
- } while (ret && (msg->message == WM_TIMER || ignore_message(msg->message)));
+ } while (ret && ignore_message(msg->message));
return ret;
}
/* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */
while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
{
- if (msg.message == WM_TIMER || ignore_message(msg.message)) continue;
+ if (ignore_message(msg.message)) continue;
ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE,
"hwnd %p message %04x\n", msg.hwnd, msg.message);
DispatchMessageA(&msg);
ok(bret, "SetForegroundWindow() failed\n");
check_active_state(popup, popup, popup);
+ ShowWindow(parent, SW_SHOW);
+ SetActiveWindow(popup);
+ ok(DestroyWindow(popup), "DestroyWindow() failed\n");
+ check_active_state(parent, parent, parent);
+
ok(DestroyWindow(parent), "DestroyWindow() failed\n");
ok(!IsWindow(parent), "parent still exists\n");
ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE),
"Ex style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
- (lpss->styleOld & ~WS_EX_WINDOWEDGE), (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE));
+ lpss->styleOld, lpcs->dwExStyle);
ok(lpss->styleNew == lpcs->style,
"Style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
/* FIXME: Remove the condition below once Wine is fixed */
- if (dwActualExStyle != dwExStyleOut)
- todo_wine ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
- else
- ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
+ todo_wine_if (dwActualExStyle != dwExStyleOut)
+ ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
DestroyWindow(hwnd);
if (hwndParent) DestroyWindow(hwndParent);
return 0;
}
+static INT_PTR WINAPI empty_dlg_proc3(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG)
+ EndDialog(hwnd, 0);
+
+ return 0;
+}
+
+struct dialog_param
+{
+ HWND parent, grand_parent;
+ DLGTEMPLATE *dlg_data;
+};
+
+static INT_PTR WINAPI empty_dlg_proc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG)
+ {
+ DWORD style = GetWindowLongA(hwnd, GWL_STYLE);
+ struct dialog_param *param = (struct dialog_param *)lparam;
+ BOOL parent_is_child;
+ HWND disabled_hwnd;
+
+ parent_is_child = (GetWindowLongA(param->parent, GWL_STYLE) & (WS_POPUP | WS_CHILD)) == WS_CHILD;
+
+ ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
+ if (parent_is_child)
+ {
+ ok(IsWindowEnabled(param->parent), "wrong state for %08x\n", style);
+ disabled_hwnd = param->grand_parent;
+ }
+ else
+ {
+ ok(!IsWindowEnabled(param->parent), "wrong state for %08x\n", style);
+ disabled_hwnd = param->parent;
+ }
+
+ if (param->grand_parent)
+ {
+ if (parent_is_child)
+ ok(!IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style);
+ else
+ ok(IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style);
+ }
+
+ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, disabled_hwnd, empty_dlg_proc3, 0);
+ ok(IsWindowEnabled(disabled_hwnd), "wrong state for %08x\n", style);
+
+ ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
+ ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent);
+ if (param->grand_parent)
+ ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style);
+
+ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
+ ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd);
+ ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent);
+ if (param->grand_parent)
+ ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style);
+
+ param->dlg_data->style |= WS_CHILD;
+ DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0);
+ ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style);
+
+ EndDialog(hwnd, 0);
+ }
+ return 0;
+}
+
static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_out, DWORD ex_style_out)
{
struct
WCHAR caption[1];
} dlg_data;
DWORD style, ex_style;
- HWND hwnd, parent = 0;
+ HWND hwnd, grand_parent = 0, parent = 0;
+ struct dialog_param param;
if (style_in & WS_CHILD)
- parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
+ {
+ grand_parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ ok(grand_parent != 0, "grand_parent creation failed\n");
+ }
+
+ parent = CreateWindowExA(0, "static", NULL, style_in,
+ 0, 0, 0, 0, grand_parent, NULL, NULL, NULL);
+ ok(parent != 0, "parent creation failed, style %#x\n", style_in);
dlg_data.dt.style = style_in;
dlg_data.dt.dwExtendedStyle = ex_style_in;
style = GetWindowLongA(hwnd, GWL_STYLE);
ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
- ok(style == (style_out | DS_3DLOOK), "expected style %#x, got %#x\n", style_out | DS_3DLOOK, style);
+ ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
+ ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in);
+
/* try setting the styles explicitly */
SetWindowLongA(hwnd, GWL_EXSTYLE, ex_style_in);
style = GetWindowLongA(hwnd, GWL_STYLE);
ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
- ok(style == (style_out | DS_3DLOOK), "expected style %#x, got %#x\n", style_out|DS_3DLOOK, style);
+ ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
/* WS_EX_WINDOWEDGE can't always be changed */
if (ex_style_in & WS_EX_DLGMODALFRAME)
ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
else
ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE;
/* FIXME: Remove the condition below once Wine is fixed */
- if (ex_style != ex_style_out)
- todo_wine ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
- else
- ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
+ todo_wine_if (ex_style != ex_style_out)
+ ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
DestroyWindow(hwnd);
+
+ param.parent = parent;
+ param.grand_parent = grand_parent;
+ param.dlg_data = &dlg_data.dt;
+ DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc2, (LPARAM)¶m);
+
+ ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in);
+ if (grand_parent)
+ ok(IsWindowEnabled(grand_parent), "wrong grand parent state (dialog style %#x)\n", style_in);
+
DestroyWindow(parent);
+ DestroyWindow(grand_parent);
}
static void test_dialog_styles(void)
}
}
+struct dlg_parent_param
+{
+ HWND ga_parent;
+ HWND gwl_parent;
+ HWND get_parent;
+ HWND owner;
+ HWND root;
+ HWND ga_root_owner;
+};
+
+static INT_PTR WINAPI parent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG) {
+ struct dlg_parent_param *param = (void*)lparam;
+ check_parents(hwnd, param->ga_parent, param->gwl_parent, param->get_parent, param->owner,
+ param->root ? param->root : hwnd, param->ga_root_owner ? param->ga_root_owner : hwnd);
+
+ ok(!IsWindowEnabled(param->gwl_parent), "parent is not disabled\n");
+ EndDialog(hwnd, 2);
+ ok(IsWindowEnabled(param->gwl_parent), "parent is not enabled\n");
+ }
+
+ return 0;
+}
+
+static INT_PTR WINAPI reparent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG) {
+ ok(!IsWindowEnabled(GetParent(hwnd)), "parent is not disabled\n");
+ SetParent(hwnd, (HWND)lparam);
+ }
+
+ return 0;
+}
+
+static INT_PTR WINAPI reparent_owned_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_INITDIALOG) {
+ HWND new_parent = (HWND)lparam;
+ HWND owner = GetWindow(hwnd, GW_OWNER);
+ ok(!IsWindowEnabled(owner), "owner is not disabled\n");
+ SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | WS_CHILD);
+ SetParent(hwnd, new_parent);
+ ok(GetParent(hwnd) == new_parent, "GetParent(hwnd) = %p, expected %p\n", GetParent(hwnd), new_parent);
+ PostMessageA(hwnd, WM_QUIT, 0, 0);
+ }
+
+ return 0;
+}
+
+static LRESULT WINAPI reparent_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_ENTERIDLE) {
+ HWND dialog = (HWND)lparam;
+ HWND owner = GetParent(dialog);
+ /* EndDialog will enable owner */
+ EnableWindow(owner, FALSE);
+ EndDialog(dialog, 2);
+ ok(IsWindowEnabled(owner), "owner is not enabled\n");
+ /* ...but it won't be enabled on dialog exit */
+ EnableWindow(owner, FALSE);
+ }
+ return DefWindowProcA( hwnd, msg, wparam, lparam );
+}
+
+static LRESULT WINAPI post_quit_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_ENTERIDLE) {
+ HWND dialog = (HWND)lparam;
+ PostMessageA(dialog, WM_QUIT, 0, 0);
+ }
+ return DefWindowProcA( hwnd, msg, wparam, lparam );
+}
+
+static LRESULT WINAPI destroy_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if (msg == WM_ENTERIDLE) {
+ HWND dialog = (HWND)lparam;
+ DestroyWindow(dialog);
+ }
+ return DefWindowProcA( hwnd, msg, wparam, lparam );
+}
+
+static void test_dialog_parent(void)
+{
+ HWND dialog, parent, child, child2, other, desktop = GetDesktopWindow();
+ struct dlg_parent_param param;
+ INT_PTR ret;
+ struct
+ {
+ DLGTEMPLATE dt;
+ WORD menu_name;
+ WORD class_id;
+ WORD class_atom;
+ WCHAR caption[1];
+ } dlg_data;
+
+ dlg_data.dt.dwExtendedStyle = 0;
+ dlg_data.dt.cdit = 0;
+ dlg_data.dt.x = 0;
+ dlg_data.dt.y = 0;
+ dlg_data.dt.cx = 100;
+ dlg_data.dt.cy = 100;
+ dlg_data.menu_name = 0;
+ dlg_data.class_id = 0;
+ dlg_data.class_atom = 0;
+ dlg_data.caption[0] = 0;
+
+ parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ /* Create a child without WS_CHILD flag. It's a valid owner window. */
+ child = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ SetParent(child, parent);
+ /* Regular child. If passed as an owner, its parent will be true owner window. */
+ child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, NULL, NULL, NULL);
+
+ trace("parent %p child %p child2 %p desktop %p\n", parent, child, child2, desktop);
+
+ /* When dialog is created with WS_CHILD style, its parent depends on function used to create it. */
+ dlg_data.dt.style = WS_CHILD;
+
+ /* CreateDialogIndirectParam uses passed parent as dialog parent. */
+ dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
+ ok(dialog != 0, "dialog creation failed\n");
+ check_parents(dialog, child2, child2, child2, NULL, parent, child);
+
+ ok(IsWindowEnabled(child2), "child2 is disabled\n");
+ EnableWindow(child2, FALSE);
+ EndDialog(dialog, 0);
+ ok(IsWindowEnabled(child2), "child2 is not enabled\n");
+ DestroyWindow(dialog);
+
+ /* DialogBoxIndirectParam uses the first parent of passed owner that's not a child window as dialog
+ * parent (like in case of dialog with owner). */
+ param.ga_parent = param.gwl_parent = param.get_parent = child;
+ param.owner = NULL;
+ param.root = parent;
+ param.ga_root_owner = child;
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m);
+ ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
+
+ /* Dialogs without WS_CHILD behave as expected, they use passed owner just like CreateWindow does. */
+ dlg_data.dt.style = WS_OVERLAPPEDWINDOW;
+
+ dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
+ ok(dialog != 0, "dialog creation failed\n");
+ check_parents(dialog, desktop, child, NULL, child, dialog, dialog);
+
+ ok(IsWindowEnabled(child), "child is disabled\n");
+ EnableWindow(child, FALSE);
+ EndDialog(dialog, 0);
+ ok(IsWindowEnabled(child), "child is not enabled\n");
+ DestroyWindow(dialog);
+
+ param.ga_parent = desktop;
+ param.gwl_parent = child;
+ param.get_parent = NULL;
+ param.owner = child;
+ param.root = param.ga_root_owner = NULL;
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m);
+ ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
+
+ other = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
+ SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)reparent_dialog_owner_proc);
+
+ /* When dialog is created with WS_CHILD|WS_POPUP style, we have an owner. */
+ dlg_data.dt.style = WS_CHILD|WS_POPUP;
+
+ dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0);
+ ok(dialog != 0, "dialog creation failed\n");
+ check_parents(dialog, desktop, child, child, child, dialog, child);
+
+ ok(IsWindowEnabled(child), "child is disabled\n");
+ EnableWindow(child, FALSE);
+ EndDialog(dialog, 0);
+ ok(IsWindowEnabled(child), "child is not enabled\n");
+ DestroyWindow(dialog);
+
+ param.ga_parent = desktop;
+ param.gwl_parent = param.get_parent = child;
+ param.owner = child;
+ param.root = NULL;
+ param.ga_root_owner = child;
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m);
+ ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
+
+ /* If we change parent in WM_INITDIALOG for WS_CHILD dialog WM_ENTERIDLE is still sent to the original
+ * parent. EndDialog will enable the new parent. */
+ EnableWindow(child, TRUE);
+ EnableWindow(other, FALSE);
+ dlg_data.dt.style = WS_CHILD;
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_dlg_proc, (LPARAM)other);
+ ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret);
+ ok(!IsWindowEnabled(other), "other is not disabled\n");
+ ok(!IsWindowEnabled(child), "child is not disabled\n");
+ ok(IsWindowEnabled(child2), "child2 is not enabled\n");
+ EnableWindow(child, TRUE);
+
+ /* If we change parent and style in WM_INITDIALOG for dialog with an owner to make it true child
+ * (thus GetParent() will return the new parent instead of an owner), WM_ENTERIDLE is still sent
+ * to the original parent. EndDialog will enable the new parent. */
+ EnableWindow(other, FALSE);
+ dlg_data.dt.style = WS_OVERLAPPED;
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_owned_dlg_proc, (LPARAM)other);
+ ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
+ ok(!IsWindowEnabled(other), "other is not disabled\n");
+ ok(!IsWindowEnabled(child), "child is not disabled\n");
+ ok(IsWindowEnabled(child2), "child2 is not enabled\n");
+ EnableWindow(child, TRUE);
+ EnableWindow(other, TRUE);
+
+ /* Quit dialog message loop by sending WM_QUIT message. Dialog owner is not enabled. */
+ SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)post_quit_dialog_owner_proc);
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0);
+ ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
+ ok(!IsWindowEnabled(other), "other is enabled\n");
+ EnableWindow(other, TRUE);
+
+ /* Quit dialog message loop by destroying the window. Dialog owner is not enabled. */
+ SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)destroy_dialog_owner_proc);
+ ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0);
+ ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret);
+ ok(!IsWindowEnabled(other), "other is enabled\n");
+ EnableWindow(other, TRUE);
+
+ DestroyWindow(parent);
+}
+
static void test_scrollwindow( HWND hwnd)
{
HDC hdc;
rcu.left,rcu.top,rcu.right,rcu.bottom);
ReleaseDC( hwnd1, hdc);
- /* test scrolling a window with an update region */
+ /* test scrolling a rect by more than its size */
DestroyWindow( hwnd2);
ValidateRect( hwnd1, NULL);
SetRect( &rc, 40,40, 50,50);
InvalidateRect( hwnd1, &rc, 1);
+ ScrollWindowEx( hwnd1, -20, 0, &rc, NULL, hrgn, &rcu,
+ SW_SCROLLCHILDREN | SW_INVALIDATE);
+ if (winetest_debug > 0) dump_region(hrgn);
+ SetRectRgn( exprgn, 20, 40, 30, 50);
+ SetRectRgn( tmprgn, 40, 40, 50, 50);
+ CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
+ ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
+ ok( rcu.left == 20 && rcu.top == 40 && rcu.right == 50 && rcu.bottom == 50,
+ "unexpected update rect: %d,%d - %d,%d\n", rcu.left,rcu.top,rcu.right,rcu.bottom);
+
+ /* test scrolling a window with an update region */
+ ValidateRect( hwnd1, NULL);
+ SetRect( &rc, 40,40, 50,50);
+ InvalidateRect( hwnd1, &rc, 1);
GetClientRect( hwnd1, &rc);
cliprc=rc;
ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
static void test_AWR_window_size(BOOL menu)
{
- LONG styles[] = {
- WS_POPUP,
- WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME,
- WS_SYSMENU,
- WS_THICKFRAME,
- WS_MINIMIZEBOX, WS_MAXIMIZEBOX,
- WS_HSCROLL, WS_VSCROLL
+ static const DWORD styles[] = {
+ WS_POPUP, WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, WS_CAPTION, WS_SYSMENU,
+ WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_HSCROLL, WS_VSCROLL
};
- LONG exStyles[] = {
- WS_EX_CLIENTEDGE,
- WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
- WS_EX_APPWINDOW,
-#if 0
- /* These styles have problems on (at least) WinXP (SP2) and Wine */
- WS_EX_DLGMODALFRAME,
- WS_EX_STATICEDGE,
-#endif
+ static const DWORD exStyles[] = {
+ WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE, WS_EX_APPWINDOW,
+ WS_EX_DLGMODALFRAME, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
};
- int i;
+ unsigned int i;
/* A exhaustive check of all the styles takes too long
* so just do a (hopefully representative) sample
test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
}
}
+
+static void test_AWR_flags(void)
+{
+ static const DWORD styles[] = { WS_POPUP, WS_BORDER, WS_DLGFRAME, WS_THICKFRAME };
+ static const DWORD exStyles[] = { WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
+ WS_EX_APPWINDOW, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE };
+
+ DWORD i, j, k, style, exstyle;
+ RECT rect, rect2;
+
+ for (i = 0; i < (1 << COUNTOF(styles)); i++)
+ {
+ for (k = style = 0; k < COUNTOF(styles); k++) if (i & (1 << k)) style |= styles[k];
+
+ for (j = 0; j < (1 << COUNTOF(exStyles)); j++)
+ {
+ for (k = exstyle = 0; k < COUNTOF(exStyles); k++) if (j & (1 << k)) exstyle |= exStyles[k];
+ SetRect( &rect, 100, 100, 200, 200 );
+ rect2 = rect;
+ AdjustWindowRectEx( &rect, style, FALSE, exstyle );
+ wine_AdjustWindowRectEx( &rect2, style, FALSE, exstyle );
+ ok( EqualRect( &rect, &rect2 ), "rects do not match: win %d,%d-%d,%d wine %d,%d-%d,%d\n",
+ rect.left, rect.top, rect.right, rect.bottom,
+ rect2.left, rect2.top, rect2.right, rect2.bottom );
+ }
+ }
+}
#undef COUNTOF
#define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
test_AWR_window_size(FALSE);
test_AWR_window_size(TRUE);
+ test_AWR_flags();
DestroyMenu(hmenu);
}
t.w.r.f, got.w.r.f)
#define parentdc_todo_field_ok(t, w, r, f, got) \
- if (t.w##_todo.r.f) todo_wine { parentdc_field_ok(t, w, r, f, got); } \
- else parentdc_field_ok(t, w, r, f, got)
+ todo_wine_if (t.w##_todo.r.f) \
+ parentdc_field_ok(t, w, r, f, got);
#define parentdc_rect_ok(t, w, r, got) \
parentdc_todo_field_ok(t, w, r, left, got); \
WNDCLASSA classA;
WNDCLASSW classW;
HWND hwnd;
+ ATOM atom;
memset(&classW, 0, sizeof(classW));
classW.hInstance = GetModuleHandleA(0);
classA.hInstance = GetModuleHandleA(0);
classA.lpfnWndProc = def_window_procA;
classA.lpszClassName = ansi_class_nameA;
- assert(RegisterClassA(&classA));
+ atom = RegisterClassA(&classA);
+ assert(atom);
/* unicode class: window proc */
hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
DestroyWindow(hwnd);
expected_cx = expected_cy = -10;
- SetRect( &expected_rect, 0, 0, 0, 0 );
+ SetRectEmpty(&expected_rect);
SetRect( &broken_rect, 0, 0, -10, -10 );
hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL);
ok( hwnd != 0, "creation failed err %u\n", GetLastError());
DestroyWindow(hwnd);
expected_cx = expected_cy = -200000;
- SetRect( &expected_rect, 0, 0, 0, 0 );
+ SetRectEmpty(&expected_rect);
SetRect( &broken_rect, 0, 0, -200000, -200000 );
hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL);
ok( hwnd != 0, "creation failed err %u\n", GetLastError());
ok(!IsWindow(hwnd), "window should not exist\n");
}
-static void test_gettext(void)
+static DWORD CALLBACK gettext_msg_thread( LPVOID arg )
{
- WNDCLASSA cls;
- LPCSTR clsname = "gettexttest";
- HWND hwnd;
+ HWND hwnd = arg;
+ char buf[32];
+ INT buf_len;
+
+ /* test GetWindowTextA */
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ return 0;
+}
+
+static DWORD CALLBACK settext_msg_thread( LPVOID arg )
+{
+ HWND hwnd = arg;
+ BOOL success;
+
+ /* test SetWindowTextA */
+ num_settext_msgs = 0;
+ success = SetWindowTextA( hwnd, "thread_caption" );
+ ok( success, "SetWindowTextA failed\n" );
+ ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
+
+ return 0;
+}
+
+static void test_gettext(void)
+{
+ DWORD tid, num_msgs;
+ WCHAR bufW[32];
+ HANDLE thread;
+ BOOL success;
+ char buf[32];
+ INT buf_len;
+ HWND hwnd, hwnd2;
LRESULT r;
+ MSG msg;
- memset( &cls, 0, sizeof cls );
- cls.lpfnWndProc = DefWindowProcA;
- cls.lpszClassName = clsname;
- cls.hInstance = GetModuleHandleA(NULL);
+ hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
+ ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
- if (!RegisterClassA( &cls )) return;
+ /* test GetWindowTextA */
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ /* other process window */
+ strcpy( buf, "a" );
+ buf_len = GetWindowTextA( GetDesktopWindow(), buf, sizeof(buf) );
+ ok( buf_len == 0, "expected a nonempty window text\n" );
+ ok( *buf == 0, "got wrong window text '%s'\n", buf );
+
+ strcpy( buf, "blah" );
+ buf_len = GetWindowTextA( GetDesktopWindow(), buf, 0 );
+ ok( buf_len == 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "blah"), "got wrong window text '%s'\n", buf );
+
+ bufW[0] = 0xcc;
+ buf_len = GetWindowTextW( GetDesktopWindow(), bufW, 0 );
+ ok( buf_len == 0, "expected a nonempty window text\n" );
+ ok( bufW[0] == 0xcc, "got %x\n", bufW[0] );
+
+ g_wm_gettext_override.enabled = TRUE;
+
+ num_gettext_msgs = 0;
+ memset( buf, 0xcc, sizeof(buf) );
+ g_wm_gettext_override.buff = buf;
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len == 0, "got %d\n", buf_len );
+ ok( *buf == 0, "got %x\n", *buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ num_gettext_msgs = 0;
+ strcpy( buf, "blah" );
+ g_wm_gettext_override.buff = buf;
+ buf_len = GetWindowTextA( hwnd, buf, 0 );
+ ok( buf_len == 0, "got %d\n", buf_len );
+ ok( !strcmp(buf, "blah"), "got %s\n", buf );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ g_wm_gettext_override.enabled = FALSE;
+
+ /* same for W window */
+ hwnd2 = CreateWindowExW( 0, mainclassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
+ ok( hwnd2 != 0, "CreateWindowExA error %d\n", GetLastError() );
+
+ g_wm_gettext_override.enabled = TRUE;
+
+ num_gettext_msgs = 0;
+ memset( bufW, 0xcc, sizeof(bufW) );
+ g_wm_gettext_override.buffW = bufW;
+ buf_len = GetWindowTextW( hwnd2, bufW, sizeof(bufW)/sizeof(WCHAR) );
+ ok( buf_len == 0, "got %d\n", buf_len );
+ ok( *bufW == 0, "got %x\n", *bufW );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ num_gettext_msgs = 0;
+ memset( bufW, 0xcc, sizeof(bufW) );
+ g_wm_gettext_override.buffW = bufW;
+ buf_len = GetWindowTextW( hwnd2, bufW, 0 );
+ ok( buf_len == 0, "got %d\n", buf_len );
+ ok( *bufW == 0xcccc, "got %x\n", *bufW );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ g_wm_gettext_override.enabled = FALSE;
+
+ DestroyWindow( hwnd2 );
+
+ /* test WM_GETTEXT */
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ r = SendMessageA( hwnd, WM_GETTEXT, sizeof(buf), (LONG_PTR)buf );
+ ok( r != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ /* test SetWindowTextA */
+ num_settext_msgs = 0;
+ success = SetWindowTextA( hwnd, "new_caption" );
+ ok( success, "SetWindowTextA failed\n" );
+ ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
+
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "new_caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ /* test WM_SETTEXT */
+ num_settext_msgs = 0;
+ r = SendMessageA( hwnd, WM_SETTEXT, 0, (ULONG_PTR)"another_caption" );
+ ok( r != 0, "WM_SETTEXT failed\n" );
+ ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
+
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
+ DispatchMessageA( &msg );
+
+ /* test interthread GetWindowTextA */
+ num_msgs = 0;
+ thread = CreateThread( NULL, 0, gettext_msg_thread, hwnd, 0, &tid );
+ ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
+ while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
+ {
+ while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
+ DispatchMessageA( &msg );
+ num_msgs++;
+ }
+ CloseHandle( thread );
+ ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
+
+ /* test interthread SetWindowText */
+ num_msgs = 0;
+ thread = CreateThread( NULL, 0, settext_msg_thread, hwnd, 0, &tid );
+ ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
+ while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
+ {
+ while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
+ DispatchMessageA( &msg );
+ num_msgs++;
+ }
+ CloseHandle( thread );
+ ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
- hwnd = CreateWindowA( clsname, "test text", WS_OVERLAPPED, 0, 0, 10, 10, 0, NULL, NULL, NULL);
- ok( hwnd != NULL, "window was null\n");
+ num_gettext_msgs = 0;
+ memset( buf, 0, sizeof(buf) );
+ buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
+ ok( buf_len != 0, "expected a nonempty window text\n" );
+ ok( !strcmp(buf, "thread_caption"), "got wrong window text '%s'\n", buf );
+ ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+ /* seems to crash on every modern Windows version */
+ if (0)
+ {
r = SendMessageA( hwnd, WM_GETTEXT, 0x10, 0x1000);
ok( r == 0, "settext should return zero\n");
r = SendMessageA( hwnd, WM_GETTEXT, 0x1000, 0xff000000);
ok( r == 0, "settext should return zero (%ld)\n", r);
+ }
DestroyWindow(hwnd);
- UnregisterClassA( clsname, NULL );
}
flush_events( TRUE );
ShowWindow(hchild, SW_HIDE);
- SetRect(&rc2, 0, 0, 0, 0);
+ SetRectEmpty(&rc2);
ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
ok(!ret, "GetUpdateRect returned not empty region\n");
ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
ShowWindow(hchild, SW_HIDE);
- SetRect(&rc2, 0, 0, 0, 0);
+ SetRectEmpty(&rc2);
ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
ok(!ret, "GetUpdateRect returned not empty region\n");
ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
DispatchMessageA(&msg);
MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT);
}
- if (flags == (RDW_INVALIDATE | RDW_FRAME))
- todo_wine ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
- else
+ todo_wine_if (flags == (RDW_INVALIDATE | RDW_FRAME))
ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
DestroyWindow(hwnd);
}
ret = pUpdateLayeredWindowIndirect( hwnd, &info );
ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
sz.cx--;
+ SetLastError(0);
ret = pUpdateLayeredWindowIndirect( hwnd, &info );
ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
- ok( GetLastError() == ERROR_INCORRECT_SIZE || broken(GetLastError() == ERROR_MR_MID_NOT_FOUND),
- "wrong error %u\n", GetLastError() );
+ /* particular error code differs from version to version, could be ERROR_INCORRECT_SIZE,
+ ERROR_MR_MID_NOT_FOUND or ERROR_GEN_FAILURE (Win8/Win10) */
+ ok( GetLastError() != 0, "wrong error %u\n", GetLastError() );
info.dwFlags = ULW_OPAQUE;
ret = pUpdateLayeredWindowIndirect( hwnd, &info );
ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
case WM_NCCREATE:
{
CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
- trace("WM_NCCREATE: rect %d,%d-%d,%d\n", cs->x, cs->y, cs->cx, cs->cy);
ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top &&
cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom,
"expected %d,%d-%d,%d, got %d,%d-%d,%d\n",
case WM_GETMINMAXINFO:
{
MINMAXINFO *minmax = (MINMAXINFO *)lp;
- dump_minmax_info(minmax);
ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left);
ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top);
ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right);
/* Windows makes a maximized window slightly larger (to hide the borders?) */
fixup = min(abs(rc.left), abs(rc.top));
InflateRect(&rc, -fixup, -fixup);
- ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
- rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
+ ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
+ rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
"%#x/%#x: window rect %d,%d-%d,%d must be in %d,%d-%d,%d\n",
ex_style, style, rc.left, rc.top, rc.right, rc.bottom,
- mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom);
+ mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom);
DestroyWindow(hwnd);
style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX;
rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
"%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
else
- ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
- rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
+ ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
+ rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
"%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
DestroyWindow(hwnd);
}
ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
- r.left = r.top = r.right = r.bottom = 0;
+ SetRectEmpty(&r);
ret = pGetWindowRgnBox(hwnd, &r);
ok( ret == SIMPLEREGION, "Expected SIMPLEREGION, got %d\n", ret);
ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15,
hrgn = CreateRectRgn(2, 3, 10, 15);
ret = pMirrorRgn( hwnd, hrgn );
ok( ret == TRUE, "MirrorRgn failed %u\n", ret );
- r.left = r.top = r.right = r.bottom = 0;
+ SetRectEmpty(&r);
GetWindowRect( hwnd, &r );
width = r.right - r.left;
- r.left = r.top = r.right = r.bottom = 0;
+ SetRectEmpty(&r);
ret = GetRgnBox( hrgn, &r );
ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret );
ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15,
DestroyWindow( parent );
}
+static void test_FlashWindow(void)
+{
+ HWND hwnd;
+ BOOL ret;
+ if (!pFlashWindow)
+ {
+ win_skip( "FlashWindow not supported\n" );
+ return;
+ }
+
+ hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP,
+ 0, 0, 0, 0, 0, 0, 0, NULL );
+ ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
+
+ SetLastError( 0xdeadbeef );
+ ret = pFlashWindow( NULL, TRUE );
+ ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "FlashWindow returned with %d\n", GetLastError() );
+
+ DestroyWindow( hwnd );
+
+ SetLastError( 0xdeadbeef );
+ ret = pFlashWindow( hwnd, TRUE );
+ ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "FlashWindow returned with %d\n", GetLastError() );
+}
+
static void test_FlashWindowEx(void)
{
HWND hwnd;
finfo.hwnd = NULL;
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(&finfo);
- todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
- "FlashWindowEx returned with %d\n", GetLastError());
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ "FlashWindowEx returned with %d\n", GetLastError());
finfo.hwnd = hwnd;
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(NULL);
- todo_wine ok(!ret && GetLastError() == ERROR_NOACCESS,
+ ok(!ret && GetLastError() == ERROR_NOACCESS,
"FlashWindowEx returned with %d\n", GetLastError());
SetLastError(0xdeadbeef);
finfo.cbSize = sizeof(FLASHWINFO) - 1;
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(&finfo);
- todo_wine ok(!ret && GetLastError()==ERROR_INVALID_PARAMETER,
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
"FlashWindowEx succeeded\n");
finfo.cbSize = sizeof(FLASHWINFO) + 1;
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(&finfo);
- todo_wine ok(!ret && GetLastError()==ERROR_INVALID_PARAMETER,
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
"FlashWindowEx succeeded\n");
finfo.cbSize = sizeof(FLASHWINFO);
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(&finfo);
- todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
+ ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
"FlashWindowEx returned with %d\n", GetLastError());
ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize);
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(NULL);
- todo_wine ok(!ret && GetLastError() == ERROR_NOACCESS,
+ ok(!ret && GetLastError() == ERROR_NOACCESS,
"FlashWindowEx returned with %d\n", GetLastError());
SetLastError(0xdeadbeef);
finfo.dwFlags = FLASHW_STOP;
SetLastError(0xdeadbeef);
ret = pFlashWindowEx(&finfo);
-todo_wine
ok(prev != ret, "previous window state should be different\n");
DestroyWindow( hwnd );
static void test_FindWindowEx(void)
{
HWND hwnd, found;
- CHAR title[1];
hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
- title[0] = 0;
-
- found = FindWindowExA( 0, 0, "MainWindowClass", title );
+ num_gettext_msgs = 0;
+ found = FindWindowExA( 0, 0, "MainWindowClass", "" );
ok( found == NULL, "expected a NULL hwnd\n" );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ num_gettext_msgs = 0;
found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ num_gettext_msgs = 0;
+ found = FindWindowExA( 0, 0, "MainWindowClass", "caption" );
+ ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
DestroyWindow( hwnd );
hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
- found = FindWindowExA( 0, 0, "MainWindowClass", title );
+ num_gettext_msgs = 0;
+ found = FindWindowExA( 0, 0, "MainWindowClass", "" );
ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
+
+ num_gettext_msgs = 0;
found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
+ ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
DestroyWindow( hwnd );
/* test behaviour with a window title that is an empty character */
- found = FindWindowExA( 0, 0, "Shell_TrayWnd", title );
+ found = FindWindowExA( 0, 0, "Shell_TrayWnd", "" );
ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL );
ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
ok(hwnd != 0, "RealChildWindowFromPoint failed\n");
ret = window_to_index(hwnd, window, sizeof(window)/sizeof(window[0]));
/* FIXME: remove once Wine is fixed */
- if (ret != real_child_pos[i])
- todo_wine ok(ret == real_child_pos[i] || broken(ret == real_child_pos_nt4[i]), "expected %d, got %d\n", real_child_pos[i], ret);
- else
+ todo_wine_if (ret != real_child_pos[i])
ok(ret == real_child_pos[i] || broken(ret == real_child_pos_nt4[i]), "expected %d, got %d\n", real_child_pos[i], ret);
get_window_attributes(hwnd, &attrs);
ok(ret, "UnregisterClass(my_window) failed\n");
}
+static void simulate_click(int x, int y)
+{
+ INPUT input[2];
+ UINT events_no;
+
+ SetCursorPos(x, y);
+ memset(input, 0, sizeof(input));
+ input[0].type = INPUT_MOUSE;
+ U(input[0]).mi.dx = x;
+ U(input[0]).mi.dy = y;
+ U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
+ input[1].type = INPUT_MOUSE;
+ U(input[1]).mi.dx = x;
+ U(input[1]).mi.dy = y;
+ U(input[1]).mi.dwFlags = MOUSEEVENTF_LEFTUP;
+ events_no = SendInput(2, input, sizeof(input[0]));
+ ok(events_no == 2, "SendInput returned %d\n", events_no);
+}
+
+static WNDPROC def_static_proc;
+static BOOL got_hittest;
+static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+ if(msg == WM_NCHITTEST)
+ got_hittest = TRUE;
+ if(msg == WM_LBUTTONDOWN)
+ ok(0, "unexpected call\n");
+
+ return def_static_proc(hwnd, msg, wp, lp);
+}
+
+static void window_from_point_proc(HWND parent)
+{
+ HANDLE start_event, end_event;
+ HANDLE win, child_static, child_button;
+ BOOL got_click;
+ DWORD ret;
+ POINT pt;
+ MSG msg;
+
+ start_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_start");
+ ok(start_event != 0, "OpenEvent failed\n");
+ end_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_end");
+ ok(end_event != 0, "OpenEvent failed\n");
+
+ child_static = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, parent, 0, NULL, NULL);
+ ok(child_static != 0, "CreateWindowEx failed\n");
+ pt.x = pt.y = 150;
+ win = WindowFromPoint(pt);
+ ok(win == parent, "WindowFromPoint returned %p, expected %p\n", win, parent);
+
+ child_button = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
+ 100, 0, 100, 100, parent, 0, NULL, NULL);
+ ok(child_button != 0, "CreateWindowEx failed\n");
+ pt.x = 250;
+ win = WindowFromPoint(pt);
+ ok(win == child_button, "WindowFromPoint returned %p, expected %p\n", win, child_button);
+
+ /* without this window simulate click test keeps sending WM_NCHITTEST
+ * message to child_static in an infinite loop */
+ win = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, parent, 0, NULL, NULL);
+ ok(win != 0, "CreateWindowEx failed\n");
+ def_static_proc = (void*)SetWindowLongPtrA(child_static,
+ GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
+ flush_events(TRUE);
+ SetEvent(start_event);
+
+ got_hittest = FALSE;
+ got_click = FALSE;
+ while(!got_click && wait_for_message(&msg)) {
+ if(msg.message == WM_LBUTTONUP) {
+ ok(msg.hwnd == win, "msg.hwnd = %p, expected %p\n", msg.hwnd, win);
+ got_click = TRUE;
+ }
+ DispatchMessageA(&msg);
+ }
+ ok(got_hittest, "transparent window didn't get WM_NCHITTEST message\n");
+ ok(got_click, "button under static window didn't get WM_LBUTTONUP\n");
+
+ ret = WaitForSingleObject(end_event, 5000);
+ ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
+
+ CloseHandle(start_event);
+ CloseHandle(end_event);
+}
+
+static void test_window_from_point(const char *argv0)
+{
+ HWND hwnd, child, win;
+ POINT pt;
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ char cmd[MAX_PATH];
+ HANDLE start_event, end_event;
+
+ hwnd = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP | WS_VISIBLE,
+ 100, 100, 200, 100, 0, 0, NULL, NULL);
+ ok(hwnd != 0, "CreateWindowEx failed\n");
+
+ pt.x = pt.y = 150;
+ win = WindowFromPoint(pt);
+ pt.x = 250;
+ if(win == hwnd)
+ win = WindowFromPoint(pt);
+ if(win != hwnd) {
+ skip("there's another window covering test window\n");
+ DestroyWindow(hwnd);
+ return;
+ }
+
+ child = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, hwnd, 0, NULL, NULL);
+ ok(child != 0, "CreateWindowEx failed\n");
+ pt.x = pt.y = 150;
+ win = WindowFromPoint(pt);
+ ok(win == hwnd, "WindowFromPoint returned %p, expected %p\n", win, hwnd);
+ DestroyWindow(child);
+
+ child = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
+ 0, 0, 100, 100, hwnd, 0, NULL, NULL);
+ ok(child != 0, "CreateWindowEx failed\n");
+ win = WindowFromPoint(pt);
+ ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
+ DestroyWindow(child);
+
+ start_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_start");
+ ok(start_event != 0, "CreateEvent failed\n");
+ end_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_end");
+ ok(start_event != 0, "CreateEvent failed\n");
+
+ sprintf(cmd, "%s win create_children %p\n", argv0, hwnd);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
+ &startup, &info), "CreateProcess failed.\n");
+ ok(wait_for_event(start_event, 1000), "didn't get start_event\n");
+
+ child = GetWindow(hwnd, GW_CHILD);
+ win = WindowFromPoint(pt);
+ ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
+
+ simulate_click(150, 150);
+ flush_events(TRUE);
+
+ child = GetWindow(child, GW_HWNDNEXT);
+ pt.x = 250;
+ win = WindowFromPoint(pt);
+ ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
+
+ SetEvent(end_event);
+ winetest_wait_child_process(info.hProcess);
+ CloseHandle(start_event);
+ CloseHandle(end_event);
+ CloseHandle(info.hProcess);
+ CloseHandle(info.hThread);
+
+ DestroyWindow(hwnd);
+}
+
static void test_map_points(void)
{
BOOL ret;
DestroyWindow(hwnd);
}
+
+struct smresult_thread_data
+{
+ HWND main_hwnd;
+ HWND thread_hwnd;
+ HANDLE thread_started;
+ HANDLE thread_got_wm_app;
+ HANDLE main_in_wm_app_1;
+ HANDLE thread_replied;
+};
+
+
+static LRESULT WINAPI smresult_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ switch (msg)
+ {
+ case WM_APP:
+ {
+ struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
+
+ ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
+
+ SendNotifyMessageA(data->main_hwnd, WM_APP+1, 0, lparam);
+
+ /* Don't return until the main thread is processing our sent message. */
+ ok(WaitForSingleObject(data->main_in_wm_app_1, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+
+ /* Break the PeekMessage loop so we can notify the main thread after we return. */
+ SetEvent(data->thread_got_wm_app);
+
+ return 0x240408ea;
+ }
+ case WM_APP+1:
+ {
+ struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
+ LRESULT res;
+
+ ok(hwnd == data->main_hwnd, "unexpected hwnd %p\n", hwnd);
+
+ /* Ask the thread to reply to our WM_APP message. */
+ SetEvent(data->main_in_wm_app_1);
+
+ /* Wait until the thread has sent a reply. */
+ ok(WaitForSingleObject(data->thread_replied, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+
+ /* Send another message while we have a reply queued for the current one. */
+ res = SendMessageA(data->thread_hwnd, WM_APP+2, 0, lparam);
+ ok(res == 0x449b0190, "unexpected result %lx\n", res);
+
+ return 0;
+ }
+ case WM_APP+2:
+ {
+ struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
+
+ ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
+
+ /* Don't return until we know the main thread is processing sent messages. */
+ SendMessageA(data->main_hwnd, WM_NULL, 0, 0);
+
+ return 0x449b0190;
+ }
+ case WM_CLOSE:
+ PostQuitMessage(0);
+ break;
+ }
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+static DWORD WINAPI smresult_thread_proc(void *param)
+{
+ MSG msg;
+ struct smresult_thread_data *data = param;
+
+ data->thread_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+ ok(data->thread_hwnd != 0, "Failed to create overlapped window\n");
+
+ SetEvent(data->thread_started);
+
+ /* Loop until we've processed WM_APP. */
+ while (WaitForSingleObject(data->thread_got_wm_app, 0) != WAIT_OBJECT_0)
+ {
+ if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+ else
+ {
+ MsgWaitForMultipleObjects(1, &data->thread_got_wm_app, FALSE, INFINITE, QS_SENDMESSAGE);
+ }
+ }
+
+ /* Notify the main thread that we replied to its WM_APP message. */
+ SetEvent(data->thread_replied);
+
+ while (GetMessageA(&msg, 0, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+
+ return 0;
+}
+
+static void test_smresult(void)
+{
+ WNDCLASSA cls;
+ HANDLE hThread;
+ DWORD tid;
+ struct smresult_thread_data data;
+ BOOL ret;
+ LRESULT res;
+
+ cls.style = CS_DBLCLKS;
+ cls.lpfnWndProc = smresult_wndproc;
+ cls.cbClsExtra = 0;
+ cls.cbWndExtra = 0;
+ cls.hInstance = GetModuleHandleA(0);
+ cls.hIcon = 0;
+ cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
+ cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+ cls.lpszMenuName = NULL;
+ cls.lpszClassName = "SmresultClass";
+
+ ret = RegisterClassA(&cls);
+ ok(ret, "RegisterClassA failed\n");
+
+ data.thread_started = CreateEventA(NULL, TRUE, FALSE, NULL);
+ ok(data.thread_started != NULL, "CreateEventA failed\n");
+
+ data.thread_got_wm_app = CreateEventA(NULL, TRUE, FALSE, NULL);
+ ok(data.thread_got_wm_app != NULL, "CreateEventA failed\n");
+
+ data.main_in_wm_app_1 = CreateEventA(NULL, TRUE, FALSE, NULL);
+ ok(data.main_in_wm_app_1 != NULL, "CreateEventA failed\n");
+
+ data.thread_replied = CreateEventA(NULL, TRUE, FALSE, NULL);
+ ok(data.thread_replied != NULL, "CreateEventA failed\n");
+
+ data.main_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
+ 100, 100, 200, 200, 0, 0, 0, NULL);
+
+ hThread = CreateThread(NULL, 0, smresult_thread_proc, &data, 0, &tid);
+ ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
+
+ ok(WaitForSingleObject(data.thread_started, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+
+ res = SendMessageA(data.thread_hwnd, WM_APP, 0, (LPARAM)&data);
+ ok(res == 0x240408ea, "unexpected result %lx\n", res);
+
+ SendMessageA(data.thread_hwnd, WM_CLOSE, 0, 0);
+
+ DestroyWindow(data.main_hwnd);
+
+ ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
+
+ CloseHandle(data.thread_started);
+ CloseHandle(data.thread_got_wm_app);
+ CloseHandle(data.main_in_wm_app_1);
+ CloseHandle(data.thread_replied);
+}
+
+static void test_GetMessagePos(void)
+{
+ HWND button;
+ DWORD pos;
+ MSG msg;
+
+ button = CreateWindowExA(0, "button", "button", WS_VISIBLE,
+ 100, 100, 100, 100, 0, 0, 0, NULL);
+ ok(button != 0, "CreateWindowExA failed\n");
+
+ SetCursorPos(120, 140);
+ flush_events(TRUE);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
+
+ SetCursorPos(340, 320);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
+
+ SendMessageW(button, WM_APP, 0, 0);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
+
+ PostMessageA(button, WM_APP, 0, 0);
+ GetMessageA(&msg, button, 0, 0);
+ ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
+
+ PostMessageA(button, WM_APP, 0, 0);
+ SetCursorPos(350, 330);
+ GetMessageA(&msg, button, 0, 0);
+ ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
+
+ PostMessageA(button, WM_APP, 0, 0);
+ SetCursorPos(320, 340);
+ PostMessageA(button, WM_APP+1, 0, 0);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
+ GetMessageA(&msg, button, 0, 0);
+ ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(350, 330), "pos = %08x\n", pos);
+ GetMessageA(&msg, button, 0, 0);
+ ok(msg.message == WM_APP+1, "msg.message = %x\n", msg.message);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(320, 340), "pos = %08x\n", pos);
+
+ SetTimer(button, 1, 250, NULL);
+ SetCursorPos(330, 350);
+ GetMessageA(&msg, button, 0, 0);
+ while (msg.message == WM_PAINT)
+ {
+ UpdateWindow( button );
+ GetMessageA(&msg, button, 0, 0);
+ }
+ ok(msg.message == WM_TIMER, "msg.message = %x\n", msg.message);
+ pos = GetMessagePos();
+ ok(pos == MAKELONG(330, 350), "pos = %08x\n", pos);
+ KillTimer(button, 1);
+
+ DestroyWindow(button);
+}
+
+#define SET_FOREGROUND_STEAL_1 0x01
+#define SET_FOREGROUND_SET_1 0x02
+#define SET_FOREGROUND_STEAL_2 0x04
+#define SET_FOREGROUND_SET_2 0x08
+#define SET_FOREGROUND_INJECT 0x10
+
+struct set_foreground_thread_params
+{
+ UINT msg_quit, msg_command;
+ HWND window1, window2, thread_window;
+ HANDLE command_executed;
+};
+
+static DWORD WINAPI set_foreground_thread(void *params)
+{
+ struct set_foreground_thread_params *p = params;
+ MSG msg;
+
+ p->thread_window = CreateWindowExA(0, "static", "thread window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 0, 0, 10, 10, 0, 0, 0, NULL);
+ SetEvent(p->command_executed);
+
+ while(GetMessageA(&msg, 0, 0, 0))
+ {
+ if (msg.message == p->msg_quit)
+ break;
+
+ if (msg.message == p->msg_command)
+ {
+ if (msg.wParam & SET_FOREGROUND_STEAL_1)
+ {
+ SetForegroundWindow(p->thread_window);
+ check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
+ }
+ if (msg.wParam & SET_FOREGROUND_INJECT)
+ {
+ SendNotifyMessageA(p->window1, WM_ACTIVATEAPP, 0, 0);
+ }
+ if (msg.wParam & SET_FOREGROUND_SET_1)
+ {
+ SetForegroundWindow(p->window1);
+ check_wnd_state(0, p->window1, 0, 0);
+ }
+ if (msg.wParam & SET_FOREGROUND_STEAL_2)
+ {
+ SetForegroundWindow(p->thread_window);
+ check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
+ }
+ if (msg.wParam & SET_FOREGROUND_SET_2)
+ {
+ SetForegroundWindow(p->window2);
+ check_wnd_state(0, p->window2, 0, 0);
+ }
+
+ SetEvent(p->command_executed);
+ continue;
+ }
+
+ TranslateMessage(&msg);
+ DispatchMessageA(&msg);
+ }
+
+ DestroyWindow(p->thread_window);
+ return 0;
+}
+
+static void test_activateapp(HWND window1)
+{
+ HWND window2, test_window;
+ HANDLE thread;
+ struct set_foreground_thread_params thread_params;
+ DWORD tid;
+ MSG msg;
+
+ window2 = CreateWindowExA(0, "static", "window 2", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+ 300, 0, 10, 10, 0, 0, 0, NULL);
+ thread_params.msg_quit = WM_USER;
+ thread_params.msg_command = WM_USER + 1;
+ thread_params.window1 = window1;
+ thread_params.window2 = window2;
+ thread_params.command_executed = CreateEventW(NULL, FALSE, FALSE, NULL);
+
+ thread = CreateThread(NULL, 0, set_foreground_thread, &thread_params, 0, &tid);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+
+ SetForegroundWindow(window1);
+ check_wnd_state(window1, window1, window1, 0);
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+
+ /* Steal foreground: WM_ACTIVATEAPP(0) is delivered. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ test_window = GetForegroundWindow();
+ ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
+ thread_params.thread_window, test_window);
+ /* Active and Focus window are sometimes 0 on KDE. Ignore them.
+ * check_wnd_state(window1, thread_params.thread_window, window1, 0); */
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ check_wnd_state(0, thread_params.thread_window, 0, 0);
+ test_window = GetForegroundWindow();
+ ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
+ thread_params.thread_window, test_window);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ /* This message is reliable on Windows and inside a virtual desktop.
+ * It is unreliable on KDE (50/50) and never arrives on FVWM.
+ * ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); */
+
+ /* Set foreground: WM_ACTIVATEAPP (1) is delivered. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ check_wnd_state(0, 0, 0, 0);
+ test_window = GetForegroundWindow();
+ ok(!test_window, "Expected foreground window 0, got %p\n", test_window);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(!= 0), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ check_wnd_state(window1, window1, window1, 0);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+
+ /* Steal foreground then set it back: No messages are delivered. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_1, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+
+ /* This is not implemented with a plain WM_ACTIVATEAPP filter. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1
+ | SET_FOREGROUND_INJECT | SET_FOREGROUND_SET_1, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
+
+ SetForegroundWindow(thread_params.thread_window);
+
+ /* Set foreground then remove: Both messages are delivered. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1 | SET_FOREGROUND_STEAL_2, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ test_window = GetForegroundWindow();
+ ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
+ thread_params.thread_window, test_window);
+ check_wnd_state(0, thread_params.thread_window, 0, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ test_window = GetForegroundWindow();
+ ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
+ thread_params.thread_window, test_window);
+ /* Active and focus are window1 on wine because the internal WM_WINE_SETACTIVEWINDOW(0)
+ * message is never generated. GetCapture() returns 0 though, so we'd get a test success
+ * in todo_wine in the line below.
+ * todo_wine check_wnd_state(0, thread_params.thread_window, 0, 0); */
+ ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
+ todo_wine ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
+
+ SetForegroundWindow(window1);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+
+ /* Switch to a different window from the same thread? No messages. */
+ app_activated = app_deactivated = FALSE;
+ PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_2, 0);
+ WaitForSingleObject(thread_params.command_executed, INFINITE);
+ test_window = GetForegroundWindow();
+ ok(test_window == window1, "Expected foreground window %p, got %p\n",
+ window1, test_window);
+ check_wnd_state(window1, window1, window1, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+ while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
+ test_window = GetForegroundWindow();
+ ok(test_window == window2, "Expected foreground window %p, got %p\n",
+ window2, test_window);
+ check_wnd_state(window2, window2, window2, 0);
+ ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
+ ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
+
+ PostThreadMessageA(tid, thread_params.msg_quit, 0, 0);
+ WaitForSingleObject(thread, INFINITE);
+
+ CloseHandle(thread_params.command_executed);
+ DestroyWindow(window2);
+}
+
+static LRESULT WINAPI winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if(!hwnd) {
+ int *count = (int*)lparam;
+ (*count)++;
+ }
+ return 0;
+}
+
+static LRESULT WINAPI winproc_convA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if(msg == WM_SETTEXT)
+ {
+ const char *text = (const char*)lparam;
+
+ ok(!wparam, "wparam = %08lx\n", wparam);
+ ok(!strcmp(text, "text"), "WM_SETTEXT lparam = %s\n", text);
+ return 1;
+ }
+ return 0;
+}
+
+static const WCHAR textW[] = {'t','e','x','t',0};
+static LRESULT WINAPI winproc_convW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ if(msg == WM_SETTEXT)
+ {
+ const WCHAR *text = (const WCHAR*)lparam;
+
+ ok(!wparam, "wparam = %08lx\n", wparam);
+ ok(!lstrcmpW(text, textW), "WM_SETTEXT lparam = %s\n", wine_dbgstr_w(text));
+ return 1;
+ }
+ return 0;
+}
+
+static void test_winproc_handles(const char *argv0)
+{
+ static const WCHAR winproc_testW[] = {'w','i','n','p','r','o','c','_','t','e','s','t',0};
+
+ HINSTANCE hinst = GetModuleHandleA(NULL);
+ WNDCLASSA wnd_classA;
+ WNDCLASSW wnd_classW;
+ int count, ret;
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ char cmd[MAX_PATH];
+
+ memset(&wnd_classA, 0, sizeof(wnd_classA));
+ wnd_classA.lpszClassName = "winproc_test";
+ wnd_classA.lpfnWndProc = winproc;
+ ret = RegisterClassA(&wnd_classA);
+ ok(ret, "RegisterClass failed with error %d\n", GetLastError());
+
+ ret = GetClassInfoW(hinst, winproc_testW, &wnd_classW);
+ ok(ret, "GetClassInfoW failed with error %d\n", GetLastError());
+ ok(wnd_classA.lpfnWndProc != wnd_classW.lpfnWndProc,
+ "winproc pointers should not be identical\n");
+
+ count = 0;
+ CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
+ ok(count == 1, "winproc should be called once (%d)\n", count);
+ count = 0;
+ CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
+ ok(count == 1, "winproc should be called once (%d)\n", count);
+
+ ret = UnregisterClassW(winproc_testW, hinst);
+ ok(ret, "UnregisterClass failed with error %d\n", GetLastError());
+
+ /* crashes on 64-bit windows because lpfnWndProc handle is already freed */
+ if (sizeof(void*) == 4)
+ {
+ count = 0;
+ CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
+ todo_wine ok(!count, "winproc should not be called (%d)\n", count);
+ CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
+ todo_wine ok(!count, "winproc should not be called (%d)\n", count);
+ }
+
+ sprintf(cmd, "%s win winproc_limit", argv0);
+ memset(&startup, 0, sizeof(startup));
+ startup.cb = sizeof(startup);
+ ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
+ &startup, &info), "CreateProcess failed.\n");
+ winetest_wait_child_process(info.hProcess);
+ CloseHandle(info.hProcess);
+ CloseHandle(info.hThread);
+}
+
+static void test_winproc_limit(void)
+{
+ WNDPROC winproc_handle;
+ LONG_PTR ret;
+ HWND hwnd;
+ int i;
+
+ hwnd = CreateWindowExA(0, "static", "test", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
+ ok(hwnd != 0, "CreateWindowEx failed\n");
+
+ ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc),
+ "SetWindowLongPtr failed\n");
+ winproc_handle = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
+ ok(winproc_handle != winproc, "winproc pointers should not be identical\n");
+
+ /* run out of winproc slots */
+ for(i = 2; i<0xffff; i++)
+ {
+ ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, i), "SetWindowLongPtr failed (%d)\n", i);
+ if(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == i)
+ break;
+ }
+ ok(i != 0xffff, "unable to run out of winproc slots\n");
+
+ ret = SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convA);
+ ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError());
+ ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
+ ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
+
+ ret = SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convW);
+ ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError());
+ ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
+ ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
+
+ /* Show that there's no message conversion when CallWindowProc is used */
+ ok(CallWindowProcA(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
+ "winproc_convW returned error\n");
+ ok(CallWindowProcW(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
+ "winproc_convW returned error\n");
+
+ i = 0;
+ CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
+ ok(i == 1, "winproc should be called once (%d)\n", i);
+ i = 0;
+ CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
+ ok(i == 1, "winproc should be called once (%d)\n", i);
+
+ DestroyWindow(hwnd);
+
+ i = 0;
+ CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
+ ok(i == 1, "winproc should be called once (%d)\n", i);
+ i = 0;
+ CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
+ ok(i == 1, "winproc should be called once (%d)\n", i);
+}
+
+static void test_deferwindowpos(void)
+{
+ HDWP hdwp, hdwp2;
+ BOOL ret;
+
+ hdwp = BeginDeferWindowPos(0);
+ ok(hdwp != NULL, "got %p\n", hdwp);
+
+ ret = EndDeferWindowPos(NULL);
+ ok(!ret, "got %d\n", ret);
+
+ hdwp2 = DeferWindowPos(NULL, NULL, NULL, 0, 0, 10, 10, 0);
+todo_wine
+ ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) ||
+ broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError());
+
+ hdwp2 = DeferWindowPos((HDWP)0xdead, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0);
+todo_wine
+ ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) ||
+ broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError());
+
+ hdwp2 = DeferWindowPos(hdwp, NULL, NULL, 0, 0, 10, 10, 0);
+ ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
+
+ hdwp2 = DeferWindowPos(hdwp, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0);
+ ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
+
+ hdwp2 = DeferWindowPos(hdwp, (HWND)0xdead, NULL, 0, 0, 10, 10, 0);
+ ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError());
+
+ ret = EndDeferWindowPos(hdwp);
+ ok(ret, "got %d\n", ret);
+}
+
START_TEST(win)
{
+ char **argv;
+ int argc = winetest_get_mainargs( &argv );
HMODULE user32 = GetModuleHandleA( "user32.dll" );
HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" );
pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" );
pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" );
pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" );
+ pFlashWindow = (void *)GetProcAddress( user32, "FlashWindow" );
pFlashWindowEx = (void *)GetProcAddress( user32, "FlashWindowEx" );
pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" );
pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" );
pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" );
+ if (argc==4 && !strcmp(argv[2], "create_children"))
+ {
+ HWND hwnd;
+
+ sscanf(argv[3], "%p", &hwnd);
+ window_from_point_proc(hwnd);
+ return;
+ }
+
+ if (argc==3 && !strcmp(argv[2], "winproc_limit"))
+ {
+ test_winproc_limit();
+ return;
+ }
+
if (!RegisterWindowClasses()) assert(0);
hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
if(!SetForegroundWindow(hwndMain)) {
/* workaround for foreground lock timeout */
- INPUT input[2];
- UINT events_no;
-
- memset(input, 0, sizeof(input));
- input[0].type = INPUT_MOUSE;
- U(input[0]).mi.dx = 101;
- U(input[0]).mi.dy = 101;
- U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
- input[0].type = INPUT_MOUSE;
- U(input[0]).mi.dx = 101;
- U(input[0]).mi.dy = 101;
- U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTUP;
- events_no = SendInput(2, input, sizeof(input[0]));
- ok(events_no == 2, "SendInput returned %d\n", events_no);
+ simulate_click(101, 101);
ok(SetForegroundWindow(hwndMain), "SetForegroundWindow failed\n");
}
/* Add the tests below this line */
test_child_window_from_point();
+ test_window_from_point(argv[0]);
test_thick_child_size(hwndMain);
test_fullscreen();
test_hwnd_message();
test_capture_3(hwndMain, hwndMain2);
test_capture_4();
test_rtl_layout();
+ test_FlashWindow();
test_FlashWindowEx();
test_CreateWindow();
test_AdjustWindowRect();
test_window_styles();
test_dialog_styles();
+ test_dialog_parent();
test_redrawnow();
test_csparentdc();
test_SetWindowLong();
test_ShowWindow();
- if (0) test_gettext(); /* crashes on NT4 */
+ test_gettext();
test_GetUpdateRect();
test_Expose();
test_layered_window();
test_SetForegroundWindow(hwndMain);
- if(!winetest_interactive)
- skip("bug ROSTESTS-23: skipping test_shell_window, it crashes ros/win7 explorer\n");
- else
- test_shell_window();
+ test_shell_window();
test_handles( hwndMain );
test_winregion();
test_map_points();
test_update_region();
test_window_without_child_style();
+ test_smresult();
+ test_GetMessagePos();
+
+ if (!winetest_interactive)
+ skip("ROSTESTS-208: Skipping test_activateapp(hwndMain).\n");
+ else
+ test_activateapp(hwndMain);
+ test_winproc_handles(argv[0]);
+ test_deferwindowpos();
/* add the tests above this line */
if (hhook) UnhookWindowsHookEx(hhook);