From 11f4efc5111501f2b0bddb07d1affd6a073875be Mon Sep 17 00:00:00 2001 From: Royce Mitchell III Date: Fri, 28 May 2004 17:56:17 +0000 Subject: [PATCH] upgrading user32 test to Wine-20040527 - disabled a test in the 'msg' test because it fails on XP SP1. svn path=/trunk/; revision=9516 --- reactos/apps/tests/user32/class.c | 16 +- reactos/apps/tests/user32/dde.c | 119 ++++ reactos/apps/tests/user32/dialog.c | 6 +- reactos/apps/tests/user32/input.c | 18 +- reactos/apps/tests/user32/listbox.c | 2 +- reactos/apps/tests/user32/makefile | 3 +- reactos/apps/tests/user32/msg.c | 899 ++++++++++++++++++++++---- reactos/apps/tests/user32/resource.c | 2 +- reactos/apps/tests/user32/sysparams.c | 209 ++++++ reactos/apps/tests/user32/testlist.c | 4 + reactos/apps/tests/user32/win.c | 541 +++++++++++++++- 11 files changed, 1666 insertions(+), 153 deletions(-) create mode 100644 reactos/apps/tests/user32/dde.c diff --git a/reactos/apps/tests/user32/class.c b/reactos/apps/tests/user32/class.c index ec46a95b359..5d61df4c1ac 100644 --- a/reactos/apps/tests/user32/class.c +++ b/reactos/apps/tests/user32/class.c @@ -20,9 +20,6 @@ /* To get CS_DROPSHADOW with the MSVC headers */ #define _WIN32_WINNT 0x0501 -#ifndef CS_DROPSHADOW -#define CS_DROPSHADOW 0x00020000 -#endif #include #include @@ -48,8 +45,8 @@ static LRESULT WINAPI ClassTest_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPA static void ClassTest(HINSTANCE hInstance, BOOL global) { WNDCLASSW cls, wc; - WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0}; - WCHAR winName[] = {'W','i','n','C','l','a','s','s','T','e','s','t',0}; + static const WCHAR className[] = {'T','e','s','t','C','l','a','s','s',0}; + static const WCHAR winName[] = {'W','i','n','C','l','a','s','s','T','e','s','t',0}; ATOM test_atom; HWND hTestWnd; DWORD i; @@ -243,7 +240,7 @@ static void check_class(HINSTANCE inst, const char *name, const char *menu_name) static void check_instance( const char *name, HINSTANCE inst, HINSTANCE info_inst, HINSTANCE gcl_inst ) { - WNDCLASS wc; + WNDCLASSA wc; HWND hwnd; ok( GetClassInfo( inst, name, &wc ), "Couldn't find class %s inst %p\n", name, inst ); @@ -251,9 +248,12 @@ static void check_instance( const char *name, HINSTANCE inst, HINSTANCE info_ins wc.hInstance, info_inst, name ); hwnd = CreateWindowExA( 0, name, "test_window", 0, 0, 0, 0, 0, 0, 0, inst, 0 ); ok( hwnd != NULL, "Couldn't create window for class %s inst %p\n", name, inst ); - ok( (HINSTANCE)GetClassLong( hwnd, GCL_HMODULE ) == gcl_inst, + ok( (HINSTANCE)GetClassLongA( hwnd, GCL_HMODULE ) == gcl_inst, "Wrong GCL instance %p/%p for class %s\n", - (HINSTANCE)GetClassLong( hwnd, GCL_HMODULE ), gcl_inst, name ); + (HINSTANCE)GetClassLongA( hwnd, GCL_HMODULE ), gcl_inst, name ); + ok( (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ) == inst, + "Wrong GWL instance %p/%p for window %s\n", + (HINSTANCE)GetWindowLongA( hwnd, GWL_HINSTANCE ), inst, name ); DestroyWindow(hwnd); } diff --git a/reactos/apps/tests/user32/dde.c b/reactos/apps/tests/user32/dde.c new file mode 100644 index 00000000000..c0b8696d1a7 --- /dev/null +++ b/reactos/apps/tests/user32/dde.c @@ -0,0 +1,119 @@ +/* + * Unit tests for DDE functions + * + * Copyright (c) 2004 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "wine/test.h" +#include "winbase.h" +#include "winuser.h" +#include "ddeml.h" +#include "winerror.h" + +static HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hconv, + HSZ hsz1, HSZ hsz2, HDDEDATA hdata, + ULONG_PTR dwData1, ULONG_PTR dwData2) +{ + return 0; +} + +static void test_DdeCreateStringHandleW(DWORD dde_inst, int codepage) +{ + static const WCHAR dde_string[] = {'D','D','E',' ','S','t','r','i','n','g',0}; + HSZ str_handle; + WCHAR bufW[256]; + char buf[256]; + int ret; + + str_handle = DdeCreateStringHandleW(dde_inst, dde_string, codepage); + ok(str_handle != 0, "DdeCreateStringHandleW failed with error %08x\n", + DdeGetLastError(dde_inst)); + + ret = DdeQueryStringW(dde_inst, str_handle, NULL, 0, codepage); + if (codepage == CP_WINANSI) + ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret); + else + ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret); + + ret = DdeQueryStringW(dde_inst, str_handle, bufW, 256, codepage); + if (codepage == CP_WINANSI) + { + ok(ret == 1, "DdeQueryStringW returned wrong length %d\n", ret); + ok(!lstrcmpA("D", (LPCSTR)bufW), "DdeQueryStringW returned wrong string\n"); + } + else + { + ok(ret == lstrlenW(dde_string), "DdeQueryStringW returned wrong length %d\n", ret); + ok(!lstrcmpW(dde_string, bufW), "DdeQueryStringW returned wrong string\n"); + } + + ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINANSI); + if (codepage == CP_WINANSI) + { + ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret); + ok(!lstrcmpA("D", buf), "DdeQueryStringW returned wrong string\n"); + } + else + { + ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret); + ok(!lstrcmpA("DDE String", buf), "DdeQueryStringA returned wrong string %s\n", buf); + } + + ret = DdeQueryStringA(dde_inst, str_handle, buf, 256, CP_WINUNICODE); + if (codepage == CP_WINANSI) + { + ok(ret == 1, "DdeQueryStringA returned wrong length %d\n", ret); + ok(!lstrcmpA("D", buf), "DdeQueryStringA returned wrong string %s\n", buf); + } + else + { + ok(ret == lstrlenA("DDE String"), "DdeQueryStringA returned wrong length %d\n", ret); + ok(!lstrcmpW(dde_string, (LPCWSTR)buf), "DdeQueryStringW returned wrong string\n"); + } + + ok(DdeFreeStringHandle(dde_inst, str_handle), "DdeFreeStringHandle failed\n"); +} + +START_TEST(dde) +{ + DWORD dde_inst, ret; + + dde_inst = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = DdeInitializeW(&dde_inst, DdeCallback, APPCMD_CLIENTONLY, 0); + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + trace("Skipping the DDE test on a Win9x platform\n"); + return; + } + + ok(ret == DMLERR_INVALIDPARAMETER, "DdeInitializeW should fail, but got %04lx instead\n", ret); + ok(DdeGetLastError(dde_inst) == DMLERR_INVALIDPARAMETER, "expected DMLERR_INVALIDPARAMETER\n"); + + dde_inst = 0; + ret = DdeInitializeW(&dde_inst, DdeCallback, APPCMD_CLIENTONLY, 0); + ok(ret == DMLERR_NO_ERROR, "DdeInitializeW failed with error %04lx (%08x)\n", + ret, DdeGetLastError(dde_inst)); + + test_DdeCreateStringHandleW(dde_inst, 0); + test_DdeCreateStringHandleW(dde_inst, CP_WINUNICODE); + test_DdeCreateStringHandleW(dde_inst, CP_WINANSI); + + ok(DdeUninitialize(dde_inst), "DdeUninitialize failed\n"); +} diff --git a/reactos/apps/tests/user32/dialog.c b/reactos/apps/tests/user32/dialog.c index c4f55888f09..963580d6d33 100644 --- a/reactos/apps/tests/user32/dialog.c +++ b/reactos/apps/tests/user32/dialog.c @@ -365,9 +365,9 @@ static void GetNextDlgItemTest (void) { 1, 23, 6, 68, 0, 0, 68}, { 1, 24, 6, 25, 0, 1, 72}, { 1, 25, 1, 70, 0, 0, 72}, - { 0, 26, 1, 70, 0, 1, 3}, + /*{ 0, 26, 1, 70, 0, 1, 3}, Crashes Win95*/ { 1, 27, 1, 70, 1, 0, 72}, - { 0, 28, 1, 70, 1, 1, 61}, + /*{ 0, 28, 1, 70, 1, 1, 61}, Crashes Win95*/ { 1, 29, 6, 67, 1, 0, 72}, { 1, 30, 6, 72, 1, 1, 67}, @@ -515,4 +515,4 @@ START_TEST(dialog) GetNextDlgItemTest(); IsDialogMessageWTest(); -} +} \ No newline at end of file diff --git a/reactos/apps/tests/user32/input.c b/reactos/apps/tests/user32/input.c index f068f2ccf49..a9b71425b6e 100644 --- a/reactos/apps/tests/user32/input.c +++ b/reactos/apps/tests/user32/input.c @@ -46,9 +46,10 @@ #define _WIN32_WINNT 0x401 +#include #include "wine/test.h" -#include "winbase.h" -#include "winuser.h" +//#include "winbase.h" +//#include "winuser.h" #include @@ -56,6 +57,8 @@ HWND hWndTest; long timetag = 0x10000000; +static UINT (WINAPI *ptr_SendInput) (UINT, INPUT*, size_t); + #define MAXKEYEVENTS 6 #define MAXKEYMESSAGES MAXKEYEVENTS /* assuming a key event generates one and only one message */ @@ -203,12 +206,19 @@ int KbdMessage( KEV kev, WPARAM *pwParam, LPARAM *plParam ) */ void do_test( HWND hwnd, int seqnr, KEV td[] ) { + HMODULE module; INPUT inputs[MAXKEYEVENTS]; KMSG expmsg[MAXKEYEVENTS]; MSG msg; char buf[100]; UINT evtctr=0; int kmctr, i; + + module = GetModuleHandleA("user32"); + if (!module) return; + ptr_SendInput = (void *)GetProcAddress(module, "SendInput"); + if (!ptr_SendInput) return; + buf[0]='\0'; TrackSysKey=0; /* see input.c */ for( i = 0; i < MAXKEYEVENTS; i++) { @@ -222,7 +232,7 @@ void do_test( HWND hwnd, int seqnr, KEV td[] ) for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++) ; assert( evtctr <= MAXKEYEVENTS ); - assert( evtctr == SendInput(evtctr, &inputs[0], sizeof(INPUT))); + assert( evtctr == ptr_SendInput(evtctr, &inputs[0], sizeof(INPUT))); i = 0; trace("======== key stroke sequence #%d: %s =============\n", seqnr + 1, buf); @@ -352,4 +362,4 @@ START_TEST(input) TranslateMessage( &msg ); DispatchMessageA( &msg ); } -} +} \ No newline at end of file diff --git a/reactos/apps/tests/user32/listbox.c b/reactos/apps/tests/user32/listbox.c index 5304fbff55e..5a2074670f3 100644 --- a/reactos/apps/tests/user32/listbox.c +++ b/reactos/apps/tests/user32/listbox.c @@ -170,4 +170,4 @@ START_TEST(listbox) check (MS); trace (" ... with NOSEL\n"); check (MS_NS); -} +} \ No newline at end of file diff --git a/reactos/apps/tests/user32/makefile b/reactos/apps/tests/user32/makefile index 7929791fbc1..fa0d1b28f2c 100644 --- a/reactos/apps/tests/user32/makefile +++ b/reactos/apps/tests/user32/makefile @@ -1,4 +1,4 @@ -# $Id: makefile,v 1.2 2004/02/14 20:13:04 sedwards Exp $ +# $Id: makefile,v 1.3 2004/05/28 17:56:17 royce Exp $ PATH_TO_TOP = ../../.. @@ -18,6 +18,7 @@ TARGET_SDKLIBS = gdi32.a user32.a TARGET_OBJECTS = \ testlist.o \ class.o \ + dde.o \ dialog.o \ listbox.o \ msg.o \ diff --git a/reactos/apps/tests/user32/msg.c b/reactos/apps/tests/user32/msg.c index 775ce9819ec..55a9b2c9638 100644 --- a/reactos/apps/tests/user32/msg.c +++ b/reactos/apps/tests/user32/msg.c @@ -3,6 +3,7 @@ * * Copyright 1999 Ove Kaaven * Copyright 2003 Dimitrie O. Paun + * Copyright 2004 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,9 +21,7 @@ */ #include -#include #include -#include #include "windef.h" #include "winbase.h" @@ -44,102 +43,246 @@ Window Edge Styles (Win31/Win95/98 look), in order of precedence: typedef enum { sent=0x1, posted=0x2, parent=0x4, wparam=0x8, lparam=0x10, - defwinproc=0x20 + defwinproc=0x20, optional=0x40, hook=0x80 } msg_flags_t; struct message { UINT message; /* the WM_* code */ msg_flags_t flags; /* message props */ - WPARAM wParam; /* expacted value of wParam */ - LPARAM lParam; /* expacted value of lParam */ + WPARAM wParam; /* expected value of wParam */ + LPARAM lParam; /* expected value of lParam */ }; /* CreateWindow (for overlapped window, not initially visible) (16/32) */ -static struct message WmCreateOverlappedSeq[] = { +static const struct message WmCreateOverlappedSeq[] = { + { HCBT_CREATEWND, hook }, { WM_GETMINMAXINFO, sent }, { WM_NCCREATE, sent }, { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { 0 } }; -/* ShowWindow (for overlapped window) (16/32) */ -static struct message WmShowOverlappedSeq[] = { - { WM_SHOWWINDOW, sent|wparam, 1 }, - { WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW*/ 0 }, - /* FIXME: WM_QUERYNEWPALETTE, if in 256-color mode */ - { WM_WINDOWPOSCHANGING, sent|wparam, /*FIXME: SWP_NOMOVE|SWP_NOSIZE*/ 0 }, +/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) + * for a not visible overlapped window. + */ +static const struct message WmSWP_ShowOverlappedSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, 0 }, /* Win9x: SWP_NOSENDCHANGING */ { WM_ACTIVATEAPP, sent|wparam, 1 }, { WM_NCACTIVATE, sent|wparam, 1 }, - { WM_GETTEXT, sent|defwinproc }, + { WM_GETTEXT, sent|defwinproc|optional }, { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, - { WM_NCPAINT, sent|wparam, 1 }, - { WM_GETTEXT, sent|defwinproc }, - { WM_ERASEBKGND, sent }, - { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_SHOWWINDOW }, - { WM_SIZE, sent }, - { WM_MOVE, sent }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, { 0 } }; - -/* DestroyWindow (for overlapped window) (32) */ -static struct message WmDestroyOverlappedSeq[] = { +/* SetWindowPos(SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE) + * for a visible overlapped window. + */ +static const struct message WmSWP_HideOverlappedSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { 0 } +}; +/* ShowWindow(SW_SHOW) for a not visible overlapped window */ +static const struct message WmShowOverlappedSeq[] = { + { WM_SHOWWINDOW, sent|wparam, 1 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_ACTIVATEAPP, sent|wparam, 1 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_SETFOCUS, sent|wparam|defwinproc, 0 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|optional }, + { WM_NCPAINT, sent|optional }, + { WM_ERASEBKGND, sent|optional }, +#if 0 /* CreateWindow/ShowWindow(SW_SHOW) also generates WM_SIZE/WM_MOVE + * messages. Does that mean that CreateWindow doesn't set initial + * window dimensions for overlapped windows? + */ + { WM_SIZE, sent }, + { WM_MOVE, sent }, +#endif + { 0 } +}; +/* ShowWindow(SW_HIDE) for a visible overlapped window */ +static const struct message WmHideOverlappedSeq[] = { + { WM_SHOWWINDOW, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_SIZE, sent }, + { WM_MOVE, sent }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_ACTIVATEAPP, sent|wparam, 0 }, + { WM_KILLFOCUS, sent|wparam, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, + { 0 } +}; +/* DestroyWindow for a visible overlapped window */ +static const struct message WmDestroyOverlappedSeq[] = { + { HCBT_DESTROYWND, hook }, { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, { WM_NCACTIVATE, sent|wparam, 0 }, { WM_ACTIVATE, sent|wparam, 0 }, { WM_ACTIVATEAPP, sent|wparam, 0 }, { WM_KILLFOCUS, sent|wparam, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 } }; +/* CreateWindow (for a child popup window, not initially visible) */ +static const struct message WmCreateChildPopupSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { WM_SIZE, sent }, + { WM_MOVE, sent }, + { 0 } +}; +/* CreateWindow (for a popup window, not initially visible, + * which sets WS_VISIBLE in WM_CREATE handler) + */ +static const struct message WmCreateInvisiblePopupSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { WM_STYLECHANGING, sent }, + { WM_STYLECHANGED, sent }, + { WM_SIZE, sent }, + { WM_MOVE, sent }, + { 0 } +}; +/* ShowWindow (for a popup window with WS_VISIBLE style set) */ +static const struct message WmShowVisiblePopupSeq[] = { + { 0 } +}; +/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER) + * for a popup window with WS_VISIBLE style set + */ +static const struct message WmShowVisiblePopupSeq_2[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { 0 } +}; +/* SetWindowPos(SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE) + * for a popup window with WS_VISIBLE style set + */ +static const struct message WmShowVisiblePopupSeq_3[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_ACTIVATE, sent|wparam, 1 }, + { HCBT_SETFOCUS, hook }, + { WM_KILLFOCUS, sent|parent }, + { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|defwinproc|optional, 1 }, + { WM_SETFOCUS, sent|defwinproc }, + { 0 } +}; /* CreateWindow (for child window, not initially visible) */ -static struct message WmCreateChildSeq[] = { +static const struct message WmCreateChildSeq[] = { + { HCBT_CREATEWND, hook }, { WM_NCCREATE, sent }, /* child is inserted into parent's child list after WM_NCCREATE returns */ { WM_NCCALCSIZE, sent|wparam, 0 }, { WM_CREATE, sent }, { WM_SIZE, sent }, { WM_MOVE, sent }, - { WM_PARENTNOTIFY, sent|parent|wparam, 1 }, + { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, { 0 } }; -/* ShowWindow (for child window) */ -static struct message WmShowChildSeq[] = { +/* CreateWindow (for maximized child window, not initially visible) */ +static const struct message WmCreateMaximizedChildSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, + { WM_SIZE, sent }, + { WM_MOVE, sent }, + { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, + { WM_GETMINMAXINFO, sent }, + { WM_WINDOWPOSCHANGING, sent }, + { WM_NCCALCSIZE, sent }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_SIZE, sent|defwinproc }, + { WM_PARENTNOTIFY, sent|parent|wparam, WM_CREATE }, + { 0 } +}; +/* ShowWindow(SW_SHOW) for a not visible child window */ +static const struct message WmShowChildSeq[] = { { WM_SHOWWINDOW, sent|wparam, 1 }, { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, - { WM_ERASEBKGND, sent|parent }, + { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, { 0 } }; -/* DestroyWindow (for child window) */ -static struct message WmDestroyChildSeq[] = { - { WM_PARENTNOTIFY, sent|parent|wparam, 2 }, +/* DestroyWindow for a visible child window */ +static const struct message WmDestroyChildSeq[] = { + { HCBT_DESTROYWND, hook }, + { WM_PARENTNOTIFY, sent|parent|wparam, WM_DESTROY }, { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, - { WM_ERASEBKGND, sent|parent }, + { WM_ERASEBKGND, sent|parent|optional }, { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { HCBT_SETFOCUS, hook }, /* set focus to a parent */ + { WM_KILLFOCUS, sent }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|parent|optional, 1 }, + { WM_SETFOCUS, sent|parent }, { WM_DESTROY, sent }, + { WM_DESTROY, sent|optional }, /* a bug in win2k sp4 ? */ { WM_NCDESTROY, sent }, + { WM_NCDESTROY, sent|optional }, /* a bug in win2k sp4 ? */ { 0 } }; /* Moving the mouse in nonclient area */ -static struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */ +static const struct message WmMouseMoveInNonClientAreaSeq[] = { /* FIXME: add */ { WM_NCHITTEST, sent }, { WM_SETCURSOR, sent }, { WM_NCMOUSEMOVE, posted }, { 0 } }; /* Moving the mouse in client area */ -static struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */ +static const struct message WmMouseMoveInClientAreaSeq[] = { /* FIXME: add */ { WM_NCHITTEST, sent }, { WM_SETCURSOR, sent }, { WM_MOUSEMOVE, posted }, { 0 } }; /* Moving by dragging the title bar (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */ -static struct message WmDragTitleBarSeq[] = { /* FIXME: add */ +static const struct message WmDragTitleBarSeq[] = { /* FIXME: add */ { WM_NCLBUTTONDOWN, sent|wparam, HTCAPTION }, { WM_SYSCOMMAND, sent|defwinproc|wparam, SC_MOVE+2 }, { WM_GETMINMAXINFO, sent|defwinproc }, @@ -151,7 +294,7 @@ static struct message WmDragTitleBarSeq[] = { /* FIXME: add */ { 0 } }; /* Sizing by dragging the thick borders (after WM_NCHITTEST and WM_SETCURSOR) (outline move) */ -static struct message WmDragThinkBordersBarSeq[] = { /* FIXME: add */ +static const struct message WmDragThickBordersBarSeq[] = { /* FIXME: add */ { WM_NCLBUTTONDOWN, sent|wparam, 0xd }, { WM_SYSCOMMAND, sent|defwinproc|wparam, 0xf004 }, { WM_GETMINMAXINFO, sent|defwinproc }, @@ -170,17 +313,17 @@ static struct message WmDragThinkBordersBarSeq[] = { /* FIXME: add */ { 0 } }; /* Resizing child window with MoveWindow (32) */ -static struct message WmResizingChildWithMoveWindowSeq[] = { +static const struct message WmResizingChildWithMoveWindowSeq[] = { { WM_WINDOWPOSCHANGING, sent }, { WM_NCCALCSIZE, sent|wparam, 1 }, - { WM_ERASEBKGND, sent }, + { WM_ERASEBKGND, sent|optional }, { WM_WINDOWPOSCHANGED, sent }, { WM_MOVE, sent|defwinproc }, { WM_SIZE, sent|defwinproc }, { 0 } }; /* Clicking on inactive button */ -static struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */ +static const struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */ { WM_NCHITTEST, sent }, { WM_PARENTNOTIFY, sent|parent|wparam, WM_LBUTTONDOWN }, { WM_MOUSEACTIVATE, sent }, @@ -201,7 +344,7 @@ static struct message WmClickInactiveButtonSeq[] = { /* FIXME: add */ }; /* Reparenting a button (16/32) */ /* The last child (button) reparented gets topmost for its new parent. */ -static struct message WmReparentButtonSeq[] = { /* FIXME: add */ +static const struct message WmReparentButtonSeq[] = { /* FIXME: add */ { WM_SHOWWINDOW, sent|wparam, 0 }, { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER }, { WM_ERASEBKGND, sent|parent }, @@ -213,62 +356,147 @@ static struct message WmReparentButtonSeq[] = { /* FIXME: add */ { WM_SHOWWINDOW, sent|wparam, 1 }, { 0 } }; -/* Creation of a modal dialog (32) */ -static struct message WmCreateModalDialogSeq[] = { /* FIXME: add */ - { WM_CANCELMODE, sent|parent }, - { WM_KILLFOCUS, sent|parent }, - { WM_ENABLE, sent|parent|wparam, 0 }, - /* (window proc creation messages not tracked yet, because...) */ - { WM_SETFONT, sent }, - { WM_INITDIALOG, sent }, - /* (...the window proc message hook was installed here, IsVisible still FALSE) */ - { WM_NCACTIVATE, sent|parent|wparam, 0 }, - { WM_GETTEXT, sent|defwinproc }, - { WM_ACTIVATE, sent|parent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent }, - { WM_WINDOWPOSCHANGING, sent|parent }, - { WM_NCACTIVATE, sent|wparam, 1 }, - { WM_ACTIVATE, sent|wparam, 1 }, - /* (setting focus) */ +/* Creation of a custom dialog (32) */ +static const struct message WmCreateCustomDialogSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_GETMINMAXINFO, sent }, + { WM_NCCREATE, sent }, + { WM_NCCALCSIZE, sent|wparam, 0 }, + { WM_CREATE, sent }, { WM_SHOWWINDOW, sent|wparam, 1 }, - { WM_WINDOWPOSCHANGING, sent }, - { WM_NCPAINT, sent }, - { WM_GETTEXT, sent|defwinproc }, + { HCBT_ACTIVATE, hook }, + { WM_QUERYNEWPALETTE, sent|wparam|lparam|optional, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_ACTIVATE, sent|wparam, 1 }, + { WM_KILLFOCUS, sent|parent }, + { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 1 }, + { WM_SETFOCUS, sent }, + { WM_GETDLGCODE, sent|defwinproc|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETTEXT, sent|optional|defwinproc }, { WM_ERASEBKGND, sent }, { WM_CTLCOLORDLG, sent|defwinproc }, - { WM_WINDOWPOSCHANGED, sent }, - { WM_PAINT, sent }, - /* FIXME: (bunch of WM_CTLCOLOR* for each control) */ - { WM_PAINT, sent|parent }, - { WM_ENTERIDLE, sent|parent|wparam, 0}, - { WM_SETCURSOR, sent|parent }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_GETTEXT, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, + { WM_NCPAINT, sent|optional }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_ERASEBKGND, sent|optional }, + { WM_CTLCOLORDLG, sent|optional|defwinproc }, + { WM_SIZE, sent }, + { WM_MOVE, sent }, { 0 } }; -/* Destruction of a modal dialog (32) */ -static struct message WmDestroyModalDialogSeq[] = { /* FIXME: add */ - /* (inside dialog proc: EndDialog is called) */ - { WM_ENABLE, sent|parent|wparam, 1 }, - { WM_SETFOCUS, sent }, +/* Calling EndDialog for a custom dialog (32) */ +static const struct message WmEndCustomDialogSeq[] = { { WM_WINDOWPOSCHANGING, sent }, - { WM_NCPAINT, sent|parent }, - { WM_GETTEXT, sent|defwinproc }, - { WM_ERASEBKGND, sent|parent }, { WM_WINDOWPOSCHANGED, sent }, + { WM_GETTEXT, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { HCBT_ACTIVATE, hook }, { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETTEXT, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETICON, sent|optional|defwinproc }, + { WM_GETTEXT, sent|optional|defwinproc }, { WM_ACTIVATE, sent|wparam, 0 }, - { WM_WINDOWPOSCHANGING, sent }, - { WM_WINDOWPOSCHANGING, sent|parent }, - { WM_NCACTIVATE, sent|parent|wparam, 1 }, - { WM_GETTEXT, sent|defwinproc }, - { WM_ACTIVATE, sent|parent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { HCBT_SETFOCUS, hook }, { WM_KILLFOCUS, sent }, - { WM_SETFOCUS, sent|parent }, + { WM_IME_SETCONTEXT, sent|wparam|optional, 0 }, + { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, + { WM_SETFOCUS, sent|parent|defwinproc }, + { 0 } +}; +/* Creation and destruction of a modal dialog (32) */ +static const struct message WmModalDialogSeq[] = { + { WM_CANCELMODE, sent|parent }, + { WM_KILLFOCUS, sent|parent }, + { WM_IME_SETCONTEXT, sent|parent|wparam|optional, 0 }, + { WM_ENABLE, sent|parent|wparam, 0 }, + { WM_SETFONT, sent }, + { WM_INITDIALOG, sent }, + { WM_CHANGEUISTATE, sent|optional }, + { WM_SHOWWINDOW, sent }, + { WM_WINDOWPOSCHANGING, sent }, + { WM_NCACTIVATE, sent|wparam, 1 }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_ACTIVATE, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent }, + { WM_NCPAINT, sent }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_ERASEBKGND, sent }, + { WM_CTLCOLORDLG, sent }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|optional }, + { WM_NCPAINT, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_CTLCOLORDLG, sent|optional }, + { WM_PAINT, sent|optional }, + { WM_CTLCOLORBTN, sent }, + { WM_ENTERIDLE, sent|parent }, + { WM_TIMER, sent }, + { WM_ENABLE, sent|parent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent }, + { WM_WINDOWPOSCHANGED, sent }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { HCBT_ACTIVATE, hook }, + { WM_NCACTIVATE, sent|wparam, 0 }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_ACTIVATE, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|optional }, + { HCBT_SETFOCUS, hook }, + { WM_IME_SETCONTEXT, sent|parent|wparam|defwinproc|optional, 1 }, + { WM_SETFOCUS, sent|parent|defwinproc }, { WM_DESTROY, sent }, { WM_NCDESTROY, sent }, { 0 } }; /* Creation of a modal dialog that is resized inside WM_INITDIALOG (32) */ -static struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */ +static const struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */ /* (inside dialog proc, handling WM_INITDIALOG) */ { WM_WINDOWPOSCHANGING, sent }, { WM_NCCALCSIZE, sent }, @@ -296,37 +524,124 @@ static struct message WmCreateModalDialogResizeSeq[] = { /* FIXME: add */ { WM_SETCURSOR, sent|parent }, { 0 } }; +/* SetMenu for NonVisible windows with size change*/ +static const struct message WmSetMenuNonVisibleSizeChangeSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETICON, sent|optional }, + { WM_GETTEXT, sent|optional }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, + { 0 } +}; +/* SetMenu for NonVisible windows with no size change */ +static const struct message WmSetMenuNonVisibleNoSizeChangeSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { 0 } +}; +/* SetMenu for Visible windows with size change */ +static const struct message WmSetMenuVisibleSizeChangeSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_ACTIVATE, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { WM_MOVE, sent|defwinproc }, + { WM_SIZE, sent|defwinproc }, + { WM_NCCALCSIZE, sent|wparam|optional, 1 }, + { WM_NCPAINT, sent|wparam|optional, 1 }, + { WM_ERASEBKGND, sent|optional }, + { 0 } +}; +/* SetMenu for Visible windows with no size change */ +static const struct message WmSetMenuVisibleNoSizeChangeSeq[] = { + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_ACTIVATE, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { 0 } +}; +/* DrawMenuBar for a visible window */ +static const struct message WmDrawMenuBarSeq[] = +{ + { WM_WINDOWPOSCHANGING, sent|wparam, 0 }, + { WM_NCCALCSIZE, sent|wparam, 1 }, + { WM_NCPAINT, sent|wparam, 1 }, + { WM_GETTEXT, sent|defwinproc|optional }, + { WM_ERASEBKGND, sent|optional }, + { WM_WINDOWPOSCHANGED, sent|wparam, 0 }, + { 0 } +}; +static const struct message WmSetRedrawFalseSeq[] = +{ + { WM_SETREDRAW, sent|wparam, 0 }, + { 0 } +}; + +static const struct message WmSetRedrawTrueSeq[] = +{ + { WM_SETREDRAW, sent|wparam, 1 }, + { 0 } +}; + +static int after_end_dialog; static int sequence_cnt, sequence_size; static struct message* sequence; -static void add_message(struct message msg) +static void add_message(const struct message *msg) { if (!sequence) - sequence = malloc ( (sequence_size = 10) * sizeof (struct message) ); + { + sequence_size = 10; + sequence = HeapAlloc( GetProcessHeap(), 0, sequence_size * sizeof (struct message) ); + } if (sequence_cnt == sequence_size) - sequence = realloc ( sequence, (sequence_size *= 2) * sizeof (struct message) ); + { + sequence_size *= 2; + sequence = HeapReAlloc( GetProcessHeap(), 0, sequence, sequence_size * sizeof (struct message) ); + } assert(sequence); - sequence[sequence_cnt++] = msg; + + sequence[sequence_cnt].message = msg->message; + sequence[sequence_cnt].flags = msg->flags; + sequence[sequence_cnt].wParam = msg->wParam; + sequence[sequence_cnt].lParam = msg->lParam; + + sequence_cnt++; } static void flush_sequence() { - free(sequence); + HeapFree(GetProcessHeap(), 0, sequence); sequence = 0; sequence_cnt = sequence_size = 0; } -static void ok_sequence(struct message *expected, const char *context) +static void ok_sequence(const struct message *expected, const char *context) { - static struct message end_of_sequence = { 0, 0, 0, 0 }; - struct message *actual = sequence; + static const struct message end_of_sequence = { 0, 0, 0, 0 }; + const struct message *actual; - add_message(end_of_sequence); + add_message(&end_of_sequence); - /* naive sequence comparison. Would be nice to use a regexp engine here */ - while (expected->message || actual->message) + actual = sequence; + + while (expected->message && actual->message) { + trace("expected %04x - actual %04x\n", expected->message, actual->message); + if (expected->message == actual->message) { if (expected->flags & wparam) @@ -337,30 +652,23 @@ static void ok_sequence(struct message *expected, const char *context) ok (expected->lParam == actual->lParam, "%s: in msg 0x%04x expecting lParam 0x%lx got 0x%lx\n", context, expected->message, expected->lParam, actual->lParam); - /* FIXME: should we check defwinproc? */ + ok ((expected->flags & defwinproc) == (actual->flags & defwinproc), + "%s: the msg 0x%04x should %shave been sent by DefWindowProc\n", + context, expected->message, (expected->flags & defwinproc) ? "" : "NOT "); ok ((expected->flags & (sent|posted)) == (actual->flags & (sent|posted)), "%s: the msg 0x%04x should have been %s\n", context, expected->message, (expected->flags & posted) ? "posted" : "sent"); ok ((expected->flags & parent) == (actual->flags & parent), "%s: the msg 0x%04x was expected in %s\n", context, expected->message, (expected->flags & parent) ? "parent" : "child"); + ok ((expected->flags & hook) == (actual->flags & hook), + "%s: the msg 0x%04x should have been sent by a hook\n", + context, expected->message); expected++; actual++; } - else if (expected->message && ((expected + 1)->message == actual->message) ) - { - todo_wine { - ok (FALSE, "%s: the msg 0x%04x was not received\n", context, expected->message); + else if (expected->flags & optional) expected++; - } - } - else if (actual->message && (expected->message == (actual + 1)->message) ) - { - todo_wine { - ok (FALSE, "%s: the msg 0x%04x was not expected\n", context, actual->message); - actual++; - } - } else { todo_wine { @@ -372,31 +680,112 @@ static void ok_sequence(struct message *expected, const char *context) } } + /* skip all optional trailing messages */ + while (expected->message && (expected->flags & optional)) + expected++; + // the next test was disabled because it fails in XP - Royce3 + /*todo_wine { + if (expected->message || actual->message) + ok (FALSE, "%s: the msg sequence is not complete (got 0x%04x)\n", context, actual->message); + }*/ + flush_sequence(); } +static void test_WM_SETREDRAW(HWND hwnd) +{ + DWORD style = GetWindowLongA(hwnd, GWL_STYLE); + + flush_sequence(); + + SendMessageA(hwnd, WM_SETREDRAW, FALSE, 0); + ok_sequence(WmSetRedrawFalseSeq, "SetRedraw:FALSE"); + + ok(!(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE), "WS_VISIBLE should NOT be set\n"); + ok(!IsWindowVisible(hwnd), "IsWindowVisible() should return FALSE\n"); + + flush_sequence(); + SendMessageA(hwnd, WM_SETREDRAW, TRUE, 0); + ok_sequence(WmSetRedrawTrueSeq, "SetRedraw:TRUE"); + + ok(GetWindowLongA(hwnd, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(IsWindowVisible(hwnd), "IsWindowVisible() should return TRUE\n"); + + /* restore original WS_VISIBLE state */ + SetWindowLongA(hwnd, GWL_STYLE, style); + + flush_sequence(); +} + +static INT_PTR CALLBACK TestModalDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct message msg; + + trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + if (message == WM_INITDIALOG) SetTimer( hwnd, 1, 100, NULL ); + if (message == WM_TIMER) EndDialog( hwnd, 0 ); + return 0; +} + /* test if we receive the right sequence of messages */ static void test_messages(void) { HWND hwnd, hparent, hchild; HWND hchild2, hbutton; + HMENU hmenu; hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hwnd != 0, "Failed to create overlapped window\n"); ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped"); + + /* test WM_SETREDRAW on a not visible top level window */ + test_WM_SETREDRAW(hwnd); + + SetWindowPos(hwnd, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); + ok_sequence(WmSWP_ShowOverlappedSeq, "SetWindowPos:SWP_SHOWWINDOW:overlapped"); + ok(IsWindowVisible(hwnd), "window should be visible at this point\n"); + + ok(GetActiveWindow() == hwnd, "window should be active\n"); + ok(GetFocus() == hwnd, "window should have input focus\n"); + ShowWindow(hwnd, SW_HIDE); + ok_sequence(WmHideOverlappedSeq, "ShowWindow(SW_HIDE):overlapped"); - ShowWindow(hwnd, TRUE); - ok_sequence(WmShowOverlappedSeq, "ShowWindow:overlapped"); + ShowWindow(hwnd, SW_SHOW); + ok_sequence(WmShowOverlappedSeq, "ShowWindow(SW_SHOW):overlapped"); + + ok(GetActiveWindow() == hwnd, "window should be active\n"); + ok(GetFocus() == hwnd, "window should have input focus\n"); + SetWindowPos(hwnd, 0,0,0,0,0, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE); + ok_sequence(WmSWP_HideOverlappedSeq, "SetWindowPos:SWP_HIDEWINDOW:overlapped"); + ok(!IsWindowVisible(hwnd), "window should not be visible at this point\n"); + + /* test WM_SETREDRAW on a visible top level window */ + ShowWindow(hwnd, SW_SHOW); + test_WM_SETREDRAW(hwnd); DestroyWindow(hwnd); ok_sequence(WmDestroyOverlappedSeq, "DestroyWindow:overlapped"); - hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW, + hparent = CreateWindowExA(0, "TestParentClass", "Test parent", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 200, 200, 0, 0, 0, NULL); ok (hparent != 0, "Failed to create parent window\n"); flush_sequence(); + hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILD | WS_MAXIMIZE, + 0, 0, 10, 10, hparent, 0, 0, NULL); + ok (hchild != 0, "Failed to create child window\n"); + ok_sequence(WmCreateMaximizedChildSeq, "CreateWindow:maximized child"); + DestroyWindow(hchild); + flush_sequence(); + hchild = CreateWindowExA(0, "TestWindowClass", "Test child", WS_CHILDWINDOW, 0, 0, 10, 10, hparent, 0, 0, NULL); ok (hchild != 0, "Failed to create child window\n"); @@ -410,24 +799,247 @@ static void test_messages(void) hbutton = CreateWindowExA(0, "TestWindowClass", "Test button", WS_CHILDWINDOW, 0, 100, 50, 50, hchild, 0, 0, NULL); ok (hbutton != 0, "Failed to create button window\n"); - flush_sequence(); - ShowWindow(hchild, TRUE); + /* test WM_SETREDRAW on a not visible child window */ + test_WM_SETREDRAW(hchild); + + ShowWindow(hchild, SW_SHOW); ok_sequence(WmShowChildSeq, "ShowWindow:child"); + /* test WM_SETREDRAW on a visible child window */ + test_WM_SETREDRAW(hchild); + + SetFocus(hchild); + flush_sequence(); + MoveWindow(hchild, 10, 10, 20, 20, TRUE); ok_sequence(WmResizingChildWithMoveWindowSeq, "MoveWindow:child"); DestroyWindow(hchild); ok_sequence(WmDestroyChildSeq, "DestroyWindow:child"); + DestroyWindow(hchild2); + DestroyWindow(hbutton); + + flush_sequence(); + hchild = CreateWindowExA(0, "TestWindowClass", "Test Child Popup", WS_CHILD | WS_POPUP, + 0, 0, 100, 100, hparent, 0, 0, NULL); + ok (hchild != 0, "Failed to create child popup window\n"); + ok_sequence(WmCreateChildPopupSeq, "CreateWindow:child_popup"); + DestroyWindow(hchild); + + /* test what happens to a window which sets WS_VISIBLE in WM_CREATE */ + flush_sequence(); + hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP, + 0, 0, 100, 100, hparent, 0, 0, NULL); + ok (hchild != 0, "Failed to create popup window\n"); + ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup"); + ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); + flush_sequence(); + ShowWindow(hchild, SW_SHOW); + ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup"); + flush_sequence(); + SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); + ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2"); + flush_sequence(); + SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE); + ok_sequence(WmShowVisiblePopupSeq_3, "CreateWindow:show_visible_popup_3"); + DestroyWindow(hchild); + + /* this time add WS_VISIBLE for CreateWindowEx, but this fact actually + * changes nothing in message sequences. + */ + flush_sequence(); + hchild = CreateWindowExA(0, "TestPopupClass", "Test Popup", WS_POPUP | WS_VISIBLE, + 0, 0, 100, 100, hparent, 0, 0, NULL); + ok (hchild != 0, "Failed to create popup window\n"); + ok_sequence(WmCreateInvisiblePopupSeq, "CreateWindow:invisible_popup"); + ok(GetWindowLongA(hchild, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(IsWindowVisible(hchild), "IsWindowVisible() should return TRUE\n"); + flush_sequence(); + ShowWindow(hchild, SW_SHOW); + ok_sequence(WmShowVisiblePopupSeq, "CreateWindow:show_visible_popup"); + flush_sequence(); + SetWindowPos(hchild, 0,0,0,0,0, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); + ok_sequence(WmShowVisiblePopupSeq_2, "CreateWindow:show_visible_popup_2"); + DestroyWindow(hchild); + + flush_sequence(); + hwnd = CreateWindowExA(WS_EX_DLGMODALFRAME, "TestDialogClass", NULL, WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_DLGFRAME, + 0, 0, 100, 100, hparent, 0, 0, NULL); + ok(hwnd != 0, "Failed to create custom dialog window\n"); + ok_sequence(WmCreateCustomDialogSeq, "CreateCustomDialog"); + + flush_sequence(); + after_end_dialog = 1; + EndDialog( hwnd, 0 ); + ok_sequence(WmEndCustomDialogSeq, "EndCustomDialog"); + + DestroyWindow(hwnd); + after_end_dialog = 0; + + flush_sequence(); + DialogBoxA( 0, "TEST_DIALOG", hparent, TestModalDlgProcA ); + ok_sequence(WmModalDialogSeq, "ModalDialog"); + + DestroyWindow(hparent); + flush_sequence(); + + /* Message sequence for SetMenu */ + hmenu = CreateMenu(); + ok (hmenu != 0, "Failed to create menu\n"); + ok (InsertMenuA(hmenu, -1, MF_BYPOSITION, 0x1000, "foo"), "InsertMenu failed\n"); + hwnd = CreateWindowExA(0, "TestWindowClass", "Test overlapped", WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, hmenu, 0, NULL); + ok_sequence(WmCreateOverlappedSeq, "CreateWindow:overlapped"); + ok (SetMenu(hwnd, 0), "SetMenu\n"); + ok_sequence(WmSetMenuNonVisibleSizeChangeSeq, "SetMenu:NonVisibleSizeChange"); + ok (SetMenu(hwnd, 0), "SetMenu\n"); + ok_sequence(WmSetMenuNonVisibleNoSizeChangeSeq, "SetMenu:NonVisibleNoSizeChange"); + ShowWindow(hwnd, SW_SHOW); + flush_sequence(); + ok (SetMenu(hwnd, 0), "SetMenu\n"); + ok_sequence(WmSetMenuVisibleNoSizeChangeSeq, "SetMenu:VisibleNoSizeChange"); + ok (SetMenu(hwnd, hmenu), "SetMenu\n"); + ok_sequence(WmSetMenuVisibleSizeChangeSeq, "SetMenu:VisibleSizeChange"); + + ok(DrawMenuBar(hwnd), "DrawMenuBar\n"); + ok_sequence(WmDrawMenuBarSeq, "DrawMenuBar"); + + DestroyWindow(hwnd); } static LRESULT WINAPI MsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { - struct message msg = { message, sent|wparam|lparam, wParam, lParam }; + static long defwndproc_counter = 0; + LRESULT ret; + struct message msg; - add_message(msg); - return DefWindowProcA(hwnd, message, wParam, lParam); + trace("%p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + if (message == WM_GETMINMAXINFO && (GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) + { + HWND parent = GetParent(hwnd); + RECT rc; + MINMAXINFO *minmax = (MINMAXINFO *)lParam; + + GetClientRect(parent, &rc); + trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom); + + trace("ptReserved = (%ld,%ld)\n" + "ptMaxSize = (%ld,%ld)\n" + "ptMaxPosition = (%ld,%ld)\n" + "ptMinTrackSize = (%ld,%ld)\n" + "ptMaxTrackSize = (%ld,%ld)\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + + ok(minmax->ptMaxSize.x == rc.right, "default width of maximized child %ld != %ld\n", + minmax->ptMaxSize.x, rc.right); + ok(minmax->ptMaxSize.y == rc.bottom, "default height of maximized child %ld != %ld\n", + minmax->ptMaxSize.y, rc.bottom); + } + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; +} + +static LRESULT WINAPI PopupMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static long defwndproc_counter = 0; + LRESULT ret; + struct message msg; + + trace("popup: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + if (message == WM_CREATE) + { + DWORD style = GetWindowLongA(hwnd, GWL_STYLE) | WS_VISIBLE; + SetWindowLongA(hwnd, GWL_STYLE, style); + } + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; +} + +static LRESULT WINAPI ParentMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static long defwndproc_counter = 0; + LRESULT ret; + struct message msg; + + trace("parent: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + if (message == WM_PARENTNOTIFY || message == WM_CANCELMODE || + message == WM_SETFOCUS || message == WM_KILLFOCUS || + message == WM_ENABLE || message == WM_ENTERIDLE || + message == WM_IME_SETCONTEXT) + { + msg.message = message; + msg.flags = sent|parent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + } + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; +} + +static LRESULT WINAPI TestDlgProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static long defwndproc_counter = 0; + LRESULT ret; + struct message msg; + + trace("dialog: %p, %04x, %08x, %08lx\n", hwnd, message, wParam, lParam); + + DefDlgProcA(hwnd, DM_SETDEFID, 1, 0); + ret = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); + if (after_end_dialog) + ok( ret == 0, "DM_GETDEFID should return 0 after EndDialog, got %lx\n", ret ); + else + ok(HIWORD(ret) == DC_HASDEFID, "DM_GETDEFID should return DC_HASDEFID, got %lx\n", ret); + + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + + defwndproc_counter++; + ret = DefDlgProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + return ret; } static BOOL RegisterWindowClasses(void) @@ -444,41 +1056,64 @@ static BOOL RegisterWindowClasses(void) cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "TestWindowClass"; - if(!RegisterClassA(&cls)) return FALSE; - cls.style = 0; - cls.lpfnWndProc = DefWindowProcA; - cls.cbClsExtra = 0; - cls.cbWndExtra = 0; - cls.hInstance = GetModuleHandleA(0); - cls.hIcon = 0; - cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - cls.hbrBackground = GetStockObject(WHITE_BRUSH); - cls.lpszMenuName = NULL; + cls.lpfnWndProc = PopupMsgCheckProcA; + cls.lpszClassName = "TestPopupClass"; + if(!RegisterClassA(&cls)) return FALSE; + + cls.lpfnWndProc = ParentMsgCheckProcA; cls.lpszClassName = "TestParentClass"; - if(!RegisterClassA(&cls)) return FALSE; - cls.style = 0; cls.lpfnWndProc = DefWindowProcA; - cls.cbClsExtra = 0; - cls.cbWndExtra = 0; - cls.hInstance = GetModuleHandleA(0); - cls.hIcon = 0; - cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW); - cls.hbrBackground = GetStockObject(WHITE_BRUSH); - cls.lpszMenuName = NULL; cls.lpszClassName = "SimpleWindowClass"; + if(!RegisterClassA(&cls)) return FALSE; + ok(GetClassInfoA(0, "#32770", &cls), "GetClassInfo failed\n"); + cls.lpfnWndProc = TestDlgProcA; + cls.lpszClassName = "TestDialogClass"; if(!RegisterClassA(&cls)) return FALSE; return TRUE; } +static HHOOK hCBT_hook; + +static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) +{ + char buf[256]; + + trace("CBT: %d, %08x, %08lx\n", nCode, wParam, lParam); + + if (GetClassNameA((HWND)wParam, buf, sizeof(buf))) + { + if (!strcmp(buf, "TestWindowClass") || + !strcmp(buf, "TestParentClass") || + !strcmp(buf, "TestPopupClass") || + !strcmp(buf, "SimpleWindowClass") || + !strcmp(buf, "TestDialogClass")) + { + struct message msg; + + msg.message = nCode; + msg.flags = hook; + msg.wParam = wParam; + msg.lParam = lParam; + add_message(&msg); + } + } + return CallNextHookEx(hCBT_hook, nCode, wParam, lParam); +} + START_TEST(msg) { if (!RegisterWindowClasses()) assert(0); + hCBT_hook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); + assert(hCBT_hook); + test_messages(); + + UnhookWindowsHookEx(hCBT_hook); } diff --git a/reactos/apps/tests/user32/resource.c b/reactos/apps/tests/user32/resource.c index ef82349e34e..66b4a1de614 100644 --- a/reactos/apps/tests/user32/resource.c +++ b/reactos/apps/tests/user32/resource.c @@ -26,7 +26,7 @@ void test_LoadStringA (void) { HINSTANCE hInst = GetModuleHandle (NULL); - const char str[] = "String resource"; /* same in resource.rc */ + static const char str[] = "String resource"; /* same in resource.rc */ char buf[128]; struct string_test { int bufsiz; diff --git a/reactos/apps/tests/user32/sysparams.c b/reactos/apps/tests/user32/sysparams.c index 21dfa7fcc81..190fec695bd 100644 --- a/reactos/apps/tests/user32/sysparams.c +++ b/reactos/apps/tests/user32/sysparams.c @@ -78,6 +78,16 @@ static int strict; #define SPI_SETSHOWSOUNDS_VALNAME "On" #define SPI_SETDRAGFULLWINDOWS_REGKEY "Control Panel\\Desktop" #define SPI_SETDRAGFULLWINDOWS_VALNAME "DragFullWindows" +#define SPI_SETMOUSEHOVERWIDTH_REGKEY "Control Panel\\Mouse" +#define SPI_SETMOUSEHOVERWIDTH_VALNAME "MouseHoverWidth" +#define SPI_SETMOUSEHOVERHEIGHT_REGKEY "Control Panel\\Mouse" +#define SPI_SETMOUSEHOVERHEIGHT_VALNAME "MouseHoverHeight" +#define SPI_SETMOUSEHOVERTIME_REGKEY "Control Panel\\Mouse" +#define SPI_SETMOUSEHOVERTIME_VALNAME "MouseHoverTime" +#define SPI_SETMOUSESCROLLLINES_REGKEY "Control Panel\\Desktop" +#define SPI_SETMOUSESCROLLLINES_VALNAME "WheelScrollLines" +#define SPI_SETMENUSHOWDELAY_REGKEY "Control Panel\\Desktop" +#define SPI_SETMENUSHOWDELAY_VALNAME "MenuShowDelay" #define SPI_SETDESKWALLPAPER_REGKEY "Control Panel\\Desktop" #define SPI_SETDESKWALLPAPER_VALNAME "Wallpaper" /* FIXME - don't have access to Windows with this action (W95, NT5.0). Set real values */ @@ -1028,6 +1038,200 @@ static void test_SPI_SETSCREENREADER( void ) /* 71 */ /* TODO!!! - don't have version of Windows which has this */ } +static void test_SPI_SETMOUSEHOVERWIDTH( void ) /* 99 */ +{ + BOOL rc; + UINT old_width; + const UINT vals[]={0,32767}; + int i; + + trace("testing SPI_{GET,SET}MOUSEHOVERWIDTH\n"); + rc=SystemParametersInfoA( SPI_GETMOUSEHOVERWIDTH, 0, &old_width, 0 ); + if (rc==0 && (GetLastError()==0 || GetLastError()==ERROR_INVALID_SPI_VALUE)) + { + /* SPI_{GET,SET}MOUSEHOVERWIDTH does not seem to be supported on Win9x despite + * what MSDN states (Verified on Win98SE) + */ + trace("SPI_{GET,SET}MOUSEHOVERWIDTH not supported on this platform\n"); + return; + } + ok(rc!=0,"SystemParametersInfoA: rc=%d err=%ld\n",rc,GetLastError()); + + for (i=0;ihwnd, 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); + ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y); + } + /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */ + if (!(winpos->flags & SWP_NOSIZE) && !is_win9x) + { + ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx); + ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy); + } + break; + } + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *winpos = (WINDOWPOS *)lparam; + trace("main: WM_WINDOWPOSCHANGED\n"); + trace("%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); + + ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx); + ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy); + break; + } case WM_NCCREATE: { BOOL got_getminmaxinfo = GetWindowLongA(hwnd, GWL_USERDATA) == 0x20031021; @@ -535,6 +572,43 @@ static BOOL RegisterWindowClasses(void) return TRUE; } +static void verify_window_info(HWND hwnd, const WINDOWINFO *info, BOOL test_borders) +{ + RECT rcWindow, rcClient; + INT border; + DWORD status; + + ok(IsWindow(hwnd), "bad window handle\n"); + + GetWindowRect(hwnd, &rcWindow); + ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow\n"); + + GetClientRect(hwnd, &rcClient); + /* translate to screen coordinates */ + MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2); + ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient\n"); + + ok(info->dwStyle == GetWindowLongA(hwnd, GWL_STYLE), "wrong dwStyle\n"); + ok(info->dwExStyle == GetWindowLongA(hwnd, GWL_EXSTYLE), "wrong dwExStyle\n"); + status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0; + ok(info->dwWindowStatus == status, "wrong dwWindowStatus\n"); + + if (test_borders && !IsRectEmpty(&rcWindow)) + { + trace("rcWindow: %ld,%ld - %ld,%ld\n", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom); + trace("rcClient: %ld,%ld - %ld,%ld\n", rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); + + ok(info->cxWindowBorders == rcClient.left - rcWindow.left, + "wrong cxWindowBorders %d != %ld\n", info->cxWindowBorders, rcClient.left - rcWindow.left); + border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top); + ok(info->cyWindowBorders == border, + "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border); + } + + ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType\n"); + ok(info->wCreatorVersion == 0x0400, "wrong wCreatorVersion %04x\n", info->wCreatorVersion); +} + static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) { static const char *CBT_code_name[10] = { @@ -556,7 +630,11 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) { case HCBT_CREATEWND: { - DWORD style; +#if 0 /* Uncomment this once the test succeeds in all cases */ + static const RECT rc_null; + RECT rc; +#endif + LONG style; CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam; trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08lx\n", (HWND)wParam, createwnd->lpcs->hwndParent, createwnd->lpcs->style); @@ -567,8 +645,69 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) ok(style == GetWindowLongA((HWND)wParam, GWL_STYLE), "style of hwnd and style in the CREATESTRUCT do not match: %08lx != %08lx\n", GetWindowLongA((HWND)wParam, GWL_STYLE), style); + +#if 0 /* Uncomment this once the test succeeds in all cases */ + if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) + { + ok(GetParent((HWND)wParam) == hwndMessage, + "wrong result from GetParent %p: message window %p\n", + GetParent((HWND)wParam), hwndMessage); + } + else + ok(!GetParent((HWND)wParam), "GetParent should return 0 at this point\n"); + + ok(!GetWindow((HWND)wParam, GW_OWNER), "GW_OWNER should be set to 0 at this point\n"); +#endif +#if 0 /* while NT assigns GW_HWNDFIRST/LAST some values at this point, + * Win9x still has them set to 0. + */ + ok(GetWindow((HWND)wParam, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n"); + ok(GetWindow((HWND)wParam, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n"); +#endif + ok(!GetWindow((HWND)wParam, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n"); + ok(!GetWindow((HWND)wParam, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n"); + +#if 0 /* Uncomment this once the test succeeds in all cases */ + if (pGetAncestor) + { + ok(pGetAncestor((HWND)wParam, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n"); + ok(pGetAncestor((HWND)wParam, GA_ROOT) == (HWND)wParam, + "GA_ROOT is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOT), (HWND)wParam); + + if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) + ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == hwndMessage, + "GA_ROOTOWNER should be set to hwndMessage at this point\n"); + else + ok(pGetAncestor((HWND)wParam, GA_ROOTOWNER) == (HWND)wParam, + "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor((HWND)wParam, GA_ROOTOWNER), (HWND)wParam); + } + + ok(GetWindowRect((HWND)wParam, &rc), "GetWindowRect failed\n"); + ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n"); + ok(GetClientRect((HWND)wParam, &rc), "GetClientRect failed\n"); + ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n"); +#endif break; } + + case HCBT_DESTROYWND: + case HCBT_SETFOCUS: + if (wParam && pGetWindowInfo) + { + WINDOWINFO info; + + info.cbSize = 0; + ok(pGetWindowInfo((HWND)wParam, &info), "GetWindowInfo should not fail\n"); + /* win2k SP4 returns broken border info if GetWindowInfo + * is being called from HCBT_DESTROYWND hook proc. + */ + verify_window_info((HWND)wParam, &info, nCode != HCBT_DESTROYWND); + + info.cbSize = sizeof(WINDOWINFO) + 1; + ok(pGetWindowInfo((HWND)wParam, &info), "GetWindowInfo should not fail\n"); + verify_window_info((HWND)wParam, &info, nCode != HCBT_DESTROYWND); + } + break; } return CallNextHookEx(hhook, nCode, wParam, lParam); @@ -878,6 +1017,62 @@ static void test_MDI_create(HWND parent, HWND mdi_client) (LPVOID)mdi_lParam_test_message); ok(mdi_child != 0, "MDI child creation failed\n"); DestroyWindow(mdi_child); + + /* maximized child */ + mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", + WS_CHILD | WS_MAXIMIZE, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + mdi_client, 0, GetModuleHandle(0), + (LPVOID)mdi_lParam_test_message); + ok(mdi_child != 0, "MDI child creation failed\n"); + DestroyWindow(mdi_child); + + trace("Creating maximized child with a caption\n"); + mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", + WS_CHILD | WS_MAXIMIZE | WS_CAPTION, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + mdi_client, 0, GetModuleHandle(0), + (LPVOID)mdi_lParam_test_message); + ok(mdi_child != 0, "MDI child creation failed\n"); + DestroyWindow(mdi_child); + + trace("Creating maximized child with a caption and a thick frame\n"); + mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", + WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + mdi_client, 0, GetModuleHandle(0), + (LPVOID)mdi_lParam_test_message); + ok(mdi_child != 0, "MDI child creation failed\n"); + DestroyWindow(mdi_child); +} + +/********************************************************************** + * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c) + * + * Note: The rule here is that client rect of the maximized MDI child + * is equal to the client rect of the MDI client window. + */ +static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax ) +{ + RECT rect; + + GetClientRect( client, &rect ); + AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ), + 0, GetWindowLongA( hwnd, GWL_EXSTYLE )); + + rect.right -= rect.left; + rect.bottom -= rect.top; + lpMinMax->ptMaxSize.x = rect.right; + lpMinMax->ptMaxSize.y = rect.bottom; + + lpMinMax->ptMaxPosition.x = rect.left; + lpMinMax->ptMaxPosition.y = rect.top; + + trace("max rect (%ld,%ld - %ld, %ld)\n", + rect.left, rect.top, rect.right, rect.bottom); } static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) @@ -919,12 +1114,13 @@ static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, L if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES) { - ok(cs->style == (mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS), + LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS; + ok(cs->style == style, "cs->style does not match (%08lx)\n", cs->style); } else { - DWORD style = mdi_cs->style; + LONG style = mdi_cs->style; style &= ~WS_POPUP; style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; @@ -933,6 +1129,69 @@ static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, L } break; } + + case WM_GETMINMAXINFO: + { + HWND client = GetParent(hwnd); + RECT rc; + MINMAXINFO *minmax = (MINMAXINFO *)lparam; + MINMAXINFO my_minmax; + LONG style, exstyle; + + style = GetWindowLongA(hwnd, GWL_STYLE); + exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); + + GetWindowRect(client, &rc); + trace("MDI client %p window size = (%ld x %ld)\n", client, rc.right-rc.left, rc.bottom-rc.top); + GetClientRect(client, &rc); + trace("MDI client %p client size = (%ld x %ld)\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) + style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ + AdjustWindowRectEx(&rc, style, 0, exstyle); + trace("MDI child: calculated max window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top); + + trace("ptReserved = (%ld,%ld)\n" + "ptMaxSize = (%ld,%ld)\n" + "ptMaxPosition = (%ld,%ld)\n" + "ptMinTrackSize = (%ld,%ld)\n" + "ptMaxTrackSize = (%ld,%ld)\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + + ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n", + minmax->ptMaxSize.x, rc.right - rc.left); + ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n", + minmax->ptMaxSize.y, rc.bottom - rc.top); + + DefMDIChildProcA(hwnd, msg, wparam, lparam); + + trace("DefMDIChildProc returned:\n" + "ptReserved = (%ld,%ld)\n" + "ptMaxSize = (%ld,%ld)\n" + "ptMaxPosition = (%ld,%ld)\n" + "ptMinTrackSize = (%ld,%ld)\n" + "ptMaxTrackSize = (%ld,%ld)\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + + MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax); + ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %ld != %ld\n", + minmax->ptMaxSize.x, my_minmax.ptMaxSize.x); + ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %ld != %ld\n", + minmax->ptMaxSize.y, my_minmax.ptMaxSize.y); + + return 1; + } } return DefMDIChildProcA(hwnd, msg, wparam, lparam); } @@ -946,6 +1205,9 @@ static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, L { CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; + trace("%s\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE"); + trace("x %d, y %d, cx %d, cy %d\n", cs->x, cs->y, cs->cx, cs->cy); + ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n"); ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n"); @@ -963,6 +1225,68 @@ static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, L ok(cs->cy == 0, "%d != 0\n", cs->cy); break; } + + case WM_GETMINMAXINFO: + { + HWND parent = GetParent(hwnd); + RECT rc; + MINMAXINFO *minmax = (MINMAXINFO *)lparam; + LONG style, exstyle; + + trace("WM_GETMINMAXINFO\n"); + + style = GetWindowLongA(hwnd, GWL_STYLE); + exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); + + GetClientRect(parent, &rc); + trace("parent %p client size = (%ld x %ld)\n", parent, rc.right, rc.bottom); + + GetClientRect(parent, &rc); + if ((style & WS_CAPTION) == WS_CAPTION) + style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ + AdjustWindowRectEx(&rc, style, 0, exstyle); + trace("calculated max child window size = (%ld x %ld)\n", rc.right-rc.left, rc.bottom-rc.top); + + trace("ptReserved = (%ld,%ld)\n" + "ptMaxSize = (%ld,%ld)\n" + "ptMaxPosition = (%ld,%ld)\n" + "ptMinTrackSize = (%ld,%ld)\n" + "ptMaxTrackSize = (%ld,%ld)\n", + minmax->ptReserved.x, minmax->ptReserved.y, + minmax->ptMaxSize.x, minmax->ptMaxSize.y, + minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, + minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, + minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); + + ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %ld != %ld\n", + minmax->ptMaxSize.x, rc.right - rc.left); + ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %ld != %ld\n", + minmax->ptMaxSize.y, rc.bottom - rc.top); + break; + } + + case WM_WINDOWPOSCHANGING: + case WM_WINDOWPOSCHANGED: + { + WINDOWPOS *winpos = (WINDOWPOS *)lparam; + WINDOWPOS my_winpos = *winpos; + + trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); + trace("%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); + + DefWindowProcA(hwnd, msg, wparam, lparam); + + trace("%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(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)), + "DefWindowProc should not change WINDOWPOS values\n"); + + return 1; + } } return DefWindowProcA(hwnd, msg, wparam, lparam); } @@ -1131,9 +1455,214 @@ static void test_icons(void) ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 ); } +static void test_SetWindowPos(HWND hwnd) +{ + SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE); + SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE); + + SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE); + SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE); +} + +static void test_SetMenu(HWND parent) +{ + HWND child; + HMENU hMenu, ret; + + hMenu = CreateMenu(); + assert(hMenu); + + /* parent */ + ret = GetMenu(parent); + ok(ret == 0, "unexpected menu id %p\n", ret); + + ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n"); + ret = GetMenu(parent); + ok(ret == 0, "unexpected menu id %p\n", ret); + + ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n"); + ret = GetMenu(parent); + ok(ret == (HMENU)hMenu, "unexpected menu id %p\n", ret); + + ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n"); + ret = GetMenu(parent); + ok(ret == 0, "unexpected menu id %p\n", ret); + + /* child */ + child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL); + assert(child); + + ret = GetMenu(child); + ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); + + ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n"); + ret = GetMenu(child); + ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); + + ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n"); + ret = GetMenu(child); + ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); + + ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n"); + ret = GetMenu(child); + ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); + + DestroyWindow(child); + DestroyMenu(hMenu); +} + +static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total) +{ + HWND child[5], hwnd; + int i; + + assert(total <= 5); + + hwnd = GetWindow(parent, GW_CHILD); + ok(!hwnd, "have to start without children to perform the test\n"); + + for (i = 0; i < total; i++) + { + child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10, + parent, 0, 0, NULL); + trace("child[%d] = %p\n", i, child[i]); + ok(child[i] != 0, "CreateWindowEx failed to create child window\n"); + } + + hwnd = GetWindow(parent, GW_CHILD); + ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n"); + ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n"); + ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n"); + + for (i = 0; i < total; i++) + { + trace("hwnd[%d] = %p\n", i, hwnd); + ok(child[order[i]] == hwnd, "Z order of child #%d is wrong\n", i); + + hwnd = GetWindow(hwnd, GW_HWNDNEXT); + } + + for (i = 0; i < total; i++) + ok(DestroyWindow(child[i]), "DestroyWindow failed\n"); +} + +static void test_children_zorder(HWND parent) +{ + const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD, + WS_CHILD }; + const int simple_order[5] = { 0, 1, 2, 3, 4 }; + + const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE, + WS_CHILD | WS_VISIBLE, WS_CHILD, + WS_CHILD | WS_MAXIMIZE | WS_VISIBLE }; + const int complex_order_1[1] = { 0 }; + const int complex_order_2[2] = { 1, 0 }; + const int complex_order_3[3] = { 1, 0, 2 }; + const int complex_order_4[4] = { 1, 0, 2, 3 }; + const int complex_order_5[5] = { 4, 1, 0, 2, 3 }; + + /* simple WS_CHILD */ + test_window_tree(parent, simple_style, simple_order, 5); + + /* complex children styles */ + test_window_tree(parent, complex_style, complex_order_1, 1); + test_window_tree(parent, complex_style, complex_order_2, 2); + test_window_tree(parent, complex_style, complex_order_3, 3); + test_window_tree(parent, complex_style, complex_order_4, 4); + test_window_tree(parent, complex_style, complex_order_5, 5); +} + +static void test_SetFocus(HWND hwnd) +{ + HWND child; + + /* check if we can set focus to non-visible windows */ + + ShowWindow(hwnd, SW_SHOW); + SetFocus(0); + SetFocus(hwnd); + ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd ); + ok( GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd ); + ShowWindow(hwnd, SW_HIDE); + SetFocus(0); + SetFocus(hwnd); + ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd ); + ok( !(GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd ); + child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL); + assert(child); + SetFocus(child); + ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child ); + ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child ); + ShowWindow(child, SW_SHOW); + ok( GetWindowLong(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child ); + ok( GetFocus() == child, "Focus no longer on child %p\n", child ); + ShowWindow(child, SW_HIDE); + ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child ); + ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() ); + ShowWindow(child, SW_SHOW); + SetFocus(child); + ok( GetFocus() == child, "Focus should be on child %p\n", child ); + SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW); + ok( GetFocus() == child, "Focus should still be on child %p\n", child ); + + ShowWindow(child, SW_HIDE); + SetFocus(hwnd); + ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() ); + SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); + ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() ); + ShowWindow(child, SW_HIDE); + ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() ); + + DestroyWindow( child ); +} + +static void test_SetActiveWindow(HWND hwnd) +{ + HWND hwnd2; + + ShowWindow(hwnd, SW_SHOW); + SetActiveWindow(0); + SetActiveWindow(hwnd); + ok( GetActiveWindow() == hwnd, "Failed to set focus to visible window %p\n", hwnd ); + SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); + ok( GetActiveWindow() == hwnd, "Window %p no longer active\n", hwnd ); + SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW); + ShowWindow(hwnd, SW_HIDE); + ok( GetActiveWindow() != hwnd, "Window %p is still active\n", hwnd ); + ShowWindow(hwnd, SW_SHOW); + + hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); + ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 ); + DestroyWindow(hwnd2); + ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 ); + + hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); + ok( GetActiveWindow() == hwnd2, "Window %p is not active\n", hwnd2 ); + SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); + ok( GetActiveWindow() == hwnd2, "Window %p no longer active (%p)\n", hwnd2, GetActiveWindow() ); + DestroyWindow(hwnd2); + ok( GetActiveWindow() != hwnd2, "Window %p is still active\n", hwnd2 ); +} + START_TEST(win) { pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" ); + pGetWindowInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetWindowInfo" ); + + hwndMain = CreateWindowExA(0, "static", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, NULL); + if (hwndMain) + { + ok(!GetParent(hwndMain), "GetParent should return 0 for message only windows\n"); + if (pGetAncestor) + { + hwndMessage = pGetAncestor(hwndMain, GA_PARENT); + ok(hwndMessage != 0, "GetAncestor(GA_PARENT) should not return 0 for message only windows\n"); + trace("hwndMessage %p\n", hwndMessage); + } + DestroyWindow(hwndMain); + } + else + trace("CreateWindowExA with parent HWND_MESSAGE failed\n"); if (!RegisterWindowClasses()) assert(0); @@ -1158,6 +1687,12 @@ START_TEST(win) test_mdi(); test_icons(); + test_SetWindowPos(hwndMain); + test_SetMenu(hwndMain); + test_SetFocus(hwndMain); + test_SetActiveWindow(hwndMain); + + test_children_zorder(hwndMain); UnhookWindowsHookEx(hhook); }