From caec6026e7edc3cfa087e6487a9781881f6a3082 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Wed, 23 Mar 2005 10:26:15 +0000 Subject: [PATCH] - Window styles passed to CreateWindowEx must the same as passed in CREATESTRUCT for WM_CREATE/WM_NCCREATE. - Fix cases where WS_EX_WINDOWEDGE style is applied. - Tests for the above. --- dlls/user/tests/win.c | 112 ++++++++++++++++++++++++++++++++++++++++++ dlls/x11drv/window.c | 11 ++++- windows/win.c | 45 +++++++++-------- 3 files changed, 147 insertions(+), 21 deletions(-) diff --git a/dlls/user/tests/win.c b/dlls/user/tests/win.c index bb18ee9218f..ed8425c2df8 100644 --- a/dlls/user/tests/win.c +++ b/dlls/user/tests/win.c @@ -2471,6 +2471,116 @@ todo_wine { ok(!IsWindow(child4), "child4 still exists\n"); } +static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + LPCREATESTRUCT lpcs; + LPSTYLESTRUCT lpss; + + switch (msg) + { + case WM_NCCREATE: + case WM_CREATE: + lpcs = (LPCREATESTRUCT)lparam; + lpss = (LPSTYLESTRUCT)lpcs->lpCreateParams; + if (lpss) + { + if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) || + ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) && + (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME)))) + ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n"); + else + ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n"); + + ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE), + "Ex style (0x%08lx) should match what the caller passed to CreateWindowEx (0x%08lx)\n", + (lpss->styleOld & ~WS_EX_WINDOWEDGE), (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE)); + + ok(lpss->styleNew == lpcs->style, + "Style (0x%08lx) should match what the caller passed to CreateWindowEx (0x%08lx)\n", + lpss->styleNew, lpcs->style); + } + break; + } + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +static ATOM atomStyleCheckClass; + +static void register_style_check_class(void) +{ + WNDCLASS wc = + { + 0, + StyleCheckProc, + 0, + 0, + GetModuleHandle(NULL), + NULL, + LoadCursor(NULL, IDC_ARROW), + (HBRUSH)(COLOR_BTNFACE+1), + NULL, + TEXT("WineStyleCheck"), + }; + + atomStyleCheckClass = RegisterClass(&wc); +} + +static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut) +{ + DWORD dwActualStyle; + DWORD dwActualExStyle; + STYLESTRUCT ss; + HWND hwnd; + HWND hwndParent = NULL; + MSG msg; + + ss.styleNew = dwStyleIn; + ss.styleOld = dwExStyleIn; + + if (dwStyleIn & WS_CHILD) + { + hwndParent = CreateWindowEx(0, MAKEINTATOM(atomStyleCheckClass), NULL, + WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL); + } + + hwnd = CreateWindowEx(dwExStyleIn, MAKEINTATOM(atomStyleCheckClass), NULL, + dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss); + assert(hwnd); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + dwActualStyle = GetWindowLong(hwnd, GWL_STYLE); + dwActualExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + ok((dwActualStyle == dwStyleOut) && (dwActualExStyle == dwExStyleOut), + "Style (0x%08lx) should really be 0x%08lx and/or Ex style (0x%08lx) should really be 0x%08lx\n", + dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut); + + DestroyWindow(hwnd); + if (hwndParent) DestroyWindow(hwndParent); +} + +/* tests what window styles the window manager automatically adds */ +static void test_window_styles() +{ + register_style_check_class(); + + check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE); + check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE); + check_window_style(WS_CHILD, 0, WS_CHILD, 0); + check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0); + check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW); + check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0); + check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0); + check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); + check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); + check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE); + check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE); +} + START_TEST(win) { pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" ); @@ -2531,4 +2641,6 @@ START_TEST(win) test_nccalcscroll( hwndMain); UnhookWindowsHookEx(hhook); + + test_window_styles(); } diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c index e8762b40558..f987d878b47 100644 --- a/dlls/x11drv/window.c +++ b/dlls/x11drv/window.c @@ -871,6 +871,7 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) RECT rect; DWORD style; CBT_CREATEWNDA cbtc; + CREATESTRUCTA cbcs; BOOL ret = FALSE; if (cs->cx > 65535) @@ -926,7 +927,15 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) } /* Call the WH_CBT hook */ - cbtc.lpcs = cs; + + /* the window style passed to the hook must be the real window style, + * rather than just the window style that the caller to CreateWindowEx + * passed in, so we have to copy the original CREATESTRUCT and get the + * the real style. */ + cbcs = *cs; + cbcs.style = GetWindowLongW(hwnd, GWL_STYLE); + + cbtc.lpcs = &cbcs; cbtc.hwndInsertAfter = HWND_TOP; if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) { diff --git a/windows/win.c b/windows/win.c index 9f70ee97759..f9a05cab7ea 100644 --- a/windows/win.c +++ b/windows/win.c @@ -1111,18 +1111,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, WIN_FixCoordinates(cs, &sw); /* fix default coordinates */ - /* Correct the window styles. - * - * It affects both the style loaded into the WIN structure and - * passed in the CREATESTRUCT to the WM_[NC]CREATE. - * - * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so - * why does the user get to set it? - */ - - /* This has been tested for WS_CHILD | WS_VISIBLE. It has not been - * tested for WS_POPUP - */ if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) || ((!(cs->dwExStyle & WS_EX_STATICEDGE)) && (cs->style & (WS_DLGFRAME | WS_THICKFRAME)))) @@ -1130,13 +1118,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, else cs->dwExStyle &= ~WS_EX_WINDOWEDGE; - if (!(cs->style & WS_CHILD)) - { - cs->style |= WS_CLIPSIBLINGS; - if (!(cs->style & WS_POPUP)) - cs->style |= WS_CAPTION; - } - /* Create the window structure */ if (!(wndPtr = create_window_handle( parent, owner, classAtom, cs->hInstance, type ))) @@ -1165,7 +1146,31 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->hIconSmall = 0; wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU) ? MENU_GetSysMenu( hwnd, 0 ) : 0; - if (!(cs->style & (WS_CHILD | WS_POPUP))) + /* + * Correct the window styles. + * + * It affects only the style loaded into the WIN structure. + */ + + if (!(wndPtr->dwStyle & WS_CHILD)) + { + wndPtr->dwStyle |= WS_CLIPSIBLINGS; + if (!(wndPtr->dwStyle & WS_POPUP)) + wndPtr->dwStyle |= WS_CAPTION; + } + + /* + * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so + * why does the user get to set it? + */ + + if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) || + (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME))) + wndPtr->dwExStyle |= WS_EX_WINDOWEDGE; + else + wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE; + + if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP))) wndPtr->flags |= WIN_NEED_SIZE; SERVER_START_REQ( set_window_info )