user32/tests: Show that messages are not converted when function pointer is passed...
[wine.git] / dlls / user32 / tests / win.c
blob957e8a1d07d22c100e12c50716f47fdb08cfb9af
1 /*
2 * Unit tests for window handling
4 * Copyright 2002 Bill Medland
5 * Copyright 2002 Alexandre Julliard
6 * Copyright 2003 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* To get ICON_SMALL2 with the MSVC headers */
24 #define _WIN32_WINNT 0x0501
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
36 #include "wine/test.h"
38 #ifndef SPI_GETDESKWALLPAPER
39 #define SPI_GETDESKWALLPAPER 0x0073
40 #endif
42 #ifndef WM_SYSTIMER
43 #define WM_SYSTIMER 0x0118
44 #endif
46 #define LONG_PTR INT_PTR
47 #define ULONG_PTR UINT_PTR
49 void dump_region(HRGN hrgn);
51 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
52 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
53 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT);
54 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*);
55 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
56 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
57 static BOOL (WINAPI *pUpdateLayeredWindowIndirect)(HWND,const UPDATELAYEREDWINDOWINFO*);
58 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
59 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
60 static int (WINAPI *pGetWindowRgnBox)(HWND,LPRECT);
61 static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*);
62 static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout );
63 static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout );
64 static BOOL (WINAPI *pFlashWindow)( HWND hwnd, BOOL bInvert );
65 static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi );
66 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
67 static DWORD (WINAPI *pGetLayout)(HDC hdc);
68 static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn);
70 static BOOL test_lbuttondown_flag;
71 static DWORD num_gettext_msgs;
72 static DWORD num_settext_msgs;
73 static HWND hwndMessage;
74 static HWND hwndMain, hwndMain2;
75 static HHOOK hhook;
76 static BOOL app_activated, app_deactivated;
78 static const char* szAWRClass = "Winsize";
79 static HMENU hmenu;
80 static DWORD our_pid;
82 static BOOL is_win9x = FALSE;
84 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
86 static void dump_minmax_info( const MINMAXINFO *minmax )
88 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
89 minmax->ptReserved.x, minmax->ptReserved.y,
90 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
91 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
92 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
93 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
96 /* try to make sure pending X events have been processed before continuing */
97 static void flush_events( BOOL remove_messages )
99 MSG msg;
100 int diff = 200;
101 int min_timeout = 100;
102 DWORD time = GetTickCount() + diff;
104 while (diff > 0)
106 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
107 if (remove_messages)
108 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
109 diff = time - GetTickCount();
110 min_timeout = 50;
114 static BOOL wait_for_event(HANDLE event, int timeout)
116 DWORD end_time = GetTickCount() + timeout;
117 MSG msg;
119 do {
120 if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
121 return TRUE;
122 while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
123 DispatchMessageA(&msg);
124 timeout = end_time - GetTickCount();
125 }while(timeout > 0);
127 return FALSE;
130 /* check the values returned by the various parent/owner functions on a given window */
131 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
132 HWND gw_owner, HWND ga_root, HWND ga_root_owner )
134 HWND res;
136 if (pGetAncestor)
138 res = pGetAncestor( hwnd, GA_PARENT );
139 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
141 res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
142 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
143 res = GetParent( hwnd );
144 ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
145 res = GetWindow( hwnd, GW_OWNER );
146 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
147 if (pGetAncestor)
149 res = pGetAncestor( hwnd, GA_ROOT );
150 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
151 res = pGetAncestor( hwnd, GA_ROOTOWNER );
152 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
156 #define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
157 static void check_wnd_state_(const char *file, int line,
158 HWND active, HWND foreground, HWND focus, HWND capture)
160 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
161 /* only check foreground if it belongs to the current thread */
162 /* foreground can be moved to a different app pretty much at any time */
163 if (foreground && GetForegroundWindow() &&
164 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
165 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
166 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
167 ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
170 /* same as above but without capture test */
171 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
172 static void check_active_state_(const char *file, int line,
173 HWND active, HWND foreground, HWND focus)
175 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
176 /* only check foreground if it belongs to the current thread */
177 /* foreground can be moved to a different app pretty much at any time */
178 if (foreground && GetForegroundWindow() &&
179 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
180 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
181 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
184 static BOOL ignore_message( UINT message )
186 /* these are always ignored */
187 return (message >= 0xc000 ||
188 message == WM_GETICON ||
189 message == WM_GETOBJECT ||
190 message == WM_TIMER ||
191 message == WM_SYSTIMER ||
192 message == WM_TIMECHANGE ||
193 message == WM_DEVICECHANGE);
196 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
198 (*(LPINT)lParam)++;
199 trace("EnumChildProc on %p\n", hwndChild);
200 if (*(LPINT)lParam > 1) return FALSE;
201 return TRUE;
204 /* will search for the given window */
205 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam)
207 trace("EnumChildProc1 on %p\n", hwndChild);
208 if ((HWND)lParam == hwndChild) return FALSE;
209 return TRUE;
212 static HWND create_tool_window( LONG style, HWND parent )
214 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
215 0, 0, 100, 100, parent, 0, 0, NULL );
216 ok( ret != 0, "Creation failed\n" );
217 return ret;
220 /* test parent and owner values for various combinations */
221 static void test_parent_owner(void)
223 LONG style;
224 HWND test, owner, ret;
225 HWND desktop = GetDesktopWindow();
226 HWND child = create_tool_window( WS_CHILD, hwndMain );
227 INT numChildren;
229 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
231 /* child without parent, should fail */
232 SetLastError(0xdeadbeef);
233 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
234 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
235 ok( !test, "WS_CHILD without parent created\n" );
236 ok( GetLastError() == ERROR_TLW_WITH_WSCHILD ||
237 broken(GetLastError() == 0xdeadbeef), /* win9x */
238 "CreateWindowExA error %u\n", GetLastError() );
240 /* desktop window */
241 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
242 style = GetWindowLongA( desktop, GWL_STYLE );
243 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
244 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
245 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
247 /* normal child window */
248 test = create_tool_window( WS_CHILD, hwndMain );
249 trace( "created child %p\n", test );
250 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
251 SetWindowLongA( test, GWL_STYLE, 0 );
252 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
253 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
254 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
255 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
256 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
257 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
258 DestroyWindow( test );
260 /* normal child window with WS_MAXIMIZE */
261 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
262 DestroyWindow( test );
264 /* normal child window with WS_THICKFRAME */
265 test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
266 DestroyWindow( test );
268 /* popup window with WS_THICKFRAME */
269 test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
270 DestroyWindow( test );
272 /* child of desktop */
273 test = create_tool_window( WS_CHILD, desktop );
274 trace( "created child of desktop %p\n", test );
275 check_parents( test, desktop, 0, desktop, 0, test, desktop );
276 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
277 check_parents( test, desktop, 0, 0, 0, test, test );
278 SetWindowLongA( test, GWL_STYLE, 0 );
279 check_parents( test, desktop, 0, 0, 0, test, test );
280 DestroyWindow( test );
282 /* child of desktop with WS_MAXIMIZE */
283 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
284 DestroyWindow( test );
286 /* child of desktop with WS_MINIMIZE */
287 test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
288 DestroyWindow( test );
290 /* child of child */
291 test = create_tool_window( WS_CHILD, child );
292 trace( "created child of child %p\n", test );
293 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
294 SetWindowLongA( test, GWL_STYLE, 0 );
295 check_parents( test, child, child, 0, 0, hwndMain, test );
296 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
297 check_parents( test, child, child, 0, 0, hwndMain, test );
298 DestroyWindow( test );
300 /* child of child with WS_MAXIMIZE */
301 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
302 DestroyWindow( test );
304 /* child of child with WS_MINIMIZE */
305 test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
306 DestroyWindow( test );
308 /* not owned top-level window */
309 test = create_tool_window( 0, 0 );
310 trace( "created top-level %p\n", test );
311 check_parents( test, desktop, 0, 0, 0, test, test );
312 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
313 check_parents( test, desktop, 0, 0, 0, test, test );
314 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
315 check_parents( test, desktop, 0, desktop, 0, test, desktop );
316 DestroyWindow( test );
318 /* not owned top-level window with WS_MAXIMIZE */
319 test = create_tool_window( WS_MAXIMIZE, 0 );
320 DestroyWindow( test );
322 /* owned top-level window */
323 test = create_tool_window( 0, hwndMain );
324 trace( "created owned top-level %p\n", test );
325 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
326 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
327 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
328 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
329 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
330 DestroyWindow( test );
332 /* owned top-level window with WS_MAXIMIZE */
333 test = create_tool_window( WS_MAXIMIZE, hwndMain );
334 DestroyWindow( test );
336 /* not owned popup */
337 test = create_tool_window( WS_POPUP, 0 );
338 trace( "created popup %p\n", test );
339 check_parents( test, desktop, 0, 0, 0, test, test );
340 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
341 check_parents( test, desktop, 0, desktop, 0, test, desktop );
342 SetWindowLongA( test, GWL_STYLE, 0 );
343 check_parents( test, desktop, 0, 0, 0, test, test );
344 DestroyWindow( test );
346 /* not owned popup with WS_MAXIMIZE */
347 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
348 DestroyWindow( test );
350 /* owned popup */
351 test = create_tool_window( WS_POPUP, hwndMain );
352 trace( "created owned popup %p\n", test );
353 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
354 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
355 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
356 SetWindowLongA( test, GWL_STYLE, 0 );
357 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
358 DestroyWindow( test );
360 /* owned popup with WS_MAXIMIZE */
361 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
362 DestroyWindow( test );
364 /* top-level window owned by child (same as owned by top-level) */
365 test = create_tool_window( 0, child );
366 trace( "created top-level owned by child %p\n", test );
367 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
368 DestroyWindow( test );
370 /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
371 test = create_tool_window( WS_MAXIMIZE, child );
372 DestroyWindow( test );
374 /* popup owned by desktop (same as not owned) */
375 test = create_tool_window( WS_POPUP, desktop );
376 trace( "created popup owned by desktop %p\n", test );
377 check_parents( test, desktop, 0, 0, 0, test, test );
378 DestroyWindow( test );
380 /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
381 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
382 DestroyWindow( test );
384 /* popup owned by child (same as owned by top-level) */
385 test = create_tool_window( WS_POPUP, child );
386 trace( "created popup owned by child %p\n", test );
387 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
388 DestroyWindow( test );
390 /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
391 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
392 DestroyWindow( test );
394 /* not owned popup with WS_CHILD (same as WS_POPUP only) */
395 test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
396 trace( "created WS_CHILD popup %p\n", test );
397 check_parents( test, desktop, 0, 0, 0, test, test );
398 DestroyWindow( test );
400 /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
401 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
402 DestroyWindow( test );
404 /* owned popup with WS_CHILD (same as WS_POPUP only) */
405 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
406 trace( "created owned WS_CHILD popup %p\n", test );
407 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
408 DestroyWindow( test );
410 /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
411 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
412 DestroyWindow( test );
414 /******************** parent changes *************************/
415 trace( "testing parent changes\n" );
417 /* desktop window */
418 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
419 if (0)
421 /* this test succeeds on NT but crashes on win9x systems */
422 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
423 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
424 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
425 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
426 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
428 /* normal child window */
429 test = create_tool_window( WS_CHILD, hwndMain );
430 trace( "created child %p\n", test );
432 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
433 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
434 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
436 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
437 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
438 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
440 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
441 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
442 check_parents( test, desktop, 0, desktop, 0, test, desktop );
444 /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
445 if (!is_win9x)
447 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test );
448 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
449 check_parents( test, desktop, 0, desktop, 0, test, desktop );
451 else
452 win_skip("Test creates circular window tree under Win9x/WinMe\n" );
454 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
455 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
456 check_parents( test, desktop, child, desktop, child, test, desktop );
458 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
459 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
460 check_parents( test, desktop, 0, desktop, 0, test, desktop );
461 DestroyWindow( test );
463 /* not owned top-level window */
464 test = create_tool_window( 0, 0 );
465 trace( "created top-level %p\n", test );
467 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
468 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
469 check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
471 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
472 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
473 check_parents( test, desktop, child, 0, child, test, test );
475 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
476 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
477 check_parents( test, desktop, 0, 0, 0, test, test );
478 DestroyWindow( test );
480 /* not owned popup */
481 test = create_tool_window( WS_POPUP, 0 );
482 trace( "created popup %p\n", test );
484 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
485 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
486 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
488 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
489 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
490 check_parents( test, desktop, child, child, child, test, hwndMain );
492 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
493 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
494 check_parents( test, desktop, 0, 0, 0, test, test );
495 DestroyWindow( test );
497 /* normal child window */
498 test = create_tool_window( WS_CHILD, hwndMain );
499 trace( "created child %p\n", test );
501 ret = SetParent( test, desktop );
502 ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
503 check_parents( test, desktop, 0, desktop, 0, test, desktop );
505 ret = SetParent( test, child );
506 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
507 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
509 ret = SetParent( test, hwndMain2 );
510 ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
511 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
512 DestroyWindow( test );
514 /* not owned top-level window */
515 test = create_tool_window( 0, 0 );
516 trace( "created top-level %p\n", test );
518 ret = SetParent( test, child );
519 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
520 check_parents( test, child, child, 0, 0, hwndMain, test );
522 if (!is_win9x)
524 ShowWindow( test, SW_SHOW );
525 ret = SetParent( test, test );
526 ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL );
527 ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" );
528 check_parents( test, child, child, 0, 0, hwndMain, test );
530 else
531 win_skip( "Test crashes on Win9x/WinMe\n" );
532 DestroyWindow( test );
534 /* owned popup */
535 test = create_tool_window( WS_POPUP, hwndMain2 );
536 trace( "created owned popup %p\n", test );
538 ret = SetParent( test, child );
539 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
540 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
542 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
543 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
544 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
545 DestroyWindow( test );
547 /**************** test owner destruction *******************/
549 /* owned child popup */
550 owner = create_tool_window( 0, 0 );
551 test = create_tool_window( WS_POPUP, owner );
552 trace( "created owner %p and popup %p\n", owner, test );
553 ret = SetParent( test, child );
554 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
555 check_parents( test, child, child, owner, owner, hwndMain, owner );
556 /* window is now child of 'child' but owned by 'owner' */
557 DestroyWindow( owner );
558 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
559 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
560 * while Win95, Win2k, WinXP do.
562 /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
563 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
564 DestroyWindow(test);
566 /* owned top-level popup */
567 owner = create_tool_window( 0, 0 );
568 test = create_tool_window( WS_POPUP, owner );
569 trace( "created owner %p and popup %p\n", owner, test );
570 check_parents( test, desktop, owner, owner, owner, test, owner );
571 DestroyWindow( owner );
572 ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
574 /* top-level popup owned by child */
575 owner = create_tool_window( WS_CHILD, hwndMain2 );
576 test = create_tool_window( WS_POPUP, 0 );
577 trace( "created owner %p and popup %p\n", owner, test );
578 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
579 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
580 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
581 DestroyWindow( owner );
582 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
583 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
584 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
585 * while Win95, Win2k, WinXP do.
587 /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
588 DestroyWindow(test);
590 /* final cleanup */
591 DestroyWindow(child);
594 owner = create_tool_window( WS_OVERLAPPED, 0 );
595 test = create_tool_window( WS_POPUP, desktop );
597 ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
598 numChildren = 0;
599 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
600 "EnumChildWindows should have returned FALSE\n" );
601 ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
603 SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
604 ret = SetParent( test, owner );
605 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
607 numChildren = 0;
608 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
609 "EnumChildWindows should have returned TRUE\n" );
610 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
612 child = create_tool_window( WS_CHILD, owner );
613 numChildren = 0;
614 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
615 "EnumChildWindows should have returned FALSE\n" );
616 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
617 DestroyWindow( child );
619 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
620 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
621 numChildren = 0;
622 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
623 "EnumChildWindows should have returned TRUE\n" );
624 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
626 ret = SetParent( child, owner );
627 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
628 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
629 numChildren = 0;
630 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
631 "EnumChildWindows should have returned FALSE\n" );
632 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
634 ret = SetParent( child, NULL );
635 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
636 ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
637 numChildren = 0;
638 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
639 "EnumChildWindows should have returned TRUE\n" );
640 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
642 /* even GW_OWNER == owner it's still a desktop's child */
643 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
644 "EnumChildWindows should have found %p and returned FALSE\n", child );
646 DestroyWindow( child );
647 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
649 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
650 "EnumChildWindows should have found %p and returned FALSE\n", child );
652 DestroyWindow( child );
653 DestroyWindow( test );
654 DestroyWindow( owner );
656 /* Test that owner window takes into account WS_CHILD flag even if parent is set by SetParent. */
657 owner = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, desktop );
658 SetParent(owner, hwndMain);
659 check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
660 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
661 check_parents( test, desktop, owner, NULL, owner, test, test );
662 DestroyWindow( owner );
663 DestroyWindow( test );
665 owner = create_tool_window( WS_VISIBLE | WS_CHILD, desktop );
666 SetParent(owner, hwndMain);
667 check_parents( owner, hwndMain, hwndMain, hwndMain, NULL, hwndMain, hwndMain );
668 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
669 check_parents( test, desktop, hwndMain, NULL, hwndMain, test, test );
670 DestroyWindow( owner );
671 DestroyWindow( test );
673 owner = create_tool_window( WS_VISIBLE | WS_POPUP | WS_CHILD, desktop );
674 SetParent(owner, hwndMain);
675 check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner );
676 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
677 check_parents( test, desktop, owner, NULL, owner, test, test );
678 DestroyWindow( owner );
679 DestroyWindow( test );
682 static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam)
684 (*(LPINT)lParam)++;
685 if (*(LPINT)lParam > 2) return FALSE;
686 return TRUE;
688 static DWORD CALLBACK enum_thread( void *arg )
690 INT count;
691 HWND hwnd[3];
692 BOOL ret;
693 MSG msg;
695 if (pGetGUIThreadInfo)
697 GUITHREADINFO info;
698 info.cbSize = sizeof(info);
699 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
700 ok( ret || broken(!ret), /* win9x */
701 "GetGUIThreadInfo failed without message queue\n" );
702 SetLastError( 0xdeadbeef );
703 info.cbSize = sizeof(info) + 1;
704 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
705 ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" );
706 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
707 broken(GetLastError() == 0xdeadbeef), /* win9x */
708 "wrong error %u\n", GetLastError() );
711 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */
713 count = 0;
714 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
715 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
716 ok( count == 0, "count should be 0 got %d\n", count );
718 hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP,
719 0, 0, 100, 100, 0, 0, 0, NULL );
720 count = 0;
721 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
722 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
723 if (count != 2) /* Vista gives us two windows for the price of one */
725 ok( count == 1, "count should be 1 got %d\n", count );
726 hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP,
727 0, 0, 100, 100, 0, 0, 0, NULL );
729 else hwnd[2] = 0;
731 hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP,
732 0, 0, 100, 100, 0, 0, 0, NULL );
733 count = 0;
734 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
735 ok( !ret, "EnumThreadWindows should have returned FALSE\n" );
736 ok( count == 3, "count should be 3 got %d\n", count );
738 if (hwnd[2]) DestroyWindow(hwnd[2]);
739 DestroyWindow(hwnd[1]);
740 DestroyWindow(hwnd[0]);
741 return 0;
744 /* test EnumThreadWindows in a separate thread */
745 static void test_enum_thread_windows(void)
747 DWORD id;
748 HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id );
749 ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" );
750 CloseHandle( handle );
753 static struct wm_gettext_override_data
755 BOOL enabled; /* when 1 bypasses default procedure */
756 char *buff; /* expected text buffer pointer */
757 WCHAR *buffW; /* same, for W test */
758 } g_wm_gettext_override;
760 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
762 switch (msg)
764 case WM_GETMINMAXINFO:
766 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
767 break;
769 case WM_WINDOWPOSCHANGING:
771 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
772 if (!(winpos->flags & SWP_NOMOVE))
774 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
775 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
777 /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
778 if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
780 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
781 winpos->cx == 32768, /* win7 doesn't truncate */
782 "bad winpos->cx %d\n", winpos->cx);
783 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
784 winpos->cy == 40000, /* win7 doesn't truncate */
785 "bad winpos->cy %d\n", winpos->cy);
787 break;
789 case WM_WINDOWPOSCHANGED:
791 RECT rc1, rc2;
792 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
793 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
794 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
796 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
797 winpos->cx == 32768, /* win7 doesn't truncate */
798 "bad winpos->cx %d\n", winpos->cx);
799 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
800 winpos->cy == 40000, /* win7 doesn't truncate */
801 "bad winpos->cy %d\n", winpos->cy);
803 GetWindowRect(hwnd, &rc1);
804 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
805 /* note: winpos coordinates are relative to parent */
806 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
807 if (0)
809 /* Uncomment this once the test succeeds in all cases */
810 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
811 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
813 GetClientRect(hwnd, &rc2);
814 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
815 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
816 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
817 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
819 break;
821 case WM_NCCREATE:
823 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
824 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
826 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
827 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
828 else
829 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
830 break;
832 case WM_COMMAND:
833 if (test_lbuttondown_flag)
835 ShowWindow((HWND)wparam, SW_SHOW);
836 flush_events( FALSE );
838 break;
839 case WM_GETTEXT:
840 num_gettext_msgs++;
841 if (g_wm_gettext_override.enabled)
843 char *text = (char*)lparam;
844 ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text);
845 ok(*text == 0, "expected empty string buffer %x\n", *text);
846 return 0;
848 break;
849 case WM_SETTEXT:
850 num_settext_msgs++;
851 break;
852 case WM_ACTIVATEAPP:
853 if (wparam) app_activated = TRUE;
854 else app_deactivated = TRUE;
855 break;
858 return DefWindowProcA(hwnd, msg, wparam, lparam);
861 static LRESULT WINAPI main_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
863 switch (msg)
865 case WM_GETTEXT:
866 num_gettext_msgs++;
867 if (g_wm_gettext_override.enabled)
869 WCHAR *text = (WCHAR*)lparam;
870 ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text);
871 ok(*text == 0, "expected empty string buffer %x\n", *text);
872 return 0;
874 break;
877 return DefWindowProcA(hwnd, msg, wparam, lparam);
880 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
882 switch (msg)
884 case WM_GETMINMAXINFO:
886 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
887 break;
889 case WM_NCCREATE:
891 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
892 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
894 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
895 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
896 else
897 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
898 break;
902 return DefWindowProcA(hwnd, msg, wparam, lparam);
905 static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0};
907 static BOOL RegisterWindowClasses(void)
909 WNDCLASSW clsW;
910 WNDCLASSA cls;
912 cls.style = CS_DBLCLKS;
913 cls.lpfnWndProc = main_window_procA;
914 cls.cbClsExtra = 0;
915 cls.cbWndExtra = 0;
916 cls.hInstance = GetModuleHandleA(0);
917 cls.hIcon = 0;
918 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
919 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
920 cls.lpszMenuName = NULL;
921 cls.lpszClassName = "MainWindowClass";
923 if(!RegisterClassA(&cls)) return FALSE;
925 clsW.style = CS_DBLCLKS;
926 clsW.lpfnWndProc = main_window_procW;
927 clsW.cbClsExtra = 0;
928 clsW.cbWndExtra = 0;
929 clsW.hInstance = GetModuleHandleA(0);
930 clsW.hIcon = 0;
931 clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
932 clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
933 clsW.lpszMenuName = NULL;
934 clsW.lpszClassName = mainclassW;
936 if(!RegisterClassW(&clsW)) return FALSE;
938 cls.style = 0;
939 cls.lpfnWndProc = tool_window_procA;
940 cls.cbClsExtra = 0;
941 cls.cbWndExtra = 0;
942 cls.hInstance = GetModuleHandleA(0);
943 cls.hIcon = 0;
944 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
945 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
946 cls.lpszMenuName = NULL;
947 cls.lpszClassName = "ToolWindowClass";
949 if(!RegisterClassA(&cls)) return FALSE;
951 return TRUE;
954 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info)
956 RECT rcWindow, rcClient;
957 DWORD status;
959 ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook);
961 GetWindowRect(hwnd, &rcWindow);
962 ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook);
964 GetClientRect(hwnd, &rcClient);
965 /* translate to screen coordinates */
966 MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
967 ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook);
969 ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
970 "wrong dwStyle: %08x != %08x for %p in hook %s\n",
971 info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook);
972 /* Windows reports some undocumented exstyles in WINDOWINFO, but
973 * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE).
975 ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
976 "wrong dwExStyle: %08x != %08x for %p in hook %s\n",
977 info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook);
978 status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
979 if (GetForegroundWindow())
980 ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n",
981 info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook);
983 /* win2k and XP return broken border info in GetWindowInfo most of
984 * the time, so there is no point in testing it.
986 if (0)
988 UINT border;
989 ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
990 "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
991 border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
992 ok(info->cyWindowBorders == border,
993 "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
995 ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n",
996 hwnd, hook);
997 ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
998 info->wCreatorVersion == 0x0500 /* Vista */,
999 "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
1002 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
1004 AdjustWindowRectEx(rc, style, menu, exstyle);
1005 /* AdjustWindowRectEx does not include scroll bars */
1006 if (style & WS_VSCROLL)
1008 if(exstyle & WS_EX_LEFTSCROLLBAR)
1009 rc->left -= GetSystemMetrics(SM_CXVSCROLL);
1010 else
1011 rc->right += GetSystemMetrics(SM_CXVSCROLL);
1013 if (style & WS_HSCROLL)
1014 rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
1017 /* reimplement it to check that the Wine algorithm gives the correct result */
1018 static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle )
1020 int adjust;
1022 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
1023 WS_EX_STATICEDGE)
1025 adjust = 1; /* for the outer frame always present */
1027 else
1029 adjust = 0;
1030 if ((exStyle & WS_EX_DLGMODALFRAME) ||
1031 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
1033 if (style & WS_THICKFRAME)
1034 adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */
1035 if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1036 (exStyle & WS_EX_DLGMODALFRAME))
1037 adjust++; /* The other border */
1039 InflateRect (rect, adjust, adjust);
1041 if ((style & WS_CAPTION) == WS_CAPTION)
1043 if (exStyle & WS_EX_TOOLWINDOW)
1044 rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
1045 else
1046 rect->top -= GetSystemMetrics(SM_CYCAPTION);
1048 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
1050 if (exStyle & WS_EX_CLIENTEDGE)
1051 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
1053 if (style & WS_VSCROLL)
1055 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
1056 rect->left -= GetSystemMetrics(SM_CXVSCROLL);
1057 else
1058 rect->right += GetSystemMetrics(SM_CXVSCROLL);
1060 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
1063 static void test_nonclient_area(HWND hwnd)
1065 DWORD style, exstyle;
1066 RECT rc_window, rc_client, rc;
1067 BOOL menu;
1068 LRESULT ret;
1070 style = GetWindowLongA(hwnd, GWL_STYLE);
1071 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1072 menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
1074 GetWindowRect(hwnd, &rc_window);
1075 GetClientRect(hwnd, &rc_client);
1077 /* avoid some cases when things go wrong */
1078 if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
1079 rc_window.right > 32768 || rc_window.bottom > 32768) return;
1081 CopyRect(&rc, &rc_client);
1082 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1083 FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
1085 ok(EqualRect(&rc, &rc_window),
1086 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1087 style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
1088 rc.left, rc.top, rc.right, rc.bottom);
1090 CopyRect(&rc, &rc_client);
1091 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1092 wine_AdjustWindowRectEx(&rc, style, menu, exstyle);
1093 ok(EqualRect(&rc, &rc_window),
1094 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1095 style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
1096 rc.left, rc.top, rc.right, rc.bottom);
1099 CopyRect(&rc, &rc_window);
1100 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1101 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1102 ok(EqualRect(&rc, &rc_client),
1103 "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1104 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
1105 rc.left, rc.top, rc.right, rc.bottom);
1107 /* NULL rectangle shouldn't crash */
1108 ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0);
1109 ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
1111 /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
1112 if (is_win9x)
1113 return;
1115 /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
1116 SetRect(&rc_client, 0, 0, 250, 150);
1117 CopyRect(&rc_window, &rc_client);
1118 MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
1119 FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
1121 CopyRect(&rc, &rc_window);
1122 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1123 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1124 ok(EqualRect(&rc, &rc_client),
1125 "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1126 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
1127 rc.left, rc.top, rc.right, rc.bottom);
1130 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
1132 static const char *CBT_code_name[10] = {
1133 "HCBT_MOVESIZE",
1134 "HCBT_MINMAX",
1135 "HCBT_QS",
1136 "HCBT_CREATEWND",
1137 "HCBT_DESTROYWND",
1138 "HCBT_ACTIVATE",
1139 "HCBT_CLICKSKIPPED",
1140 "HCBT_KEYSKIPPED",
1141 "HCBT_SYSCOMMAND",
1142 "HCBT_SETFOCUS" };
1143 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
1144 HWND hwnd = (HWND)wParam;
1146 switch (nCode)
1148 case HCBT_CREATEWND:
1150 static const RECT rc_null;
1151 RECT rc;
1152 LONG style;
1153 CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1154 ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1156 if (pGetWindowInfo)
1158 WINDOWINFO info;
1159 info.cbSize = sizeof(WINDOWINFO);
1160 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1161 verify_window_info(code_name, hwnd, &info);
1164 /* WS_VISIBLE should be turned off yet */
1165 style = createwnd->lpcs->style & ~WS_VISIBLE;
1166 ok(style == GetWindowLongA(hwnd, GWL_STYLE),
1167 "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1168 GetWindowLongA(hwnd, GWL_STYLE), style);
1170 if (0)
1172 /* Uncomment this once the test succeeds in all cases */
1173 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1175 ok(GetParent(hwnd) == hwndMessage,
1176 "wrong result from GetParent %p: message window %p\n",
1177 GetParent(hwnd), hwndMessage);
1179 else
1180 ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1182 ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1184 if (0)
1186 /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1187 * Win9x still has them set to 0.
1189 ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1190 ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1192 ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1193 ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1195 if (0)
1197 /* Uncomment this once the test succeeds in all cases */
1198 if (pGetAncestor)
1200 ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1201 ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1202 "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1204 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1205 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1206 "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1207 else
1208 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1209 "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1212 ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1213 ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1214 ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1215 ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1217 break;
1219 case HCBT_MOVESIZE:
1220 case HCBT_MINMAX:
1221 case HCBT_ACTIVATE:
1222 if (pGetWindowInfo && IsWindow(hwnd))
1224 WINDOWINFO info;
1226 /* Win98 actually does check the info.cbSize and doesn't allow
1227 * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1228 * WinXP do not check it at all.
1230 info.cbSize = sizeof(WINDOWINFO);
1231 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1232 verify_window_info(code_name, hwnd, &info);
1234 break;
1235 /* window state is undefined */
1236 case HCBT_SETFOCUS:
1237 case HCBT_DESTROYWND:
1238 break;
1239 default:
1240 break;
1243 return CallNextHookEx(hhook, nCode, wParam, lParam);
1246 static void test_shell_window(void)
1248 BOOL ret;
1249 DWORD error;
1250 HMODULE hinst, hUser32;
1251 BOOL (WINAPI*SetShellWindow)(HWND);
1252 HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1253 HWND shellWindow, nextWnd;
1255 if (is_win9x)
1257 win_skip("Skipping shell window test on Win9x\n");
1258 return;
1261 shellWindow = GetShellWindow();
1262 hinst = GetModuleHandleA(NULL);
1263 hUser32 = GetModuleHandleA("user32");
1265 SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1267 trace("previous shell window: %p\n", shellWindow);
1269 if (shellWindow) {
1270 DWORD pid;
1271 HANDLE hProcess;
1273 GetWindowThreadProcessId(shellWindow, &pid);
1274 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
1275 if (!hProcess)
1277 skip( "cannot get access to shell process\n" );
1278 return;
1281 SetLastError(0xdeadbeef);
1282 ret = DestroyWindow(shellWindow);
1283 error = GetLastError();
1285 ok(!ret, "DestroyWindow(shellWindow)\n");
1286 /* passes on Win XP, but not on Win98 */
1287 ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1288 "got %u after DestroyWindow(shellWindow)\n", error);
1290 /* close old shell instance */
1291 ret = TerminateProcess(hProcess, 0);
1292 ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1293 WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
1294 CloseHandle(hProcess);
1297 hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1298 trace("created window 1: %p\n", hwnd1);
1300 ret = SetShellWindow(hwnd1);
1301 ok(ret, "first call to SetShellWindow(hwnd1)\n");
1302 shellWindow = GetShellWindow();
1303 ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1305 ret = SetShellWindow(hwnd1);
1306 ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1308 ret = SetShellWindow(0);
1309 error = GetLastError();
1310 /* passes on Win XP, but not on Win98
1311 ok(!ret, "reset shell window by SetShellWindow(0)\n");
1312 ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1314 ret = SetShellWindow(hwnd1);
1315 /* passes on Win XP, but not on Win98
1316 ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1318 SetWindowLongA(hwnd1, GWL_EXSTYLE, GetWindowLongA(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
1319 ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
1320 ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1322 ret = DestroyWindow(hwnd1);
1323 ok(ret, "DestroyWindow(hwnd1)\n");
1325 hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1326 trace("created window 2: %p\n", hwnd2);
1327 ret = SetShellWindow(hwnd2);
1328 ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1330 hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1331 trace("created window 3: %p\n", hwnd3);
1333 hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1334 trace("created window 4: %p\n", hwnd4);
1336 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1337 ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1339 ret = SetShellWindow(hwnd4);
1340 ok(ret, "SetShellWindow(hwnd4)\n");
1341 shellWindow = GetShellWindow();
1342 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1344 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1345 ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1347 ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1348 ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1350 ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1351 ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1353 ret = SetShellWindow(hwnd3);
1354 ok(!ret, "SetShellWindow(hwnd3)\n");
1355 shellWindow = GetShellWindow();
1356 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1358 hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1359 trace("created window 5: %p\n", hwnd5);
1360 ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1361 ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1363 todo_wine
1365 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1366 ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1369 /* destroy test windows */
1370 DestroyWindow(hwnd2);
1371 DestroyWindow(hwnd3);
1372 DestroyWindow(hwnd4);
1373 DestroyWindow(hwnd5);
1376 /************** MDI test ****************/
1378 static char mdi_lParam_test_message[] = "just a test string";
1380 static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id)
1382 MDICREATESTRUCTA mdi_cs;
1383 HWND mdi_child, hwnd, exp_hwnd;
1384 INT_PTR id;
1385 static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1386 static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1387 BOOL isWin9x = FALSE;
1389 mdi_cs.szClass = "MDI_child_Class_1";
1390 mdi_cs.szTitle = "MDI child";
1391 mdi_cs.hOwner = GetModuleHandleA(NULL);
1392 mdi_cs.x = CW_USEDEFAULT;
1393 mdi_cs.y = CW_USEDEFAULT;
1394 mdi_cs.cx = CW_USEDEFAULT;
1395 mdi_cs.cy = CW_USEDEFAULT;
1396 mdi_cs.style = 0;
1397 mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
1398 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1399 ok(mdi_child != 0, "MDI child creation failed\n");
1400 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1401 ok(id == first_id, "wrong child id %ld\n", id);
1402 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1403 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1404 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1405 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1406 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1408 mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1409 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1410 ok(mdi_child != 0, "MDI child creation failed\n");
1411 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1412 ok(id == first_id, "wrong child id %ld\n", id);
1413 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1414 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1415 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1416 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1418 mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1419 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1420 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1422 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1424 else
1426 ok(mdi_child != 0, "MDI child creation failed\n");
1427 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1428 ok(id == first_id, "wrong child id %ld\n", id);
1429 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1430 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1431 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1432 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1435 /* test MDICREATESTRUCT A<->W mapping */
1436 /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1437 mdi_cs.style = 0;
1438 mdi_cs.szClass = (LPCSTR)classW;
1439 mdi_cs.szTitle = (LPCSTR)titleW;
1440 SetLastError(0xdeadbeef);
1441 mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1442 if (!mdi_child)
1444 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1445 isWin9x = TRUE;
1446 else
1447 ok(mdi_child != 0, "MDI child creation failed\n");
1449 else
1451 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1452 ok(id == first_id, "wrong child id %ld\n", id);
1453 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1454 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1455 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1456 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1457 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1460 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1462 CW_USEDEFAULT, CW_USEDEFAULT,
1463 CW_USEDEFAULT, CW_USEDEFAULT,
1464 mdi_client, GetModuleHandleA(NULL),
1465 (LPARAM)mdi_lParam_test_message);
1466 ok(mdi_child != 0, "MDI child creation failed\n");
1467 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1468 ok(id == first_id, "wrong child id %ld\n", id);
1469 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1470 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1471 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1472 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1473 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1475 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1476 0x7fffffff, /* without WS_POPUP */
1477 CW_USEDEFAULT, CW_USEDEFAULT,
1478 CW_USEDEFAULT, CW_USEDEFAULT,
1479 mdi_client, GetModuleHandleA(NULL),
1480 (LPARAM)mdi_lParam_test_message);
1481 ok(mdi_child != 0, "MDI child creation failed\n");
1482 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1483 ok(id == first_id, "wrong child id %ld\n", id);
1484 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1485 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1486 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1487 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1489 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1490 0xffffffff, /* with WS_POPUP */
1491 CW_USEDEFAULT, CW_USEDEFAULT,
1492 CW_USEDEFAULT, CW_USEDEFAULT,
1493 mdi_client, GetModuleHandleA(NULL),
1494 (LPARAM)mdi_lParam_test_message);
1495 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1497 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1499 else
1501 ok(mdi_child != 0, "MDI child creation failed\n");
1502 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1503 ok(id == first_id, "wrong child id %ld\n", id);
1504 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1505 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1506 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1507 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1510 /* test MDICREATESTRUCT A<->W mapping */
1511 SetLastError(0xdeadbeef);
1512 mdi_child = CreateMDIWindowW(classW, titleW,
1514 CW_USEDEFAULT, CW_USEDEFAULT,
1515 CW_USEDEFAULT, CW_USEDEFAULT,
1516 mdi_client, GetModuleHandleA(NULL),
1517 (LPARAM)mdi_lParam_test_message);
1518 if (!mdi_child)
1520 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1521 isWin9x = TRUE;
1522 else
1523 ok(mdi_child != 0, "MDI child creation failed\n");
1525 else
1527 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1528 ok(id == first_id, "wrong child id %ld\n", id);
1529 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1530 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1531 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1532 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1533 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1536 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1538 CW_USEDEFAULT, CW_USEDEFAULT,
1539 CW_USEDEFAULT, CW_USEDEFAULT,
1540 mdi_client, 0, GetModuleHandleA(NULL),
1541 mdi_lParam_test_message);
1542 ok(mdi_child != 0, "MDI child creation failed\n");
1543 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1544 ok(id == first_id, "wrong child id %ld\n", id);
1545 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1546 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1547 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1548 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1549 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1551 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1552 0x7fffffff, /* without WS_POPUP */
1553 CW_USEDEFAULT, CW_USEDEFAULT,
1554 CW_USEDEFAULT, CW_USEDEFAULT,
1555 mdi_client, 0, GetModuleHandleA(NULL),
1556 mdi_lParam_test_message);
1557 ok(mdi_child != 0, "MDI child creation failed\n");
1558 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1559 ok(id == first_id, "wrong child id %ld\n", id);
1560 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1561 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1562 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1563 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1565 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1566 0xffffffff, /* with WS_POPUP */
1567 CW_USEDEFAULT, CW_USEDEFAULT,
1568 CW_USEDEFAULT, CW_USEDEFAULT,
1569 mdi_client, 0, GetModuleHandleA(NULL),
1570 mdi_lParam_test_message);
1571 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1573 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1575 else
1577 ok(mdi_child != 0, "MDI child creation failed\n");
1578 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1579 ok(id == first_id, "wrong child id %ld\n", id);
1580 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1581 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1582 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1583 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1586 /* test MDICREATESTRUCT A<->W mapping */
1587 SetLastError(0xdeadbeef);
1588 mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
1590 CW_USEDEFAULT, CW_USEDEFAULT,
1591 CW_USEDEFAULT, CW_USEDEFAULT,
1592 mdi_client, 0, GetModuleHandleA(NULL),
1593 mdi_lParam_test_message);
1594 if (!mdi_child)
1596 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1597 isWin9x = TRUE;
1598 else
1599 ok(mdi_child != 0, "MDI child creation failed\n");
1601 else
1603 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1604 ok(id == first_id, "wrong child id %ld\n", id);
1605 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1606 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1607 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1608 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1609 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1612 /* This test fails on Win9x */
1613 if (!isWin9x)
1615 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1616 WS_CHILD,
1617 CW_USEDEFAULT, CW_USEDEFAULT,
1618 CW_USEDEFAULT, CW_USEDEFAULT,
1619 parent, 0, GetModuleHandleA(NULL),
1620 mdi_lParam_test_message);
1621 ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1624 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1625 WS_CHILD, /* without WS_POPUP */
1626 CW_USEDEFAULT, CW_USEDEFAULT,
1627 CW_USEDEFAULT, CW_USEDEFAULT,
1628 mdi_client, 0, GetModuleHandleA(NULL),
1629 mdi_lParam_test_message);
1630 ok(mdi_child != 0, "MDI child creation failed\n");
1631 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1632 ok(id == 0, "wrong child id %ld\n", id);
1633 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1634 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1635 DestroyWindow(mdi_child);
1637 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1638 WS_CHILD | WS_POPUP, /* with WS_POPUP */
1639 CW_USEDEFAULT, CW_USEDEFAULT,
1640 CW_USEDEFAULT, CW_USEDEFAULT,
1641 mdi_client, 0, GetModuleHandleA(NULL),
1642 mdi_lParam_test_message);
1643 ok(mdi_child != 0, "MDI child creation failed\n");
1644 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1645 ok(id == 0, "wrong child id %ld\n", id);
1646 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1647 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1648 DestroyWindow(mdi_child);
1650 /* maximized child */
1651 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1652 WS_CHILD | WS_MAXIMIZE,
1653 CW_USEDEFAULT, CW_USEDEFAULT,
1654 CW_USEDEFAULT, CW_USEDEFAULT,
1655 mdi_client, 0, GetModuleHandleA(NULL),
1656 mdi_lParam_test_message);
1657 ok(mdi_child != 0, "MDI child creation failed\n");
1658 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1659 ok(id == 0, "wrong child id %ld\n", id);
1660 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1661 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1662 DestroyWindow(mdi_child);
1664 trace("Creating maximized child with a caption\n");
1665 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1666 WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
1667 CW_USEDEFAULT, CW_USEDEFAULT,
1668 CW_USEDEFAULT, CW_USEDEFAULT,
1669 mdi_client, 0, GetModuleHandleA(NULL),
1670 mdi_lParam_test_message);
1671 ok(mdi_child != 0, "MDI child creation failed\n");
1672 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1673 ok(id == 0, "wrong child id %ld\n", id);
1674 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1675 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1676 DestroyWindow(mdi_child);
1678 trace("Creating maximized child with a caption and a thick frame\n");
1679 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1680 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
1681 CW_USEDEFAULT, CW_USEDEFAULT,
1682 CW_USEDEFAULT, CW_USEDEFAULT,
1683 mdi_client, 0, GetModuleHandleA(NULL),
1684 mdi_lParam_test_message);
1685 ok(mdi_child != 0, "MDI child creation failed\n");
1686 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1687 ok(id == 0, "wrong child id %ld\n", id);
1688 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1689 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1690 DestroyWindow(mdi_child);
1693 static void test_MDI_child_stack(HWND mdi_client)
1695 HWND child_1, child_2, child_3, child_4;
1696 HWND stack[4];
1697 MDICREATESTRUCTA cs;
1699 cs.szClass = "MDI_child_Class_1";
1700 cs.szTitle = "MDI child";
1701 cs.hOwner = GetModuleHandleA(0);
1702 cs.x = CW_USEDEFAULT;
1703 cs.y = CW_USEDEFAULT;
1704 cs.cx = CW_USEDEFAULT;
1705 cs.cy = CW_USEDEFAULT;
1706 cs.style = 0;
1707 cs.lParam = (LPARAM)mdi_lParam_test_message;
1709 child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1710 ok(child_1 != 0, "expected child_1 to be non NULL\n");
1711 child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1712 ok(child_2 != 0, "expected child_2 to be non NULL\n");
1713 child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1714 ok(child_3 != 0, "expected child_3 to be non NULL\n");
1715 child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1716 ok(child_4 != 0, "expected child_4 to be non NULL\n");
1718 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1719 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1720 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1721 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1722 trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]);
1723 ok(stack[0] == child_4 && stack[1] == child_3 &&
1724 stack[2] == child_2 && stack[3] == child_1,
1725 "Unexpected initial order, should be: %p->%p->%p->%p\n",
1726 child_4, child_3, child_2, child_1);
1728 trace("Activate child next to %p\n", child_3);
1729 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0);
1731 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1732 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1733 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1734 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1735 ok(stack[0] == child_2 && stack[1] == child_4 &&
1736 stack[2] == child_1 && stack[3] == child_3,
1737 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1738 child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1740 trace("Activate child previous to %p\n", child_1);
1741 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1);
1743 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1744 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1745 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1746 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1747 ok(stack[0] == child_4 && stack[1] == child_2 &&
1748 stack[2] == child_1 && stack[3] == child_3,
1749 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1750 child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1752 DestroyWindow(child_1);
1753 DestroyWindow(child_2);
1754 DestroyWindow(child_3);
1755 DestroyWindow(child_4);
1758 /**********************************************************************
1759 * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1761 * Note: The rule here is that client rect of the maximized MDI child
1762 * is equal to the client rect of the MDI client window.
1764 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
1766 RECT rect;
1768 GetClientRect( client, &rect );
1769 AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
1770 0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
1772 rect.right -= rect.left;
1773 rect.bottom -= rect.top;
1774 lpMinMax->ptMaxSize.x = rect.right;
1775 lpMinMax->ptMaxSize.y = rect.bottom;
1777 lpMinMax->ptMaxPosition.x = rect.left;
1778 lpMinMax->ptMaxPosition.y = rect.top;
1780 trace("max rect (%d,%d - %d, %d)\n",
1781 rect.left, rect.top, rect.right, rect.bottom);
1784 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1786 switch (msg)
1788 case WM_NCCREATE:
1789 case WM_CREATE:
1791 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1792 MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1794 ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1795 ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1797 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1798 ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1799 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1800 ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1801 ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1803 /* MDICREATESTRUCT should have original values */
1804 ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
1805 "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1806 ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1807 ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1808 ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1809 ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1811 /* CREATESTRUCT should have fixed values */
1812 ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1813 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1815 /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1816 ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1817 ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1819 ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1821 if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1823 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1824 ok(cs->style == style,
1825 "cs->style does not match (%08x)\n", cs->style);
1827 else
1829 LONG style = mdi_cs->style;
1830 style &= ~WS_POPUP;
1831 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1832 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1833 ok(cs->style == style,
1834 "cs->style does not match (%08x)\n", cs->style);
1836 break;
1839 case WM_GETMINMAXINFO:
1841 HWND client = GetParent(hwnd);
1842 RECT rc;
1843 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1844 MINMAXINFO my_minmax;
1845 LONG style, exstyle;
1847 style = GetWindowLongA(hwnd, GWL_STYLE);
1848 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1850 GetClientRect(client, &rc);
1852 GetClientRect(client, &rc);
1853 if ((style & WS_CAPTION) == WS_CAPTION)
1854 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1855 AdjustWindowRectEx(&rc, style, 0, exstyle);
1856 trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1857 dump_minmax_info( minmax );
1859 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1860 minmax->ptMaxSize.x, rc.right - rc.left);
1861 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1862 minmax->ptMaxSize.y, rc.bottom - rc.top);
1864 DefMDIChildProcA(hwnd, msg, wparam, lparam);
1866 trace("DefMDIChildProc returned:\n");
1867 dump_minmax_info( minmax );
1869 MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1870 ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1871 minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1872 ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1873 minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1875 return 1;
1878 case WM_MDIACTIVATE:
1880 HWND active, client = GetParent(hwnd);
1881 /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1882 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1883 if (hwnd == (HWND)lparam) /* if we are being activated */
1884 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1885 else
1886 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1887 break;
1890 return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1893 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1895 switch (msg)
1897 case WM_NCCREATE:
1898 case WM_CREATE:
1900 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1902 trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1903 cs->x, cs->y, cs->cx, cs->cy);
1905 ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1906 ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1908 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1909 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1911 /* CREATESTRUCT should have fixed values */
1912 /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1913 while NT does. */
1914 /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1915 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1917 /* cx/cy == CW_USEDEFAULT are translated to 0 */
1918 /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1919 while Win95, Win2k, WinXP do. */
1920 /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1921 ok(cs->cy == 0, "%d != 0\n", cs->cy);
1922 break;
1925 case WM_GETMINMAXINFO:
1927 HWND parent = GetParent(hwnd);
1928 RECT rc;
1929 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1930 LONG style, exstyle;
1932 style = GetWindowLongA(hwnd, GWL_STYLE);
1933 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1935 GetClientRect(parent, &rc);
1936 trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1938 GetClientRect(parent, &rc);
1939 if ((style & WS_CAPTION) == WS_CAPTION)
1940 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1941 AdjustWindowRectEx(&rc, style, 0, exstyle);
1942 dump_minmax_info( minmax );
1944 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1945 minmax->ptMaxSize.x, rc.right - rc.left);
1946 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1947 minmax->ptMaxSize.y, rc.bottom - rc.top);
1948 break;
1951 case WM_WINDOWPOSCHANGED:
1953 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1954 RECT rc1, rc2;
1956 GetWindowRect(hwnd, &rc1);
1957 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1958 /* note: winpos coordinates are relative to parent */
1959 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1960 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) pos=(%d,%d)-(%d,%d)\n",
1961 rc1.left, rc1.top, rc1.right, rc1.bottom,
1962 rc2.left, rc2.top, rc2.right, rc2.bottom);
1963 GetWindowRect(hwnd, &rc1);
1964 GetClientRect(hwnd, &rc2);
1965 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1966 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1967 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n",
1968 rc1.left, rc1.top, rc1.right, rc1.bottom,
1969 rc2.left, rc2.top, rc2.right, rc2.bottom);
1971 /* fall through */
1972 case WM_WINDOWPOSCHANGING:
1974 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1975 WINDOWPOS my_winpos = *winpos;
1977 trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1978 (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
1979 winpos->hwnd, winpos->hwndInsertAfter,
1980 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1982 DefWindowProcA(hwnd, msg, wparam, lparam);
1984 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1985 "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1986 winpos->hwnd, winpos->hwndInsertAfter,
1987 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1989 return 1;
1992 return DefWindowProcA(hwnd, msg, wparam, lparam);
1995 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1997 static HWND mdi_client;
1999 switch (msg)
2001 case WM_CREATE:
2002 return 1;
2004 case WM_WINDOWPOSCHANGED:
2006 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2007 RECT rc1, rc2;
2009 GetWindowRect(hwnd, &rc1);
2010 trace("window: (%d,%d)-(%d,%d)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
2011 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
2012 /* note: winpos coordinates are relative to parent */
2013 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
2014 trace("pos: (%d,%d)-(%d,%d)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
2015 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2017 GetWindowRect(hwnd, &rc1);
2018 GetClientRect(hwnd, &rc2);
2019 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
2020 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
2021 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
2023 /* fall through */
2024 case WM_WINDOWPOSCHANGING:
2026 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
2027 WINDOWPOS my_winpos = *winpos;
2029 trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
2030 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2031 winpos->hwnd, winpos->hwndInsertAfter,
2032 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2034 DefWindowProcA(hwnd, msg, wparam, lparam);
2036 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
2037 winpos->hwnd, winpos->hwndInsertAfter,
2038 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
2040 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
2041 "DefWindowProc should not change WINDOWPOS values\n");
2043 return 1;
2046 case WM_CLOSE:
2047 PostQuitMessage(0);
2048 break;
2050 return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
2053 static BOOL mdi_RegisterWindowClasses(void)
2055 WNDCLASSA cls;
2057 cls.style = 0;
2058 cls.lpfnWndProc = mdi_main_wnd_procA;
2059 cls.cbClsExtra = 0;
2060 cls.cbWndExtra = 0;
2061 cls.hInstance = GetModuleHandleA(0);
2062 cls.hIcon = 0;
2063 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2064 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2065 cls.lpszMenuName = NULL;
2066 cls.lpszClassName = "MDI_parent_Class";
2067 if(!RegisterClassA(&cls)) return FALSE;
2069 cls.lpfnWndProc = mdi_child_wnd_proc_1;
2070 cls.lpszClassName = "MDI_child_Class_1";
2071 if(!RegisterClassA(&cls)) return FALSE;
2073 cls.lpfnWndProc = mdi_child_wnd_proc_2;
2074 cls.lpszClassName = "MDI_child_Class_2";
2075 if(!RegisterClassA(&cls)) return FALSE;
2077 return TRUE;
2080 static void test_mdi(void)
2082 static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL };
2083 HWND mdi_hwndMain, mdi_client;
2084 CLIENTCREATESTRUCT client_cs;
2085 RECT rc;
2086 DWORD i;
2087 MSG msg;
2089 if (!mdi_RegisterWindowClasses()) assert(0);
2091 mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
2092 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2093 WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
2094 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2095 GetDesktopWindow(), 0,
2096 GetModuleHandleA(NULL), NULL);
2097 assert(mdi_hwndMain);
2099 GetClientRect(mdi_hwndMain, &rc);
2101 client_cs.hWindowMenu = 0;
2102 client_cs.idFirstChild = 1;
2104 for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
2106 HWND mdi_child;
2107 SCROLLINFO si;
2108 BOOL ret, gotit;
2110 mdi_client = CreateWindowExA(0, "mdiclient", NULL,
2111 WS_CHILD | style[i],
2112 0, 0, rc.right, rc.bottom,
2113 mdi_hwndMain, 0, 0, &client_cs);
2114 ok(mdi_client != 0, "MDI client creation failed\n");
2116 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
2118 CW_USEDEFAULT, CW_USEDEFAULT,
2119 CW_USEDEFAULT, CW_USEDEFAULT,
2120 mdi_client, 0, 0,
2121 mdi_lParam_test_message);
2122 ok(mdi_child != 0, "MDI child creation failed\n");
2124 si.cbSize = sizeof(si);
2125 si.fMask = SIF_ALL;
2126 ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2127 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2129 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2130 ok(si.nPage == 0, "expected 0\n");
2131 ok(si.nPos == 0, "expected 0\n");
2132 ok(si.nTrackPos == 0, "expected 0\n");
2133 ok(si.nMin == 0, "expected 0\n");
2134 ok(si.nMax == 100, "expected 100\n");
2136 else
2137 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2139 ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2140 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2142 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2143 ok(si.nPage == 0, "expected 0\n");
2144 ok(si.nPos == 0, "expected 0\n");
2145 ok(si.nTrackPos == 0, "expected 0\n");
2146 ok(si.nMin == 0, "expected 0\n");
2147 ok(si.nMax == 100, "expected 100\n");
2149 else
2150 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2152 SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
2154 si.cbSize = sizeof(si);
2155 si.fMask = SIF_ALL;
2156 ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2157 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2159 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2160 ok(si.nPage == 0, "expected 0\n");
2161 ok(si.nPos == 0, "expected 0\n");
2162 ok(si.nTrackPos == 0, "expected 0\n");
2163 ok(si.nMin == 0, "expected 0\n");
2164 ok(si.nMax == 100, "expected 100\n");
2166 else
2167 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2169 ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2170 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2172 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2173 ok(si.nPage == 0, "expected 0\n");
2174 ok(si.nPos == 0, "expected 0\n");
2175 ok(si.nTrackPos == 0, "expected 0\n");
2176 ok(si.nMin == 0, "expected 0\n");
2177 ok(si.nMax == 100, "expected 100\n");
2179 else
2180 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2182 gotit = FALSE;
2183 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
2185 if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT)
2187 DispatchMessageA(&msg);
2188 continue;
2191 if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */
2193 ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n");
2194 gotit = TRUE;
2196 else
2197 todo_wine
2198 ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message);
2199 DispatchMessageA(&msg);
2201 todo_wine
2202 ok(gotit, "message 0x003f should appear after SetWindowPos\n");
2204 si.cbSize = sizeof(si);
2205 si.fMask = SIF_ALL;
2206 ret = GetScrollInfo(mdi_client, SB_HORZ, &si);
2207 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2209 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]);
2210 todo_wine
2211 ok(si.nPage != 0, "expected !0\n");
2212 ok(si.nPos == 0, "expected 0\n");
2213 ok(si.nTrackPos == 0, "expected 0\n");
2214 ok(si.nMin != 0, "expected !0\n");
2215 ok(si.nMax != 100, "expected !100\n");
2217 else
2218 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]);
2220 ret = GetScrollInfo(mdi_client, SB_VERT, &si);
2221 if (style[i] & (WS_HSCROLL | WS_VSCROLL))
2223 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]);
2224 todo_wine
2225 ok(si.nPage != 0, "expected !0\n");
2226 ok(si.nPos == 0, "expected 0\n");
2227 ok(si.nTrackPos == 0, "expected 0\n");
2228 ok(si.nMin != 0, "expected !0\n");
2229 ok(si.nMax != 100, "expected !100\n");
2231 else
2232 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]);
2234 DestroyWindow(mdi_child);
2235 DestroyWindow(mdi_client);
2238 /* MDIClient without MDIS_ALLCHILDSTYLES */
2239 mdi_client = CreateWindowExA(0, "mdiclient",
2240 NULL,
2241 WS_CHILD /*| WS_VISIBLE*/,
2242 /* tests depend on a not zero MDIClient size */
2243 0, 0, rc.right, rc.bottom,
2244 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2245 &client_cs);
2246 assert(mdi_client);
2247 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2248 DestroyWindow(mdi_client);
2250 /* MDIClient with MDIS_ALLCHILDSTYLES */
2251 mdi_client = CreateWindowExA(0, "mdiclient",
2252 NULL,
2253 WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
2254 /* tests depend on a not zero MDIClient size */
2255 0, 0, rc.right, rc.bottom,
2256 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2257 &client_cs);
2258 assert(mdi_client);
2259 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2260 DestroyWindow(mdi_client);
2262 /* Test child window stack management */
2263 mdi_client = CreateWindowExA(0, "mdiclient",
2264 NULL,
2265 WS_CHILD,
2266 0, 0, rc.right, rc.bottom,
2267 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2268 &client_cs);
2269 assert(mdi_client);
2270 test_MDI_child_stack(mdi_client);
2271 DestroyWindow(mdi_client);
2273 while(GetMessage(&msg, 0, 0, 0))
2275 TranslateMessage(&msg);
2276 DispatchMessage(&msg);
2279 DestroyWindow(mdi_hwndMain);
2282 static void test_icons(void)
2284 WNDCLASSEXA cls;
2285 HWND hwnd;
2286 HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2287 HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
2288 HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
2289 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
2290 HICON res;
2292 cls.cbSize = sizeof(cls);
2293 cls.style = 0;
2294 cls.lpfnWndProc = DefWindowProcA;
2295 cls.cbClsExtra = 0;
2296 cls.cbWndExtra = 0;
2297 cls.hInstance = 0;
2298 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND);
2299 cls.hIconSm = small_icon;
2300 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2301 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2302 cls.lpszMenuName = NULL;
2303 cls.lpszClassName = "IconWindowClass";
2305 RegisterClassExA(&cls);
2307 hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
2308 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
2309 assert( hwnd );
2311 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2312 ok( res == 0, "wrong big icon %p/0\n", res );
2313 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
2314 ok( res == 0, "wrong previous big icon %p/0\n", res );
2315 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2316 ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
2317 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
2318 ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
2319 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2320 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2322 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2323 ok( res == 0, "wrong small icon %p/0\n", res );
2324 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2325 ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
2326 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
2327 ok( res == 0, "wrong previous small icon %p/0\n", res );
2328 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2329 ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
2330 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2331 ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
2332 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
2333 ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
2334 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2335 ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
2336 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2337 ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
2339 /* make sure the big icon hasn't changed */
2340 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2341 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2343 DestroyWindow( hwnd );
2346 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2348 if (msg == WM_NCCALCSIZE)
2350 RECT *rect = (RECT *)lparam;
2351 /* first time around increase the rectangle, next time decrease it */
2352 if (rect->left == 100) InflateRect( rect, 10, 10 );
2353 else InflateRect( rect, -10, -10 );
2354 return 0;
2356 return DefWindowProcA( hwnd, msg, wparam, lparam );
2359 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
2361 RECT orig_win_rc, rect;
2362 LONG_PTR old_proc;
2363 HWND hwnd_grandchild, hwnd_child, hwnd_child2;
2364 HWND hwnd_desktop;
2365 RECT rc1, rc2;
2366 BOOL ret;
2368 SetRect(&rect, 111, 222, 333, 444);
2369 ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
2370 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2371 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2373 SetRect(&rect, 111, 222, 333, 444);
2374 ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
2375 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2376 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2378 GetWindowRect(hwnd, &orig_win_rc);
2380 old_proc = SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
2381 ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2382 ok(ret, "Got %d\n", ret);
2383 GetWindowRect( hwnd, &rect );
2384 ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
2385 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2386 GetClientRect( hwnd, &rect );
2387 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2388 ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2389 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2391 ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2392 ok(ret, "Got %d\n", ret);
2393 GetWindowRect( hwnd, &rect );
2394 ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2395 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2396 GetClientRect( hwnd, &rect );
2397 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2398 ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2399 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2401 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2402 orig_win_rc.right, orig_win_rc.bottom, 0);
2403 ok(ret, "Got %d\n", ret);
2404 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, old_proc );
2406 /* Win9x truncates coordinates to 16-bit irrespectively */
2407 if (!is_win9x)
2409 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2410 ok(ret, "Got %d\n", ret);
2411 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2412 ok(ret, "Got %d\n", ret);
2414 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2415 ok(ret, "Got %d\n", ret);
2416 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2417 ok(ret, "Got %d\n", ret);
2420 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2421 orig_win_rc.right, orig_win_rc.bottom, 0);
2422 ok(ret, "Got %d\n", ret);
2424 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2425 ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2426 ok(ret, "Got %d\n", ret);
2427 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2428 ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2429 ok(ret, "Got %d\n", ret);
2430 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2431 ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2432 ok(ret, "Got %d\n", ret);
2433 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2435 hwnd_desktop = GetDesktopWindow();
2436 ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2437 hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2438 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2439 hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2440 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2441 hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2442 ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2444 ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2445 ok(ret, "Got %d\n", ret);
2446 check_active_state(hwnd, hwnd, hwnd);
2448 ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2449 ok(ret, "Got %d\n", ret);
2450 check_active_state(hwnd2, hwnd2, hwnd2);
2452 /* Returns TRUE also for windows that are not siblings */
2453 ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2454 ok(ret, "Got %d\n", ret);
2455 check_active_state(hwnd2, hwnd2, hwnd2);
2457 ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2458 ok(ret, "Got %d\n", ret);
2459 check_active_state(hwnd2, hwnd2, hwnd2);
2461 /* Does not seem to do anything even without passing flags, still returns TRUE */
2462 GetWindowRect(hwnd_child, &rc1);
2463 ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2464 ok(ret, "Got %d\n", ret);
2465 GetWindowRect(hwnd_child, &rc2);
2466 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2467 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2468 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2469 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2470 check_active_state(hwnd2, hwnd2, hwnd2);
2472 /* Same thing the other way around. */
2473 GetWindowRect(hwnd2, &rc1);
2474 ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2475 ok(ret, "Got %d\n", ret);
2476 GetWindowRect(hwnd2, &rc2);
2477 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2478 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2479 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2480 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2481 check_active_state(hwnd2, hwnd2, hwnd2);
2483 /* .. and with these windows. */
2484 GetWindowRect(hwnd_grandchild, &rc1);
2485 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2486 ok(ret, "Got %d\n", ret);
2487 GetWindowRect(hwnd_grandchild, &rc2);
2488 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2489 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2490 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2491 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2492 check_active_state(hwnd2, hwnd2, hwnd2);
2494 /* Add SWP_NOZORDER and it will be properly resized. */
2495 GetWindowRect(hwnd_grandchild, &rc1);
2496 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2497 ok(ret, "Got %d\n", ret);
2498 GetWindowRect(hwnd_grandchild, &rc2);
2499 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2500 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2501 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2502 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2503 check_active_state(hwnd2, hwnd2, hwnd2);
2505 /* Given a sibling window, the window is properly resized. */
2506 GetWindowRect(hwnd_child, &rc1);
2507 ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2508 ok(ret, "Got %d\n", ret);
2509 GetWindowRect(hwnd_child, &rc2);
2510 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2511 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2512 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2513 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2514 check_active_state(hwnd2, hwnd2, hwnd2);
2516 /* Involving the desktop window changes things. */
2517 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2518 ok(!ret, "Got %d\n", ret);
2519 check_active_state(hwnd2, hwnd2, hwnd2);
2521 GetWindowRect(hwnd_child, &rc1);
2522 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2523 ok(!ret, "Got %d\n", ret);
2524 GetWindowRect(hwnd_child, &rc2);
2525 ok(rc1.top == rc2.top && rc1.left == rc2.left &&
2526 rc1.bottom == rc2.bottom && rc1.right == rc2.right,
2527 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2528 rc1.top, rc1.left, rc1.bottom, rc1.right, rc2.top, rc2.left, rc2.bottom, rc2.right);
2529 check_active_state(hwnd2, hwnd2, hwnd2);
2531 ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2532 ok(!ret, "Got %d\n", ret);
2533 check_active_state(hwnd2, hwnd2, hwnd2);
2535 ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2536 ok(!ret, "Got %d\n", ret);
2537 check_active_state(hwnd2, hwnd2, hwnd2);
2539 ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2540 ok(!ret, "Got %d\n", ret);
2541 check_active_state(hwnd2, hwnd2, hwnd2);
2543 DestroyWindow(hwnd_grandchild);
2544 DestroyWindow(hwnd_child);
2545 DestroyWindow(hwnd_child2);
2547 hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2);
2548 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2549 ret = SetWindowPos(hwnd_child, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2550 ok(ret, "Got %d\n", ret);
2551 flush_events( TRUE );
2552 todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
2553 DestroyWindow(hwnd_child);
2556 static void test_SetMenu(HWND parent)
2558 HWND child;
2559 HMENU hMenu, ret;
2560 BOOL retok;
2561 DWORD style;
2563 hMenu = CreateMenu();
2564 assert(hMenu);
2566 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2567 if (0)
2569 /* fails on (at least) Wine, NT4, XP SP2 */
2570 test_nonclient_area(parent);
2572 ret = GetMenu(parent);
2573 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2574 /* test whether we can destroy a menu assigned to a window */
2575 retok = DestroyMenu(hMenu);
2576 ok( retok, "DestroyMenu error %d\n", GetLastError());
2577 retok = IsMenu(hMenu);
2578 ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2579 ret = GetMenu(parent);
2580 /* This test fails on Win9x */
2581 if (!is_win9x)
2582 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2583 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2584 test_nonclient_area(parent);
2586 hMenu = CreateMenu();
2587 assert(hMenu);
2589 /* parent */
2590 ret = GetMenu(parent);
2591 ok(ret == 0, "unexpected menu id %p\n", ret);
2593 ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2594 test_nonclient_area(parent);
2595 ret = GetMenu(parent);
2596 ok(ret == 0, "unexpected menu id %p\n", ret);
2598 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2599 if (0)
2601 /* fails on (at least) Wine, NT4, XP SP2 */
2602 test_nonclient_area(parent);
2604 ret = GetMenu(parent);
2605 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2607 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2608 test_nonclient_area(parent);
2609 ret = GetMenu(parent);
2610 ok(ret == 0, "unexpected menu id %p\n", ret);
2612 /* child */
2613 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2614 assert(child);
2616 ret = GetMenu(child);
2617 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2619 ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2620 test_nonclient_area(child);
2621 ret = GetMenu(child);
2622 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2624 ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2625 test_nonclient_area(child);
2626 ret = GetMenu(child);
2627 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2629 ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2630 test_nonclient_area(child);
2631 ret = GetMenu(child);
2632 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2634 style = GetWindowLongA(child, GWL_STYLE);
2635 SetWindowLongA(child, GWL_STYLE, style | WS_POPUP);
2636 ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2637 ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2638 SetWindowLongA(child, GWL_STYLE, style);
2640 SetWindowLongA(child, GWL_STYLE, style | WS_OVERLAPPED);
2641 ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n");
2642 SetWindowLongA(child, GWL_STYLE, style);
2644 DestroyWindow(child);
2645 DestroyMenu(hMenu);
2648 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2650 HWND child[5], hwnd;
2651 INT_PTR i;
2653 assert(total <= 5);
2655 hwnd = GetWindow(parent, GW_CHILD);
2656 ok(!hwnd, "have to start without children to perform the test\n");
2658 for (i = 0; i < total; i++)
2660 if (style[i] & DS_CONTROL)
2662 child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2663 0,0,0,0, parent, (HMENU)i, 0, NULL);
2664 if (style[i] & WS_VISIBLE)
2665 ShowWindow(child[i], SW_SHOW);
2667 SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
2669 else
2670 child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2671 parent, (HMENU)i, 0, NULL);
2672 trace("child[%ld] = %p\n", i, child[i]);
2673 ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2676 hwnd = GetWindow(parent, GW_CHILD);
2677 ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2678 ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2679 ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2681 for (i = 0; i < total; i++)
2683 trace("hwnd[%ld] = %p\n", i, hwnd);
2684 ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2686 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
2689 for (i = 0; i < total; i++)
2690 ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2693 static void test_children_zorder(HWND parent)
2695 const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2696 WS_CHILD };
2697 const int simple_order[5] = { 0, 1, 2, 3, 4 };
2699 const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2700 WS_CHILD | WS_VISIBLE, WS_CHILD,
2701 WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
2702 const int complex_order_1[1] = { 0 };
2703 const int complex_order_2[2] = { 1, 0 };
2704 const int complex_order_3[3] = { 1, 0, 2 };
2705 const int complex_order_4[4] = { 1, 0, 2, 3 };
2706 const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2707 const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2708 WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
2709 WS_CHILD | WS_VISIBLE };
2710 const int complex_order_6[3] = { 0, 1, 2 };
2712 /* simple WS_CHILD */
2713 test_window_tree(parent, simple_style, simple_order, 5);
2715 /* complex children styles */
2716 test_window_tree(parent, complex_style, complex_order_1, 1);
2717 test_window_tree(parent, complex_style, complex_order_2, 2);
2718 test_window_tree(parent, complex_style, complex_order_3, 3);
2719 test_window_tree(parent, complex_style, complex_order_4, 4);
2720 test_window_tree(parent, complex_style, complex_order_5, 5);
2722 /* another set of complex children styles */
2723 test_window_tree(parent, complex_style_6, complex_order_6, 3);
2726 #define check_z_order(hwnd, next, prev, owner, topmost) \
2727 check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2728 __FILE__, __LINE__)
2730 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2731 BOOL topmost, const char *file, int line)
2733 HWND test;
2734 DWORD ex_style;
2736 test = GetWindow(hwnd, GW_HWNDNEXT);
2737 /* skip foreign windows */
2738 while (test && test != next &&
2739 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2740 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2741 GetWindow(test, GW_OWNER) == next))
2743 /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2744 test = GetWindow(test, GW_HWNDNEXT);
2746 ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2748 test = GetWindow(hwnd, GW_HWNDPREV);
2749 /* skip foreign windows */
2750 while (test && test != prev &&
2751 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2752 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2753 GetWindow(test, GW_OWNER) == hwnd))
2755 /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2756 test = GetWindow(test, GW_HWNDPREV);
2758 ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2760 test = GetWindow(hwnd, GW_OWNER);
2761 ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2763 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2764 ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2765 hwnd, topmost ? "" : "NOT ");
2768 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2770 HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2772 trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2774 SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2776 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2777 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2779 hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window",
2780 WS_OVERLAPPED | WS_CAPTION,
2781 100, 100, 100, 100,
2782 0, 0, GetModuleHandleA(NULL), NULL);
2783 trace("hwnd_F %p\n", hwnd_F);
2784 check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2786 SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2787 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2788 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2789 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2791 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2792 style,
2793 100, 100, 100, 100,
2794 hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2795 trace("hwnd_C %p\n", hwnd_C);
2796 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2797 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2798 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2799 check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2801 hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2802 style,
2803 100, 100, 100, 100,
2804 hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2805 trace("hwnd_B %p\n", hwnd_B);
2806 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2807 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2808 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2809 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2810 check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2812 hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2813 style,
2814 100, 100, 100, 100,
2815 0, 0, GetModuleHandleA(NULL), NULL);
2816 trace("hwnd_A %p\n", hwnd_A);
2817 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2818 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2819 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2820 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2821 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2822 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2824 trace("A %p B %p C %p D %p E %p F %p\n", hwnd_A, hwnd_B, hwnd_C, hwnd_D, hwnd_E, hwnd_F);
2826 /* move hwnd_F and its popups up */
2827 SetWindowPos(hwnd_F, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2828 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2829 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2830 check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2831 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2832 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2833 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2835 /* move hwnd_F and its popups down */
2836 #if 0 /* enable once Wine is fixed to pass this test */
2837 SetWindowPos(hwnd_F, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2838 check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2839 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2840 check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2841 check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2842 check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2843 check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2844 #endif
2846 /* make hwnd_C owned by a topmost window */
2847 DestroyWindow( hwnd_C );
2848 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2849 style,
2850 100, 100, 100, 100,
2851 hwnd_A, 0, GetModuleHandleA(NULL), NULL);
2852 trace("hwnd_C %p\n", hwnd_C);
2853 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2854 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2855 check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2856 check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2857 check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
2858 check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
2860 DestroyWindow(hwnd_A);
2861 DestroyWindow(hwnd_B);
2862 DestroyWindow(hwnd_C);
2863 DestroyWindow(hwnd_F);
2866 static void test_vis_rgn( HWND hwnd )
2868 RECT win_rect, rgn_rect;
2869 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2870 HDC hdc;
2872 ShowWindow(hwnd,SW_SHOW);
2873 hdc = GetDC( hwnd );
2874 ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
2875 GetWindowRect( hwnd, &win_rect );
2876 GetRgnBox( hrgn, &rgn_rect );
2877 if (is_win9x)
2879 trace("win9x, mapping to screen coords\n");
2880 MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
2882 trace("win: %d,%d-%d,%d\n", win_rect.left, win_rect.top, win_rect.right, win_rect.bottom );
2883 trace("rgn: %d,%d-%d,%d\n", rgn_rect.left, rgn_rect.top, rgn_rect.right, rgn_rect.bottom );
2884 ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n",
2885 rgn_rect.left, win_rect.left );
2886 ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n",
2887 rgn_rect.top, win_rect.top );
2888 ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n",
2889 rgn_rect.right, win_rect.right );
2890 ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n",
2891 rgn_rect.bottom, win_rect.bottom );
2892 ReleaseDC( hwnd, hdc );
2895 static LRESULT WINAPI set_focus_on_activate_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
2897 if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE)
2899 HWND child = GetWindow(hwnd, GW_CHILD);
2900 ok(child != 0, "couldn't find child window\n");
2901 SetFocus(child);
2902 ok(GetFocus() == child, "Focus should be on child %p\n", child);
2903 return 0;
2905 return DefWindowProcA(hwnd, msg, wp, lp);
2908 static void test_SetFocus(HWND hwnd)
2910 HWND child, child2, ret;
2911 WNDPROC old_wnd_proc;
2913 /* check if we can set focus to non-visible windows */
2915 ShowWindow(hwnd, SW_SHOW);
2916 SetFocus(0);
2917 SetFocus(hwnd);
2918 ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2919 ok( GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2920 ShowWindow(hwnd, SW_HIDE);
2921 SetFocus(0);
2922 SetFocus(hwnd);
2923 ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2924 ok( !(GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2925 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2926 assert(child);
2927 SetFocus(child);
2928 ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2929 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2930 ShowWindow(child, SW_SHOW);
2931 ok( GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2932 ok( GetFocus() == child, "Focus no longer on child %p\n", child );
2933 ShowWindow(child, SW_HIDE);
2934 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2935 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2936 ShowWindow(child, SW_SHOW);
2937 child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL);
2938 assert(child2);
2939 ShowWindow(child2, SW_SHOW);
2940 SetFocus(child2);
2941 ShowWindow(child, SW_HIDE);
2942 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2943 ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() );
2944 ShowWindow(child, SW_SHOW);
2945 SetFocus(child);
2946 ok( GetFocus() == child, "Focus should be on child %p\n", child );
2947 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
2948 ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2950 ShowWindow(child, SW_HIDE);
2951 SetFocus(hwnd);
2952 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2953 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
2954 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2955 ShowWindow(child, SW_HIDE);
2956 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2958 ShowWindow(hwnd, SW_SHOW);
2959 ShowWindow(child, SW_SHOW);
2960 SetFocus(child);
2961 ok( GetFocus() == child, "Focus should be on child %p\n", child );
2962 EnableWindow(hwnd, FALSE);
2963 ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2964 EnableWindow(hwnd, TRUE);
2966 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2967 ShowWindow(hwnd, SW_SHOWMINIMIZED);
2968 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2969 todo_wine
2970 ok( GetFocus() != child, "Focus should not be on child %p\n", child );
2971 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
2972 ShowWindow(hwnd, SW_RESTORE);
2973 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2974 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
2975 ShowWindow(hwnd, SW_SHOWMINIMIZED);
2976 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2977 ok( GetFocus() != child, "Focus should not be on child %p\n", child );
2978 todo_wine
2979 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
2980 old_wnd_proc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)set_focus_on_activate_proc);
2981 ShowWindow(hwnd, SW_RESTORE);
2982 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2983 todo_wine
2984 ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() );
2985 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)old_wnd_proc);
2987 SetFocus( hwnd );
2988 SetParent( child, GetDesktopWindow());
2989 SetParent( child2, child );
2990 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2991 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
2992 ret = SetFocus( child2 );
2993 ok( ret == 0, "SetFocus %p should fail\n", child2);
2994 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2995 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
2996 ret = SetFocus( child );
2997 ok( ret == 0, "SetFocus %p should fail\n", child);
2998 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2999 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3000 SetWindowLongW( child, GWL_STYLE, WS_POPUP|WS_CHILD );
3001 SetFocus( child2 );
3002 ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3003 ok( GetFocus() == child2, "Focus should be on child2 %p\n", child2 );
3004 SetFocus( hwnd );
3005 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
3006 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
3007 SetFocus( child );
3008 ok( GetActiveWindow() == child, "child window %p should be active\n", child);
3009 ok( GetFocus() == child, "Focus should be on child %p\n", child );
3011 DestroyWindow( child2 );
3012 DestroyWindow( child );
3015 static void test_SetActiveWindow(HWND hwnd)
3017 HWND hwnd2;
3019 flush_events( TRUE );
3020 ShowWindow(hwnd, SW_HIDE);
3021 SetFocus(0);
3022 SetActiveWindow(0);
3023 check_wnd_state(0, 0, 0, 0);
3025 /*trace("testing SetActiveWindow %p\n", hwnd);*/
3027 ShowWindow(hwnd, SW_SHOW);
3028 check_wnd_state(hwnd, hwnd, hwnd, 0);
3030 hwnd2 = SetActiveWindow(0);
3031 ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd);
3032 if (!GetActiveWindow()) /* doesn't always work on vista */
3034 check_wnd_state(0, 0, 0, 0);
3035 hwnd2 = SetActiveWindow(hwnd);
3036 ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2);
3038 check_wnd_state(hwnd, hwnd, hwnd, 0);
3040 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3041 check_wnd_state(hwnd, hwnd, hwnd, 0);
3043 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
3044 check_wnd_state(hwnd, hwnd, hwnd, 0);
3046 ShowWindow(hwnd, SW_HIDE);
3047 check_wnd_state(0, 0, 0, 0);
3049 /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/
3050 SetActiveWindow(hwnd);
3051 check_wnd_state(hwnd, hwnd, hwnd, 0);
3053 ShowWindow(hwnd, SW_SHOW);
3054 check_wnd_state(hwnd, hwnd, hwnd, 0);
3056 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3057 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3059 DestroyWindow(hwnd2);
3060 check_wnd_state(hwnd, hwnd, hwnd, 0);
3062 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3063 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3065 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3066 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3068 DestroyWindow(hwnd2);
3069 check_wnd_state(hwnd, hwnd, hwnd, 0);
3072 struct create_window_thread_params
3074 HWND window;
3075 HANDLE window_created;
3076 HANDLE test_finished;
3079 static DWORD WINAPI create_window_thread(void *param)
3081 struct create_window_thread_params *p = param;
3082 DWORD res;
3083 BOOL ret;
3085 p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3087 ret = SetEvent(p->window_created);
3088 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
3090 res = WaitForSingleObject(p->test_finished, INFINITE);
3091 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3093 DestroyWindow(p->window);
3094 return 0;
3097 static void test_SetForegroundWindow(HWND hwnd)
3099 struct create_window_thread_params thread_params;
3100 HANDLE thread;
3101 DWORD res, tid;
3102 BOOL ret;
3103 HWND hwnd2;
3104 MSG msg;
3105 LONG style;
3107 flush_events( TRUE );
3108 ShowWindow(hwnd, SW_HIDE);
3109 SetFocus(0);
3110 SetActiveWindow(0);
3111 check_wnd_state(0, 0, 0, 0);
3113 /*trace("testing SetForegroundWindow %p\n", hwnd);*/
3115 ShowWindow(hwnd, SW_SHOW);
3116 check_wnd_state(hwnd, hwnd, hwnd, 0);
3118 hwnd2 = SetActiveWindow(0);
3119 ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd);
3120 if (GetActiveWindow() == hwnd) /* doesn't always work on vista */
3121 check_wnd_state(hwnd, hwnd, hwnd, 0);
3122 else
3123 check_wnd_state(0, 0, 0, 0);
3125 ret = SetForegroundWindow(hwnd);
3126 if (!ret)
3128 skip( "SetForegroundWindow not working\n" );
3129 return;
3131 check_wnd_state(hwnd, hwnd, hwnd, 0);
3133 SetLastError(0xdeadbeef);
3134 ret = SetForegroundWindow(0);
3135 ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n");
3136 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
3137 broken(GetLastError() == 0xdeadbeef), /* win9x */
3138 "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
3139 check_wnd_state(hwnd, hwnd, hwnd, 0);
3141 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3142 check_wnd_state(hwnd, hwnd, hwnd, 0);
3144 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
3145 check_wnd_state(hwnd, hwnd, hwnd, 0);
3147 hwnd2 = GetForegroundWindow();
3148 ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2);
3149 ret = SetForegroundWindow( GetDesktopWindow() );
3150 ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError());
3151 hwnd2 = GetForegroundWindow();
3152 ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2);
3154 ShowWindow(hwnd, SW_HIDE);
3155 check_wnd_state(0, 0, 0, 0);
3157 /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/
3158 ret = SetForegroundWindow(hwnd);
3159 ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n");
3160 check_wnd_state(hwnd, hwnd, hwnd, 0);
3162 ShowWindow(hwnd, SW_SHOW);
3163 check_wnd_state(hwnd, hwnd, hwnd, 0);
3165 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3166 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3168 DestroyWindow(hwnd2);
3169 check_wnd_state(hwnd, hwnd, hwnd, 0);
3171 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
3172 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3174 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
3175 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3177 DestroyWindow(hwnd2);
3178 check_wnd_state(hwnd, hwnd, hwnd, 0);
3180 hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
3181 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3183 thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL);
3184 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
3185 thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL);
3186 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
3187 thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid);
3188 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
3189 res = WaitForSingleObject(thread_params.window_created, INFINITE);
3190 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
3191 check_wnd_state(hwnd2, thread_params.window, hwnd2, 0);
3193 SetForegroundWindow(hwnd2);
3194 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3196 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
3197 if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3198 todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
3199 todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
3201 SetForegroundWindow(hwnd);
3202 check_wnd_state(hwnd, hwnd, hwnd, 0);
3203 style = GetWindowLongA(hwnd2, GWL_STYLE) | WS_CHILD;
3204 ok(SetWindowLongA(hwnd2, GWL_STYLE, style), "SetWindowLong failed\n");
3205 ok(SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n");
3206 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
3208 SetForegroundWindow(hwnd);
3209 check_wnd_state(hwnd, hwnd, hwnd, 0);
3210 ok(SetWindowLongA(hwnd2, GWL_STYLE, style & (~WS_POPUP)), "SetWindowLong failed\n");
3211 ok(!SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n");
3212 check_wnd_state(hwnd, hwnd, hwnd, 0);
3214 SetEvent(thread_params.test_finished);
3215 WaitForSingleObject(thread, INFINITE);
3216 CloseHandle(thread_params.test_finished);
3217 CloseHandle(thread_params.window_created);
3218 CloseHandle(thread);
3219 DestroyWindow(hwnd2);
3222 static WNDPROC old_button_proc;
3224 static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPARAM lparam)
3226 LRESULT ret;
3227 USHORT key_state;
3229 key_state = GetKeyState(VK_LBUTTON);
3230 ok(!(key_state & 0x8000), "VK_LBUTTON should not be pressed, state %04x\n", key_state);
3232 ret = CallWindowProcA(old_button_proc, button, msg, wparam, lparam);
3234 if (msg == WM_LBUTTONDOWN)
3236 HWND hwnd, capture;
3238 check_wnd_state(button, button, button, button);
3240 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3241 assert(hwnd);
3242 trace("hwnd %p\n", hwnd);
3244 check_wnd_state(button, button, button, button);
3246 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
3248 check_wnd_state(button, button, button, button);
3250 DestroyWindow(hwnd);
3252 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3253 assert(hwnd);
3254 trace("hwnd %p\n", hwnd);
3256 check_wnd_state(button, button, button, button);
3258 /* button wnd proc should release capture on WM_KILLFOCUS if it does
3259 * match internal button state.
3261 SendMessageA(button, WM_KILLFOCUS, 0, 0);
3262 check_wnd_state(button, button, button, 0);
3264 ShowWindow(hwnd, SW_SHOW);
3265 check_wnd_state(hwnd, hwnd, hwnd, 0);
3267 capture = SetCapture(hwnd);
3268 ok(capture == 0, "SetCapture() = %p\n", capture);
3270 check_wnd_state(hwnd, hwnd, hwnd, hwnd);
3272 DestroyWindow(hwnd);
3274 check_wnd_state(button, 0, button, 0);
3277 return ret;
3280 static void test_capture_1(void)
3282 HWND button, capture;
3284 capture = GetCapture();
3285 ok(capture == 0, "GetCapture() = %p\n", capture);
3287 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
3288 assert(button);
3289 trace("button %p\n", button);
3291 old_button_proc = (WNDPROC)SetWindowLongPtrA(button, GWLP_WNDPROC, (LONG_PTR)button_hook_proc);
3293 SendMessageA(button, WM_LBUTTONDOWN, 0, 0);
3295 capture = SetCapture(button);
3296 ok(capture == 0, "SetCapture() = %p\n", capture);
3297 check_wnd_state(button, 0, button, button);
3299 DestroyWindow(button);
3300 /* old active window test depends on previously executed window
3301 * activation tests, and fails under NT4.
3302 check_wnd_state(oldActive, 0, oldFocus, 0);*/
3305 static void test_capture_2(void)
3307 HWND button, hwnd, capture, oldFocus, oldActive;
3309 oldFocus = GetFocus();
3310 oldActive = GetActiveWindow();
3311 check_wnd_state(oldActive, 0, oldFocus, 0);
3313 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
3314 assert(button);
3315 trace("button %p\n", button);
3317 check_wnd_state(button, button, button, 0);
3319 capture = SetCapture(button);
3320 ok(capture == 0, "SetCapture() = %p\n", capture);
3322 check_wnd_state(button, button, button, button);
3324 /* button wnd proc should ignore WM_KILLFOCUS if it doesn't match
3325 * internal button state.
3327 SendMessageA(button, WM_KILLFOCUS, 0, 0);
3328 check_wnd_state(button, button, button, button);
3330 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3331 assert(hwnd);
3332 trace("hwnd %p\n", hwnd);
3334 check_wnd_state(button, button, button, button);
3336 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
3338 check_wnd_state(button, button, button, button);
3340 DestroyWindow(hwnd);
3342 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
3343 assert(hwnd);
3344 trace("hwnd %p\n", hwnd);
3346 check_wnd_state(button, button, button, button);
3348 ShowWindow(hwnd, SW_SHOW);
3350 check_wnd_state(hwnd, hwnd, hwnd, button);
3352 capture = SetCapture(hwnd);
3353 ok(capture == button, "SetCapture() = %p\n", capture);
3355 check_wnd_state(hwnd, hwnd, hwnd, hwnd);
3357 DestroyWindow(hwnd);
3358 check_wnd_state(button, button, button, 0);
3360 DestroyWindow(button);
3361 check_wnd_state(oldActive, 0, oldFocus, 0);
3364 static void test_capture_3(HWND hwnd1, HWND hwnd2)
3366 BOOL ret;
3368 ShowWindow(hwnd1, SW_HIDE);
3369 ShowWindow(hwnd2, SW_HIDE);
3371 ok(!IsWindowVisible(hwnd1), "%p should be invisible\n", hwnd1);
3372 ok(!IsWindowVisible(hwnd2), "%p should be invisible\n", hwnd2);
3374 SetCapture(hwnd1);
3375 check_wnd_state(0, 0, 0, hwnd1);
3377 SetCapture(hwnd2);
3378 check_wnd_state(0, 0, 0, hwnd2);
3380 ShowWindow(hwnd1, SW_SHOW);
3381 check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2);
3383 ret = ReleaseCapture();
3384 ok (ret, "releasecapture did not return TRUE.\n");
3385 ret = ReleaseCapture();
3386 ok (ret, "releasecapture did not return TRUE after second try.\n");
3389 static LRESULT CALLBACK test_capture_4_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
3391 GUITHREADINFO gti;
3392 HWND cap_wnd, cap_wnd2, set_cap_wnd;
3393 BOOL status;
3394 switch (msg)
3396 case WM_CAPTURECHANGED:
3398 /* now try to release capture from menu. this should fail */
3399 if (pGetGUIThreadInfo)
3401 memset(&gti, 0, sizeof(GUITHREADINFO));
3402 gti.cbSize = sizeof(GUITHREADINFO);
3403 status = pGetGUIThreadInfo(GetCurrentThreadId(), &gti);
3404 ok(status, "GetGUIThreadInfo() failed!\n");
3405 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
3407 cap_wnd = GetCapture();
3409 ok(cap_wnd == (HWND)lParam, "capture window %p does not match lparam %lx\n", cap_wnd, lParam);
3410 todo_wine ok(cap_wnd == hWnd, "capture window %p does not match hwnd %p\n", cap_wnd, hWnd);
3412 /* check that re-setting the capture for the menu fails */
3413 set_cap_wnd = SetCapture(cap_wnd);
3414 ok(!set_cap_wnd || broken(set_cap_wnd == cap_wnd), /* nt4 */
3415 "SetCapture should have failed!\n");
3416 if (set_cap_wnd)
3418 DestroyWindow(hWnd);
3419 break;
3422 /* check that SetCapture fails for another window and that it does not touch the error code */
3423 set_cap_wnd = SetCapture(hWnd);
3424 ok(!set_cap_wnd, "SetCapture should have failed!\n");
3426 /* check that ReleaseCapture fails and does not touch the error code */
3427 status = ReleaseCapture();
3428 ok(!status, "ReleaseCapture should have failed!\n");
3430 /* check that thread info did not change */
3431 if (pGetGUIThreadInfo)
3433 memset(&gti, 0, sizeof(GUITHREADINFO));
3434 gti.cbSize = sizeof(GUITHREADINFO);
3435 status = pGetGUIThreadInfo(GetCurrentThreadId(), &gti);
3436 ok(status, "GetGUIThreadInfo() failed!\n");
3437 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
3440 /* verify that no capture change took place */
3441 cap_wnd2 = GetCapture();
3442 ok(cap_wnd2 == cap_wnd, "Capture changed!\n");
3444 /* we are done. kill the window */
3445 DestroyWindow(hWnd);
3446 break;
3448 default:
3449 return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
3451 return 0;
3454 /* Test that no-one can mess around with the current capture while a menu is open */
3455 static void test_capture_4(void)
3457 BOOL ret;
3458 HMENU hmenu;
3459 HWND hwnd;
3460 WNDCLASSA wclass;
3461 HINSTANCE hInstance = GetModuleHandleA( NULL );
3462 ATOM aclass;
3464 if (!pGetGUIThreadInfo)
3466 win_skip("GetGUIThreadInfo is not available\n");
3467 return;
3469 wclass.lpszClassName = "TestCapture4Class";
3470 wclass.style = CS_HREDRAW | CS_VREDRAW;
3471 wclass.lpfnWndProc = test_capture_4_proc;
3472 wclass.hInstance = hInstance;
3473 wclass.hIcon = LoadIconA( 0, (LPCSTR)IDI_APPLICATION );
3474 wclass.hCursor = LoadCursorA( 0, (LPCSTR)IDC_ARROW );
3475 wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
3476 wclass.lpszMenuName = 0;
3477 wclass.cbClsExtra = 0;
3478 wclass.cbWndExtra = 0;
3479 aclass = RegisterClassA( &wclass );
3480 ok( aclass, "RegisterClassA failed with error %d\n", GetLastError());
3481 hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest",
3482 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
3483 400, 200, NULL, NULL, hInstance, NULL);
3484 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
3485 if (!hwnd) return;
3486 hmenu = CreatePopupMenu();
3488 ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest2");
3489 ok( ret, "AppendMenuA has failed!\n");
3491 /* set main window to have initial capture */
3492 SetCapture(hwnd);
3494 if (is_win9x)
3496 win_skip("TrackPopupMenu test crashes on Win9x/WinMe\n");
3498 else
3500 /* create popup (it will self-destruct) */
3501 ret = TrackPopupMenu(hmenu, TPM_RETURNCMD, 100, 100, 0, hwnd, NULL);
3502 ok( ret == 0, "TrackPopupMenu returned %d expected zero\n", ret);
3505 /* clean up */
3506 DestroyMenu(hmenu);
3507 DestroyWindow(hwnd);
3510 /* PeekMessage wrapper that ignores the messages we don't care about */
3511 static BOOL peek_message( MSG *msg )
3513 BOOL ret;
3516 ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
3517 } while (ret && ignore_message(msg->message));
3518 return ret;
3521 static void test_keyboard_input(HWND hwnd)
3523 MSG msg;
3524 BOOL ret;
3526 flush_events( TRUE );
3527 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
3528 UpdateWindow(hwnd);
3529 flush_events( TRUE );
3531 ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow());
3533 SetFocus(hwnd);
3534 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3536 flush_events( TRUE );
3538 PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3539 ret = peek_message(&msg);
3540 ok( ret, "no message available\n");
3541 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3542 ret = peek_message(&msg);
3543 ok( !ret, "message %04x available\n", msg.message);
3545 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3547 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3548 ret = peek_message(&msg);
3549 ok(ret, "no message available\n");
3550 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3551 ret = peek_message(&msg);
3552 ok( !ret, "message %04x available\n", msg.message);
3554 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3556 keybd_event(VK_SPACE, 0, 0, 0);
3557 if (!peek_message(&msg))
3559 skip( "keybd_event didn't work, skipping keyboard test\n" );
3560 return;
3562 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3563 ret = peek_message(&msg);
3564 ok( !ret, "message %04x available\n", msg.message);
3566 SetFocus(0);
3567 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3569 flush_events( TRUE );
3571 PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3572 ret = peek_message(&msg);
3573 ok(ret, "no message available\n");
3574 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3575 ret = peek_message(&msg);
3576 ok( !ret, "message %04x available\n", msg.message);
3578 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3580 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3581 ret = peek_message(&msg);
3582 ok(ret, "no message available\n");
3583 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3584 ret = peek_message(&msg);
3585 ok( !ret, "message %04x available\n", msg.message);
3587 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3589 keybd_event(VK_SPACE, 0, 0, 0);
3590 ret = peek_message(&msg);
3591 ok(ret, "no message available\n");
3592 ok(msg.hwnd == hwnd && msg.message == WM_SYSKEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3593 ret = peek_message(&msg);
3594 ok( !ret, "message %04x available\n", msg.message);
3597 static BOOL wait_for_message( MSG *msg )
3599 BOOL ret;
3601 for (;;)
3603 ret = peek_message(msg);
3604 if (ret)
3606 if (msg->message == WM_PAINT) DispatchMessageA(msg);
3607 else break;
3609 else if (MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
3611 if (!ret) msg->message = 0;
3612 return ret;
3615 static void test_mouse_input(HWND hwnd)
3617 RECT rc;
3618 POINT pt;
3619 int x, y;
3620 HWND popup;
3621 MSG msg;
3622 BOOL ret;
3623 LRESULT res;
3625 ShowWindow(hwnd, SW_SHOWNORMAL);
3626 UpdateWindow(hwnd);
3627 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3629 GetWindowRect(hwnd, &rc);
3630 trace("main window %p: (%d,%d)-(%d,%d)\n", hwnd, rc.left, rc.top, rc.right, rc.bottom);
3632 popup = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP,
3633 rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
3634 hwnd, 0, 0, NULL);
3635 assert(popup != 0);
3636 ShowWindow(popup, SW_SHOW);
3637 UpdateWindow(popup);
3638 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3640 GetWindowRect(popup, &rc);
3641 trace("popup window %p: (%d,%d)-(%d,%d)\n", popup, rc.left, rc.top, rc.right, rc.bottom);
3643 x = rc.left + (rc.right - rc.left) / 2;
3644 y = rc.top + (rc.bottom - rc.top) / 2;
3645 trace("setting cursor to (%d,%d)\n", x, y);
3647 SetCursorPos(x, y);
3648 GetCursorPos(&pt);
3649 if (x != pt.x || y != pt.y)
3651 skip( "failed to set mouse position, skipping mouse input tests\n" );
3652 goto done;
3655 flush_events( TRUE );
3657 /* Check that setting the same position may generate WM_MOUSEMOVE */
3658 SetCursorPos(x, y);
3659 msg.message = 0;
3660 ret = peek_message(&msg);
3661 if (ret)
3663 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n",
3664 msg.hwnd, msg.message);
3665 ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n",
3666 x, y, msg.pt.x, msg.pt.y);
3669 /* force the system to update its internal queue mouse position,
3670 * otherwise it won't generate relative mouse movements below.
3672 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3673 flush_events( TRUE );
3675 msg.message = 0;
3676 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3677 flush_events( FALSE );
3678 /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */
3679 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3681 if (ignore_message(msg.message)) continue;
3682 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE,
3683 "hwnd %p message %04x\n", msg.hwnd, msg.message);
3684 DispatchMessageA(&msg);
3686 ret = peek_message(&msg);
3687 ok( !ret, "message %04x available\n", msg.message);
3689 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3690 ShowWindow(popup, SW_HIDE);
3691 ret = wait_for_message( &msg );
3692 if (ret)
3693 ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3694 flush_events( TRUE );
3696 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3697 ShowWindow(hwnd, SW_HIDE);
3698 ret = wait_for_message( &msg );
3699 ok( !ret, "message %04x available\n", msg.message);
3700 flush_events( TRUE );
3702 /* test mouse clicks */
3704 ShowWindow(hwnd, SW_SHOW);
3705 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3706 flush_events( TRUE );
3707 ShowWindow(popup, SW_SHOW);
3708 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3709 flush_events( TRUE );
3711 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3712 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3713 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3714 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3716 ret = wait_for_message( &msg );
3717 if (!ret)
3719 skip( "simulating mouse click doesn't work, skipping mouse button tests\n" );
3720 goto done;
3722 if (msg.message == WM_MOUSEMOVE) /* win2k has an extra WM_MOUSEMOVE here */
3724 ret = wait_for_message( &msg );
3725 ok(ret, "no message available\n");
3728 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3729 msg.hwnd, popup, msg.message);
3731 ret = wait_for_message( &msg );
3732 ok(ret, "no message available\n");
3733 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3734 msg.hwnd, popup, msg.message);
3736 ret = wait_for_message( &msg );
3737 ok(ret, "no message available\n");
3738 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p/%p message %04x\n",
3739 msg.hwnd, popup, msg.message);
3741 ret = wait_for_message( &msg );
3742 ok(ret, "no message available\n");
3743 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3744 msg.hwnd, popup, msg.message);
3746 ret = peek_message(&msg);
3747 ok(!ret, "message %04x available\n", msg.message);
3749 ShowWindow(popup, SW_HIDE);
3750 flush_events( TRUE );
3752 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3753 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3754 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3755 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3757 ret = wait_for_message( &msg );
3758 ok(ret, "no message available\n");
3759 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3760 msg.hwnd, hwnd, msg.message);
3761 ret = wait_for_message( &msg );
3762 ok(ret, "no message available\n");
3763 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3764 msg.hwnd, hwnd, msg.message);
3766 test_lbuttondown_flag = TRUE;
3767 SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0);
3768 test_lbuttondown_flag = FALSE;
3770 ret = wait_for_message( &msg );
3771 ok(ret, "no message available\n");
3772 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3773 msg.hwnd, popup, msg.message);
3774 ok(peek_message(&msg), "no message available\n");
3775 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3776 msg.hwnd, popup, msg.message);
3777 ok(peek_message(&msg), "no message available\n");
3779 /* Test WM_MOUSEACTIVATE */
3780 #define TEST_MOUSEACTIVATE(A,B) \
3781 res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \
3782 ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res);
3784 TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE);
3785 TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE);
3786 TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE);
3787 TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE);
3788 TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE);
3789 TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE);
3790 TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE);
3791 TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE);
3792 TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE);
3793 TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE);
3794 TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE);
3795 TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE);
3796 TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE);
3797 TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE);
3798 TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE);
3799 TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE);
3800 TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE);
3801 TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE);
3802 TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE);
3803 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE);
3804 TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE);
3805 TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE);
3806 TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE);
3807 TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE);
3809 done:
3810 /* Clear any messages left behind by WM_MOUSEACTIVATE tests */
3811 flush_events( TRUE );
3813 DestroyWindow(popup);
3816 static void test_validatergn(HWND hwnd)
3818 HWND child;
3819 RECT rc, rc2;
3820 HRGN rgn;
3821 int ret;
3822 child = CreateWindowExA(0, "static", NULL, WS_CHILD| WS_VISIBLE, 10, 10, 10, 10, hwnd, 0, 0, NULL);
3823 ShowWindow(hwnd, SW_SHOW);
3824 UpdateWindow( hwnd);
3825 /* test that ValidateRect validates children*/
3826 InvalidateRect( child, NULL, 1);
3827 GetWindowRect( child, &rc);
3828 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3829 ret = GetUpdateRect( child, &rc2, 0);
3830 ok( ret == 1, "Expected GetUpdateRect to return non-zero, got %d\n", ret);
3831 ok( rc2.right > rc2.left && rc2.bottom > rc2.top,
3832 "Update rectangle is empty!\n");
3833 ValidateRect( hwnd, &rc);
3834 ret = GetUpdateRect( child, &rc2, 0);
3835 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3836 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3837 "Update rectangle %d,%d-%d,%d is not empty!\n", rc2.left, rc2.top,
3838 rc2.right, rc2.bottom);
3840 /* now test ValidateRgn */
3841 InvalidateRect( child, NULL, 1);
3842 GetWindowRect( child, &rc);
3843 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3844 rgn = CreateRectRgnIndirect( &rc);
3845 ValidateRgn( hwnd, rgn);
3846 ret = GetUpdateRect( child, &rc2, 0);
3847 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3848 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3849 "Update rectangle %d,%d-%d,%d is not empty!\n", rc2.left, rc2.top,
3850 rc2.right, rc2.bottom);
3852 DeleteObject( rgn);
3853 DestroyWindow( child );
3856 static void nccalchelper(HWND hwnd, INT x, INT y, RECT *prc)
3858 RECT rc;
3859 MoveWindow( hwnd, 0, 0, x, y, 0);
3860 GetWindowRect( hwnd, prc);
3861 rc = *prc;
3862 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc);
3863 trace("window rect is %d,%d - %d,%d, nccalc rect is %d,%d - %d,%d\n",
3864 rc.left,rc.top,rc.right,rc.bottom, prc->left,prc->top,prc->right,prc->bottom);
3867 static void test_nccalcscroll(HWND parent)
3869 RECT rc1;
3870 INT sbheight = GetSystemMetrics( SM_CYHSCROLL);
3871 INT sbwidth = GetSystemMetrics( SM_CXVSCROLL);
3872 HWND hwnd = CreateWindowExA(0, "static", NULL,
3873 WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL ,
3874 10, 10, 200, 200, parent, 0, 0, NULL);
3875 ShowWindow( parent, SW_SHOW);
3876 UpdateWindow( parent);
3878 /* test window too low for a horizontal scroll bar */
3879 nccalchelper( hwnd, 100, sbheight, &rc1);
3880 ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %d,%d - %d,%d\n",
3881 sbheight, rc1.left, rc1.top, rc1.right, rc1.bottom);
3883 /* test window just high enough for a horizontal scroll bar */
3884 nccalchelper( hwnd, 100, sbheight + 1, &rc1);
3885 ok( rc1.bottom - rc1.top == 1, "Height should be %d size is %d,%d - %d,%d\n",
3886 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
3888 /* test window too narrow for a vertical scroll bar */
3889 nccalchelper( hwnd, sbwidth - 1, 100, &rc1);
3890 ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %d,%d - %d,%d\n",
3891 sbwidth - 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
3893 /* test window just wide enough for a vertical scroll bar */
3894 nccalchelper( hwnd, sbwidth, 100, &rc1);
3895 ok( rc1.right - rc1.left == 0, "Width should be %d size is %d,%d - %d,%d\n",
3896 0, rc1.left, rc1.top, rc1.right, rc1.bottom);
3898 /* same test, but with client edge: not enough width */
3899 SetWindowLongA( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLongA( hwnd, GWL_EXSTYLE));
3900 nccalchelper( hwnd, sbwidth, 100, &rc1);
3901 ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
3902 "Width should be %d size is %d,%d - %d,%d\n",
3903 sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), rc1.left, rc1.top, rc1.right, rc1.bottom);
3905 DestroyWindow( hwnd);
3908 static void test_SetParent(void)
3910 HWND desktop = GetDesktopWindow();
3911 HMENU hMenu;
3912 HWND ret, parent, child1, child2, child3, child4, sibling, popup;
3913 BOOL bret;
3915 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3916 100, 100, 200, 200, 0, 0, 0, NULL);
3917 assert(parent != 0);
3918 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3919 0, 0, 50, 50, parent, 0, 0, NULL);
3920 assert(child1 != 0);
3921 child2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3922 0, 0, 50, 50, child1, 0, 0, NULL);
3923 assert(child2 != 0);
3924 child3 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3925 0, 0, 50, 50, child2, 0, 0, NULL);
3926 assert(child3 != 0);
3927 child4 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3928 0, 0, 50, 50, child3, 0, 0, NULL);
3929 assert(child4 != 0);
3931 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
3932 parent, child1, child2, child3, child4);
3934 check_parents(parent, desktop, 0, 0, 0, parent, parent);
3935 check_parents(child1, parent, parent, parent, 0, parent, parent);
3936 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3937 check_parents(child3, child2, child2, child2, 0, child2, parent);
3938 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3940 ok(!IsChild(desktop, parent), "wrong parent/child %p/%p\n", desktop, parent);
3941 ok(!IsChild(desktop, child1), "wrong parent/child %p/%p\n", desktop, child1);
3942 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
3943 ok(!IsChild(desktop, child3), "wrong parent/child %p/%p\n", desktop, child3);
3944 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
3946 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
3947 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
3948 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
3949 ok(!IsChild(child1, child2), "wrong parent/child %p/%p\n", child1, child2);
3950 ok(!IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
3951 ok(IsChild(child2, child3), "wrong parent/child %p/%p\n", child2, child3);
3952 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
3953 ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
3954 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
3956 if (!is_win9x) /* Win9x doesn't survive this test */
3958 ok(!SetParent(parent, child1), "SetParent should fail\n");
3959 ok(!SetParent(child2, child3), "SetParent should fail\n");
3960 ok(SetParent(child1, parent) != 0, "SetParent should not fail\n");
3961 ret = SetParent(parent, child2);
3962 todo_wine ok( !ret || broken( ret != 0 ), "SetParent should fail\n");
3963 if (ret) /* nt4, win2k */
3965 ret = SetParent(parent, child3);
3966 ok(ret != 0, "SetParent should not fail\n");
3967 ret = SetParent(child2, parent);
3968 ok(!ret, "SetParent should fail\n");
3969 ret = SetParent(parent, child4);
3970 ok(ret != 0, "SetParent should not fail\n");
3971 check_parents(parent, child4, child4, 0, 0, child4, parent);
3972 check_parents(child1, parent, parent, parent, 0, child4, parent);
3973 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3974 check_parents(child3, child2, child2, child2, 0, child2, parent);
3975 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3977 else
3979 ret = SetParent(parent, child3);
3980 ok(ret != 0, "SetParent should not fail\n");
3981 ret = SetParent(child2, parent);
3982 ok(!ret, "SetParent should fail\n");
3983 ret = SetParent(parent, child4);
3984 ok(!ret, "SetParent should fail\n");
3985 check_parents(parent, child3, child3, 0, 0, child2, parent);
3986 check_parents(child1, parent, parent, parent, 0, child2, parent);
3987 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3988 check_parents(child3, child2, child2, child2, 0, child2, parent);
3989 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3992 else
3993 skip("Win9x/WinMe crash\n");
3995 hMenu = CreateMenu();
3996 sibling = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3997 100, 100, 200, 200, 0, hMenu, 0, NULL);
3998 assert(sibling != 0);
4000 ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n");
4001 ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n");
4003 ok(SetParent(parent, desktop) != 0, "SetParent should not fail\n");
4004 ok(SetParent(child4, child3) != 0, "SetParent should not fail\n");
4005 ok(SetParent(child3, child2) != 0, "SetParent should not fail\n");
4006 ok(SetParent(child2, child1) != 0, "SetParent should not fail\n");
4007 ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
4008 SetWindowLongW(child4, GWL_STYLE, WS_CHILD);
4009 ok(IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
4010 ok(IsChild(child2, child4), "wrong parent/child %p/%p\n", child2, child4);
4011 ok(!IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4);
4012 SetWindowLongW(child2, GWL_STYLE, WS_CHILD);
4013 ok(IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4);
4014 ok(IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
4016 ok(DestroyWindow(parent), "DestroyWindow() failed\n");
4018 ok(!IsWindow(parent), "parent still exists\n");
4019 ok(!IsWindow(sibling), "sibling still exists\n");
4020 ok(!IsWindow(child1), "child1 still exists\n");
4021 ok(!IsWindow(child2), "child2 still exists\n");
4022 ok(!IsWindow(child3), "child3 still exists\n");
4023 ok(!IsWindow(child4), "child4 still exists\n");
4025 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
4026 100, 100, 200, 200, 0, 0, 0, NULL);
4027 assert(parent != 0);
4028 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
4029 0, 0, 50, 50, parent, 0, 0, NULL);
4030 assert(child1 != 0);
4031 popup = CreateWindowExA(0, "static", NULL, WS_POPUP,
4032 0, 0, 50, 50, 0, 0, 0, NULL);
4033 assert(popup != 0);
4035 trace("parent %p, child %p, popup %p\n", parent, child1, popup);
4037 check_parents(parent, desktop, 0, 0, 0, parent, parent);
4038 check_parents(child1, parent, parent, parent, 0, parent, parent);
4039 check_parents(popup, desktop, 0, 0, 0, popup, popup);
4041 SetActiveWindow(parent);
4042 SetFocus(parent);
4043 check_active_state(parent, 0, parent);
4045 ret = SetParent(popup, child1);
4046 ok(ret == desktop, "expected %p, got %p\n", desktop, ret);
4047 check_parents(popup, child1, child1, 0, 0, parent, popup);
4048 check_active_state(popup, 0, popup);
4050 SetActiveWindow(parent);
4051 SetFocus(popup);
4052 check_active_state(popup, 0, popup);
4054 EnableWindow(child1, FALSE);
4055 check_active_state(popup, 0, popup);
4056 SetFocus(parent);
4057 check_active_state(parent, 0, parent);
4058 SetFocus(popup);
4059 check_active_state(popup, 0, popup);
4060 EnableWindow(child1, TRUE);
4062 ShowWindow(child1, SW_MINIMIZE);
4063 SetFocus(parent);
4064 check_active_state(parent, 0, parent);
4065 SetFocus(popup);
4066 check_active_state(popup, 0, popup);
4067 ShowWindow(child1, SW_HIDE);
4069 SetActiveWindow(parent);
4070 SetFocus(parent);
4071 check_active_state(parent, 0, parent);
4073 bret = SetForegroundWindow(popup);
4074 ok(bret, "SetForegroundWindow() failed\n");
4075 check_active_state(popup, popup, popup);
4077 ShowWindow(parent, SW_SHOW);
4078 SetActiveWindow(popup);
4079 ok(DestroyWindow(popup), "DestroyWindow() failed\n");
4080 check_active_state(parent, parent, parent);
4082 ok(DestroyWindow(parent), "DestroyWindow() failed\n");
4084 ok(!IsWindow(parent), "parent still exists\n");
4085 ok(!IsWindow(child1), "child1 still exists\n");
4086 ok(!IsWindow(popup), "popup still exists\n");
4089 static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4091 LPCREATESTRUCTA lpcs;
4092 LPSTYLESTRUCT lpss;
4094 switch (msg)
4096 case WM_NCCREATE:
4097 case WM_CREATE:
4098 lpcs = (LPCREATESTRUCTA)lparam;
4099 lpss = lpcs->lpCreateParams;
4100 if (lpss)
4102 if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) ||
4103 ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) &&
4104 (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME))))
4105 ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n");
4106 else
4107 ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n");
4109 ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE),
4110 "Ex style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
4111 lpss->styleOld, lpcs->dwExStyle);
4113 ok(lpss->styleNew == lpcs->style,
4114 "Style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
4115 lpss->styleNew, lpcs->style);
4117 break;
4119 return DefWindowProcA(hwnd, msg, wparam, lparam);
4122 static ATOM atomStyleCheckClass;
4124 static void register_style_check_class(void)
4126 WNDCLASSA wc =
4129 StyleCheckProc,
4132 GetModuleHandleA(NULL),
4133 NULL,
4134 LoadCursorA(0, (LPCSTR)IDC_ARROW),
4135 (HBRUSH)(COLOR_BTNFACE+1),
4136 NULL,
4137 "WineStyleCheck",
4140 atomStyleCheckClass = RegisterClassA(&wc);
4141 assert(atomStyleCheckClass);
4144 static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut)
4146 DWORD dwActualStyle;
4147 DWORD dwActualExStyle;
4148 STYLESTRUCT ss;
4149 HWND hwnd;
4150 HWND hwndParent = NULL;
4152 ss.styleNew = dwStyleIn;
4153 ss.styleOld = dwExStyleIn;
4155 if (dwStyleIn & WS_CHILD)
4157 hwndParent = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL,
4158 WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4161 hwnd = CreateWindowExA(dwExStyleIn, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL,
4162 dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss);
4163 assert(hwnd);
4165 flush_events( TRUE );
4167 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4168 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4169 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4170 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4172 /* try setting the styles explicitly */
4173 SetWindowLongA( hwnd, GWL_EXSTYLE, dwExStyleIn );
4174 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4175 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4176 /* WS_EX_WINDOWEDGE can't always be changed */
4177 if (dwExStyleIn & WS_EX_DLGMODALFRAME)
4178 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4179 else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE))
4180 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4181 else
4182 dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
4183 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4184 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4186 SetWindowLongA( hwnd, GWL_STYLE, dwStyleIn );
4187 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE);
4188 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
4189 /* WS_CLIPSIBLINGS can't be reset on top-level windows */
4190 if ((dwStyleIn & (WS_CHILD|WS_POPUP)) == WS_CHILD) dwStyleOut = dwStyleIn;
4191 else dwStyleOut = dwStyleIn | WS_CLIPSIBLINGS;
4192 /* WS_EX_WINDOWEDGE can't always be changed */
4193 if (dwExStyleIn & WS_EX_DLGMODALFRAME)
4194 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4195 else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE))
4196 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
4197 else
4198 dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
4199 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle);
4200 /* FIXME: Remove the condition below once Wine is fixed */
4201 todo_wine_if (dwActualExStyle != dwExStyleOut)
4202 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle);
4204 DestroyWindow(hwnd);
4205 if (hwndParent) DestroyWindow(hwndParent);
4208 /* tests what window styles the window manager automatically adds */
4209 static void test_window_styles(void)
4211 register_style_check_class();
4213 check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4214 check_window_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4215 check_window_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
4216 check_window_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE);
4217 check_window_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE);
4218 check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
4219 check_window_style(WS_CHILD, 0, WS_CHILD, 0);
4220 check_window_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4221 check_window_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE);
4222 check_window_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE);
4223 check_window_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE);
4224 check_window_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE);
4225 check_window_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE);
4226 check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4227 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4228 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4229 check_window_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4230 check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4231 check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4232 check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4233 check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4234 check_window_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW);
4235 check_window_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4236 check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4237 check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW);
4238 check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0);
4239 check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0);
4240 check_window_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4241 check_window_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4242 check_window_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4243 check_window_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4244 check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE);
4245 check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE);
4247 if (pGetLayeredWindowAttributes)
4249 check_window_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE);
4250 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE);
4251 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION,
4252 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE);
4256 static INT_PTR WINAPI empty_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4258 return 0;
4261 static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_out, DWORD ex_style_out)
4263 struct
4265 DLGTEMPLATE dt;
4266 WORD menu_name;
4267 WORD class_id;
4268 WORD class_atom;
4269 WCHAR caption[1];
4270 } dlg_data;
4271 DWORD style, ex_style;
4272 HWND hwnd, parent = 0;
4274 if (style_in & WS_CHILD)
4275 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
4276 0, 0, 0, 0, NULL, NULL, NULL, NULL);
4278 dlg_data.dt.style = style_in;
4279 dlg_data.dt.dwExtendedStyle = ex_style_in;
4280 dlg_data.dt.cdit = 0;
4281 dlg_data.dt.x = 0;
4282 dlg_data.dt.y = 0;
4283 dlg_data.dt.cx = 100;
4284 dlg_data.dt.cy = 100;
4285 dlg_data.menu_name = 0;
4286 dlg_data.class_id = 0;
4287 dlg_data.class_atom = 0;
4288 dlg_data.caption[0] = 0;
4290 hwnd = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc, 0);
4291 ok(hwnd != 0, "dialog creation failed, style %#x, exstyle %#x\n", style_in, ex_style_in);
4293 flush_events( TRUE );
4295 style = GetWindowLongA(hwnd, GWL_STYLE);
4296 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4297 ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
4298 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4300 /* try setting the styles explicitly */
4301 SetWindowLongA(hwnd, GWL_EXSTYLE, ex_style_in);
4302 style = GetWindowLongA(hwnd, GWL_STYLE);
4303 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4304 ok(style == (style_out | DS_3DLOOK), "got %#x\n", style);
4305 /* WS_EX_WINDOWEDGE can't always be changed */
4306 if (ex_style_in & WS_EX_DLGMODALFRAME)
4307 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4308 else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE))
4309 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4310 else
4311 ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE;
4312 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4314 SetWindowLongA(hwnd, GWL_STYLE, style_in);
4315 style = GetWindowLongA(hwnd, GWL_STYLE);
4316 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
4317 /* WS_CLIPSIBLINGS can't be reset on top-level windows */
4318 if ((style_in & (WS_CHILD | WS_POPUP)) == WS_CHILD) style_out = style_in;
4319 else style_out = style_in | WS_CLIPSIBLINGS;
4320 ok(style == style_out, "expected style %#x, got %#x\n", style_out, style);
4321 /* WS_EX_WINDOWEDGE can't always be changed */
4322 if (ex_style_in & WS_EX_DLGMODALFRAME)
4323 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4324 else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE))
4325 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE;
4326 else
4327 ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE;
4328 /* FIXME: Remove the condition below once Wine is fixed */
4329 todo_wine_if (ex_style != ex_style_out)
4330 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style);
4332 DestroyWindow(hwnd);
4333 DestroyWindow(parent);
4336 static void test_dialog_styles(void)
4338 check_dialog_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4339 check_dialog_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4340 check_dialog_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4341 check_dialog_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4342 check_dialog_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4343 check_dialog_style(DS_CONTROL, 0, WS_CLIPSIBLINGS|WS_CAPTION|DS_CONTROL, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4344 check_dialog_style(WS_CAPTION, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4345 check_dialog_style(WS_BORDER, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4346 check_dialog_style(WS_DLGFRAME, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4347 check_dialog_style(WS_BORDER|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4348 check_dialog_style(WS_DLGFRAME|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4349 check_dialog_style(WS_CAPTION|WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4350 check_dialog_style(WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4351 check_dialog_style(WS_CAPTION|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4352 check_dialog_style(WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4353 check_dialog_style(WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4354 check_dialog_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4355 check_dialog_style(WS_CHILD, 0, WS_CHILD, 0);
4356 check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4357 check_dialog_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE);
4358 check_dialog_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE);
4359 check_dialog_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE);
4360 check_dialog_style(WS_CHILD|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4361 check_dialog_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE);
4362 check_dialog_style(WS_CHILD|WS_BORDER, 0, WS_CHILD|WS_BORDER, 0);
4363 check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE);
4364 check_dialog_style(WS_CHILD|WS_BORDER|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4365 check_dialog_style(WS_CHILD|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4366 check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE);
4367 check_dialog_style(WS_CHILD|WS_SYSMENU, 0, WS_CHILD|WS_SYSMENU, 0);
4368 check_dialog_style(WS_CHILD|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4369 check_dialog_style(WS_CHILD|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4370 check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT);
4371 check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4372 check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4373 check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
4374 check_dialog_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4375 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4376 check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4377 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4378 check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE);
4379 check_dialog_style(WS_CHILD|WS_POPUP|DS_CONTROL, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT);
4380 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4381 check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER, 0, WS_CHILD|WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, 0);
4382 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4383 check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4384 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4385 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
4386 check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, 0);
4387 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4388 check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4389 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4390 check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW);
4391 check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0);
4392 check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
4393 check_dialog_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_CONTROLPARENT);
4394 check_dialog_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4395 check_dialog_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4396 check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4397 check_dialog_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4398 check_dialog_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4399 check_dialog_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT);
4400 check_dialog_style(WS_POPUP|DS_CONTROL, 0, WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT);
4401 check_dialog_style(WS_POPUP|WS_CAPTION, 0, WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4402 check_dialog_style(WS_POPUP|WS_BORDER, 0, WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4403 check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4404 check_dialog_style(WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4405 check_dialog_style(WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4406 check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4407 check_dialog_style(WS_POPUP|WS_SYSMENU, 0, WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4408 check_dialog_style(WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4409 check_dialog_style(WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4410 check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT);
4411 check_dialog_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4412 check_dialog_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4414 if (pGetLayeredWindowAttributes)
4416 check_dialog_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4417 check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4418 check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION,
4419 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT);
4423 static void test_scrollwindow( HWND hwnd)
4425 HDC hdc;
4426 RECT rc, rc2, rc3;
4427 COLORREF colr;
4429 ShowWindow( hwnd, SW_SHOW);
4430 UpdateWindow( hwnd);
4431 flush_events( TRUE );
4432 GetClientRect( hwnd, &rc);
4433 hdc = GetDC( hwnd);
4434 /* test ScrollWindow(Ex) with no clip rectangle */
4435 /* paint the lower half of the window black */
4436 rc2 = rc;
4437 rc2.top = ( rc2.top + rc2.bottom) / 2;
4438 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4439 /* paint the upper half of the window white */
4440 rc2.bottom = rc2.top;
4441 rc2.top =0;
4442 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
4443 /* scroll lower half up */
4444 rc2 = rc;
4445 rc2.top = ( rc2.top + rc2.bottom) / 2;
4446 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, NULL, NULL, NULL, SW_ERASE);
4447 flush_events(FALSE);
4448 /* expected: black should have scrolled to the upper half */
4449 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 );
4450 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4451 /* Repeat that test of ScrollWindow(Ex) now with clip rectangle */
4452 /* paint the lower half of the window black */
4453 rc2 = rc;
4454 rc2.top = ( rc2.top + rc2.bottom) / 2;
4455 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4456 /* paint the upper half of the window white */
4457 rc2.bottom = rc2.top;
4458 rc2.top =0;
4459 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
4460 /* scroll lower half up */
4461 rc2 = rc;
4462 rc2.top = ( rc2.top + rc2.bottom) / 2;
4463 rc3 = rc;
4464 rc3.left = rc3.right / 4;
4465 rc3.right -= rc3.right / 4;
4466 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, &rc3, NULL, NULL, SW_ERASE);
4467 flush_events(FALSE);
4468 /* expected: black should have scrolled to the upper half */
4469 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 );
4470 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4472 /* clean up */
4473 ReleaseDC( hwnd, hdc);
4476 static void test_scrollvalidate( HWND parent)
4478 HDC hdc;
4479 HRGN hrgn=CreateRectRgn(0,0,0,0);
4480 HRGN exprgn, tmprgn, clipping;
4481 RECT rc, rcu, cliprc;
4482 /* create two overlapping child windows. The visual region
4483 * of hwnd1 is clipped by the overlapping part of
4484 * hwnd2 because of the WS_CLIPSIBLING style */
4485 HWND hwnd1, hwnd2;
4487 clipping = CreateRectRgn(0,0,0,0);
4488 tmprgn = CreateRectRgn(0,0,0,0);
4489 exprgn = CreateRectRgn(0,0,0,0);
4490 hwnd2 = CreateWindowExA(0, "static", NULL,
4491 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
4492 75, 30, 100, 100, parent, 0, 0, NULL);
4493 hwnd1 = CreateWindowExA(0, "static", NULL,
4494 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
4495 25, 50, 100, 100, parent, 0, 0, NULL);
4496 ShowWindow( parent, SW_SHOW);
4497 UpdateWindow( parent);
4498 GetClientRect( hwnd1, &rc);
4499 cliprc=rc;
4500 SetRectRgn( clipping, 10, 10, 90, 90);
4501 hdc = GetDC( hwnd1);
4502 /* for a visual touch */
4503 TextOutA( hdc, 0,10, "0123456789", 10);
4504 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
4505 if (winetest_debug > 0) dump_region(hrgn);
4506 /* create a region with what is expected */
4507 SetRectRgn( exprgn, 39,0,49,74);
4508 SetRectRgn( tmprgn, 88,79,98,93);
4509 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4510 SetRectRgn( tmprgn, 0,93,98,98);
4511 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4512 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4513 trace("update rect is %d,%d - %d,%d\n",
4514 rcu.left,rcu.top,rcu.right,rcu.bottom);
4515 /* now with clipping region */
4516 SelectClipRgn( hdc, clipping);
4517 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
4518 if (winetest_debug > 0) dump_region(hrgn);
4519 /* create a region with what is expected */
4520 SetRectRgn( exprgn, 39,10,49,74);
4521 SetRectRgn( tmprgn, 80,79,90,85);
4522 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4523 SetRectRgn( tmprgn, 10,85,90,90);
4524 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4525 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4526 trace("update rect is %d,%d - %d,%d\n",
4527 rcu.left,rcu.top,rcu.right,rcu.bottom);
4528 ReleaseDC( hwnd1, hdc);
4530 /* test scrolling a window with an update region */
4531 DestroyWindow( hwnd2);
4532 ValidateRect( hwnd1, NULL);
4533 SetRect( &rc, 40,40, 50,50);
4534 InvalidateRect( hwnd1, &rc, 1);
4535 GetClientRect( hwnd1, &rc);
4536 cliprc=rc;
4537 ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
4538 SW_SCROLLCHILDREN | SW_INVALIDATE);
4539 if (winetest_debug > 0) dump_region(hrgn);
4540 SetRectRgn( exprgn, 88,0,98,98);
4541 SetRectRgn( tmprgn, 30, 40, 50, 50);
4542 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4543 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4545 /* clear an update region */
4546 UpdateWindow( hwnd1 );
4548 SetRect( &rc, 0,40, 100,60);
4549 SetRect( &cliprc, 0,0, 100,100);
4550 ScrollWindowEx( hwnd1, 0, -25, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
4551 if (winetest_debug > 0) dump_region( hrgn );
4552 SetRectRgn( exprgn, 0, 40, 98, 60 );
4553 ok( EqualRgn( exprgn, hrgn), "wrong update region in excessive scroll\n");
4555 /* now test ScrollWindowEx with a combination of
4556 * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */
4557 /* make hwnd2 the child of hwnd1 */
4558 hwnd2 = CreateWindowExA(0, "static", NULL,
4559 WS_CHILD| WS_VISIBLE | WS_BORDER ,
4560 50, 50, 100, 100, hwnd1, 0, 0, NULL);
4561 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS);
4562 GetClientRect( hwnd1, &rc);
4563 cliprc=rc;
4565 /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */
4566 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
4567 ValidateRect( hwnd1, NULL);
4568 ValidateRect( hwnd2, NULL);
4569 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
4570 SW_SCROLLCHILDREN | SW_INVALIDATE);
4571 if (winetest_debug > 0) dump_region(hrgn);
4572 SetRectRgn( exprgn, 88,0,98,88);
4573 SetRectRgn( tmprgn, 0,88,98,98);
4574 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4575 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4577 /* SW_SCROLLCHILDREN */
4578 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
4579 ValidateRect( hwnd1, NULL);
4580 ValidateRect( hwnd2, NULL);
4581 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE);
4582 if (winetest_debug > 0) dump_region(hrgn);
4583 /* expected region is the same as in previous test */
4584 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4586 /* no SW_SCROLLCHILDREN */
4587 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
4588 ValidateRect( hwnd1, NULL);
4589 ValidateRect( hwnd2, NULL);
4590 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
4591 if (winetest_debug > 0) dump_region(hrgn);
4592 /* expected region is the same as in previous test */
4593 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4595 /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */
4596 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
4597 ValidateRect( hwnd1, NULL);
4598 ValidateRect( hwnd2, NULL);
4599 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
4600 if (winetest_debug > 0) dump_region(hrgn);
4601 SetRectRgn( exprgn, 88,0,98,20);
4602 SetRectRgn( tmprgn, 20,20,98,30);
4603 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4604 SetRectRgn( tmprgn, 20,30,30,88);
4605 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4606 SetRectRgn( tmprgn, 0,88,30,98);
4607 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
4608 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
4610 /* clean up */
4611 DeleteObject( hrgn);
4612 DeleteObject( exprgn);
4613 DeleteObject( tmprgn);
4614 DestroyWindow( hwnd1);
4615 DestroyWindow( hwnd2);
4618 /* couple of tests of return values of scrollbar functions
4619 * called on a scrollbarless window */
4620 static void test_scroll(void)
4622 BOOL ret;
4623 INT min, max;
4624 SCROLLINFO si;
4625 HWND hwnd = CreateWindowExA(0, "Static", "Wine test window",
4626 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP,
4627 100, 100, 200, 200, 0, 0, 0, NULL);
4628 /* horizontal */
4629 ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
4630 if (!ret) /* win9x */
4632 win_skip( "GetScrollRange doesn't work\n" );
4633 DestroyWindow( hwnd);
4634 return;
4636 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
4637 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
4638 si.cbSize = sizeof( si);
4639 si.fMask = SIF_PAGE;
4640 si.nPage = 0xdeadbeef;
4641 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
4642 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
4643 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
4644 /* vertical */
4645 ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
4646 ok( ret, "GetScrollRange returns FALSE\n");
4647 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
4648 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
4649 si.cbSize = sizeof( si);
4650 si.fMask = SIF_PAGE;
4651 si.nPage = 0xdeadbeef;
4652 ret = GetScrollInfo( hwnd, SB_VERT, &si);
4653 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
4654 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
4655 /* clean up */
4656 DestroyWindow( hwnd);
4659 static void test_scrolldc( HWND parent)
4661 HDC hdc;
4662 HRGN exprgn, tmprgn, hrgn;
4663 RECT rc, rc2, rcu, cliprc;
4664 HWND hwnd1;
4665 COLORREF colr;
4667 hrgn = CreateRectRgn(0,0,0,0);
4668 tmprgn = CreateRectRgn(0,0,0,0);
4669 exprgn = CreateRectRgn(0,0,0,0);
4671 hwnd1 = CreateWindowExA(0, "static", NULL,
4672 WS_CHILD| WS_VISIBLE,
4673 25, 50, 100, 100, parent, 0, 0, NULL);
4674 ShowWindow( parent, SW_SHOW);
4675 UpdateWindow( parent);
4676 flush_events( TRUE );
4677 GetClientRect( hwnd1, &rc);
4678 hdc = GetDC( hwnd1);
4679 /* paint the upper half of the window black */
4680 rc2 = rc;
4681 rc2.bottom = ( rc.top + rc.bottom) /2;
4682 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4683 /* clip region is the lower half */
4684 cliprc=rc;
4685 cliprc.top = (rc.top + rc.bottom) /2;
4686 /* test whether scrolled pixels are properly clipped */
4687 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
4688 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4689 /* this scroll should not cause any visible changes */
4690 ScrollDC( hdc, 5, -20, &rc, &cliprc, hrgn, &rcu);
4691 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
4692 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4693 /* test with NULL clip rect */
4694 ScrollDC( hdc, 20, -20, &rc, NULL, hrgn, &rcu);
4695 /*FillRgn(hdc, hrgn, GetStockObject(WHITE_BRUSH));*/
4696 trace("update rect: %d,%d - %d,%d\n",
4697 rcu.left, rcu.top, rcu.right, rcu.bottom);
4698 if (winetest_debug > 0) dump_region(hrgn);
4699 SetRect(&rc2, 0, 0, 100, 100);
4700 ok(EqualRect(&rcu, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
4701 rcu.left, rcu.top, rcu.right, rcu.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
4703 SetRectRgn( exprgn, 0, 0, 20, 80);
4704 SetRectRgn( tmprgn, 0, 80, 100, 100);
4705 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
4706 if (winetest_debug > 0) dump_region(exprgn);
4707 ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
4708 /* test clip rect > scroll rect */
4709 FillRect( hdc, &rc, GetStockObject(WHITE_BRUSH));
4710 rc2=rc;
4711 InflateRect( &rc2, -(rc.right-rc.left)/4, -(rc.bottom-rc.top)/4);
4712 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4713 ScrollDC( hdc, 10, 10, &rc2, &rc, hrgn, &rcu);
4714 SetRectRgn( exprgn, 25, 25, 75, 35);
4715 SetRectRgn( tmprgn, 25, 35, 35, 75);
4716 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
4717 ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
4718 trace("update rect: %d,%d - %d,%d\n",
4719 rcu.left, rcu.top, rcu.right, rcu.bottom);
4720 if (winetest_debug > 0) dump_region(hrgn);
4722 /* clean up */
4723 DeleteObject(hrgn);
4724 DeleteObject(exprgn);
4725 DeleteObject(tmprgn);
4726 DestroyWindow(hwnd1);
4729 static void test_params(void)
4731 HWND hwnd;
4732 INT rc;
4734 ok(!IsWindow(0), "IsWindow(0)\n");
4735 ok(!IsWindow(HWND_BROADCAST), "IsWindow(HWND_BROADCAST)\n");
4736 ok(!IsWindow(HWND_TOPMOST), "IsWindow(HWND_TOPMOST)\n");
4738 /* Just a param check */
4739 if (pGetMonitorInfoA)
4741 SetLastError(0xdeadbeef);
4742 rc = GetWindowTextA(hwndMain2, NULL, 1024);
4743 ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError());
4745 else
4747 /* Skips actually on Win95 and NT4 */
4748 win_skip("Test would crash on Win95\n");
4751 SetLastError(0xdeadbeef);
4752 hwnd=CreateWindowA("LISTBOX", "TestList",
4753 (LBS_STANDARD & ~LBS_SORT),
4754 0, 0, 100, 100,
4755 NULL, (HMENU)1, NULL, 0);
4757 ok(!hwnd || broken(hwnd != NULL), /* w2k3 sp2 */
4758 "CreateWindow with invalid menu handle should fail\n");
4759 if (!hwnd)
4760 ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */
4761 GetLastError() == 0xdeadbeef, /* Win9x */
4762 "wrong last error value %d\n", GetLastError());
4765 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
4767 HWND hwnd = 0;
4769 hwnd = CreateWindowExA(exStyle, class, class, style,
4770 110, 100,
4771 225, 200,
4773 menu ? hmenu : 0,
4774 0, 0);
4775 if (!hwnd) {
4776 trace("Failed to create window class=%s, style=0x%08x, exStyle=0x%08x\n", class, style, exStyle);
4777 return;
4779 ShowWindow(hwnd, SW_SHOW);
4781 test_nonclient_area(hwnd);
4783 SetMenu(hwnd, 0);
4784 DestroyWindow(hwnd);
4787 static BOOL AWR_init(void)
4789 WNDCLASSA class;
4791 class.style = CS_HREDRAW | CS_VREDRAW;
4792 class.lpfnWndProc = DefWindowProcA;
4793 class.cbClsExtra = 0;
4794 class.cbWndExtra = 0;
4795 class.hInstance = 0;
4796 class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
4797 class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
4798 class.hbrBackground = 0;
4799 class.lpszMenuName = 0;
4800 class.lpszClassName = szAWRClass;
4802 if (!RegisterClassA(&class)) {
4803 ok(FALSE, "RegisterClass failed\n");
4804 return FALSE;
4807 hmenu = CreateMenu();
4808 if (!hmenu)
4809 return FALSE;
4810 ok(hmenu != 0, "Failed to create menu\n");
4811 ok(AppendMenuA(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n");
4813 return TRUE;
4817 static void test_AWR_window_size(BOOL menu)
4819 static const DWORD styles[] = {
4820 WS_POPUP, WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, WS_CAPTION, WS_SYSMENU,
4821 WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_HSCROLL, WS_VSCROLL
4823 static const DWORD exStyles[] = {
4824 WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE, WS_EX_APPWINDOW,
4825 WS_EX_DLGMODALFRAME, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE
4828 unsigned int i;
4830 /* A exhaustive check of all the styles takes too long
4831 * so just do a (hopefully representative) sample
4833 for (i = 0; i < COUNTOF(styles); ++i)
4834 test_AWRwindow(szAWRClass, styles[i], 0, menu);
4835 for (i = 0; i < COUNTOF(exStyles); ++i) {
4836 test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu);
4837 test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
4841 static void test_AWR_flags(void)
4843 static const DWORD styles[] = { WS_POPUP, WS_BORDER, WS_DLGFRAME, WS_THICKFRAME };
4844 static const DWORD exStyles[] = { WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
4845 WS_EX_APPWINDOW, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE };
4847 DWORD i, j, k, style, exstyle;
4848 RECT rect, rect2;
4850 for (i = 0; i < (1 << COUNTOF(styles)); i++)
4852 for (k = style = 0; k < COUNTOF(styles); k++) if (i & (1 << k)) style |= styles[k];
4854 for (j = 0; j < (1 << COUNTOF(exStyles)); j++)
4856 for (k = exstyle = 0; k < COUNTOF(exStyles); k++) if (j & (1 << k)) exstyle |= exStyles[k];
4857 SetRect( &rect, 100, 100, 200, 200 );
4858 rect2 = rect;
4859 AdjustWindowRectEx( &rect, style, FALSE, exstyle );
4860 wine_AdjustWindowRectEx( &rect2, style, FALSE, exstyle );
4861 ok( EqualRect( &rect, &rect2 ), "rects do not match: win %d,%d-%d,%d wine %d,%d-%d,%d\n",
4862 rect.left, rect.top, rect.right, rect.bottom,
4863 rect2.left, rect2.top, rect2.right, rect2.bottom );
4867 #undef COUNTOF
4869 #define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
4871 static void test_AdjustWindowRect(void)
4873 if (!AWR_init())
4874 return;
4876 SHOWSYSMETRIC(SM_CYCAPTION);
4877 SHOWSYSMETRIC(SM_CYSMCAPTION);
4878 SHOWSYSMETRIC(SM_CYMENU);
4879 SHOWSYSMETRIC(SM_CXEDGE);
4880 SHOWSYSMETRIC(SM_CYEDGE);
4881 SHOWSYSMETRIC(SM_CXVSCROLL);
4882 SHOWSYSMETRIC(SM_CYHSCROLL);
4883 SHOWSYSMETRIC(SM_CXFRAME);
4884 SHOWSYSMETRIC(SM_CYFRAME);
4885 SHOWSYSMETRIC(SM_CXDLGFRAME);
4886 SHOWSYSMETRIC(SM_CYDLGFRAME);
4887 SHOWSYSMETRIC(SM_CXBORDER);
4888 SHOWSYSMETRIC(SM_CYBORDER);
4890 test_AWR_window_size(FALSE);
4891 test_AWR_window_size(TRUE);
4892 test_AWR_flags();
4894 DestroyMenu(hmenu);
4896 #undef SHOWSYSMETRIC
4899 /* Global variables to trigger exit from loop */
4900 static int redrawComplete, WMPAINT_count;
4902 static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4904 switch (msg)
4906 case WM_PAINT:
4907 trace("doing WM_PAINT %d\n", WMPAINT_count);
4908 WMPAINT_count++;
4909 if (WMPAINT_count > 10 && redrawComplete == 0) {
4910 PAINTSTRUCT ps;
4911 BeginPaint(hwnd, &ps);
4912 EndPaint(hwnd, &ps);
4913 return 1;
4915 return 0;
4917 return DefWindowProcA(hwnd, msg, wparam, lparam);
4920 /* Ensure we exit from RedrawNow regardless of invalidated area */
4921 static void test_redrawnow(void)
4923 WNDCLASSA cls;
4924 HWND hwndMain;
4926 cls.style = CS_DBLCLKS;
4927 cls.lpfnWndProc = redraw_window_procA;
4928 cls.cbClsExtra = 0;
4929 cls.cbWndExtra = 0;
4930 cls.hInstance = GetModuleHandleA(0);
4931 cls.hIcon = 0;
4932 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
4933 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4934 cls.lpszMenuName = NULL;
4935 cls.lpszClassName = "RedrawWindowClass";
4937 if(!RegisterClassA(&cls)) {
4938 trace("Register failed %d\n", GetLastError());
4939 return;
4942 hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
4943 CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL);
4945 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4946 ShowWindow(hwndMain, SW_SHOW);
4947 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4948 RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN);
4949 ok( WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */
4950 "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4951 redrawComplete = TRUE;
4952 ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count);
4954 /* clean up */
4955 DestroyWindow( hwndMain);
4958 struct parentdc_stat {
4959 RECT client;
4960 RECT clip;
4961 RECT paint;
4964 struct parentdc_test {
4965 struct parentdc_stat main, main_todo;
4966 struct parentdc_stat child1, child1_todo;
4967 struct parentdc_stat child2, child2_todo;
4970 static LRESULT WINAPI parentdc_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4972 RECT rc;
4973 PAINTSTRUCT ps;
4975 struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
4977 switch (msg)
4979 case WM_PAINT:
4980 GetClientRect(hwnd, &rc);
4981 CopyRect(&t->client, &rc);
4982 GetWindowRect(hwnd, &rc);
4983 trace("WM_PAINT: hwnd %p, client rect (%d,%d)-(%d,%d), window rect (%d,%d)-(%d,%d)\n", hwnd,
4984 t->client.left, t->client.top, t->client.right, t->client.bottom,
4985 rc.left, rc.top, rc.right, rc.bottom);
4986 BeginPaint(hwnd, &ps);
4987 CopyRect(&t->paint, &ps.rcPaint);
4988 GetClipBox(ps.hdc, &rc);
4989 CopyRect(&t->clip, &rc);
4990 trace("clip rect (%d,%d)-(%d,%d), paint rect (%d,%d)-(%d,%d)\n",
4991 rc.left, rc.top, rc.right, rc.bottom,
4992 ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
4993 EndPaint(hwnd, &ps);
4994 return 0;
4996 return DefWindowProcA(hwnd, msg, wparam, lparam);
4999 static void zero_parentdc_stat(struct parentdc_stat *t)
5001 SetRectEmpty(&t->client);
5002 SetRectEmpty(&t->clip);
5003 SetRectEmpty(&t->paint);
5006 static void zero_parentdc_test(struct parentdc_test *t)
5008 zero_parentdc_stat(&t->main);
5009 zero_parentdc_stat(&t->child1);
5010 zero_parentdc_stat(&t->child2);
5013 #define parentdc_field_ok(t, w, r, f, got) \
5014 ok (t.w.r.f==got.w.r.f, "window " #w ", rect " #r ", field " #f \
5015 ": expected %d, got %d\n", \
5016 t.w.r.f, got.w.r.f)
5018 #define parentdc_todo_field_ok(t, w, r, f, got) \
5019 todo_wine_if (t.w##_todo.r.f) \
5020 parentdc_field_ok(t, w, r, f, got);
5022 #define parentdc_rect_ok(t, w, r, got) \
5023 parentdc_todo_field_ok(t, w, r, left, got); \
5024 parentdc_todo_field_ok(t, w, r, top, got); \
5025 parentdc_todo_field_ok(t, w, r, right, got); \
5026 parentdc_todo_field_ok(t, w, r, bottom, got);
5028 #define parentdc_win_ok(t, w, got) \
5029 parentdc_rect_ok(t, w, client, got); \
5030 parentdc_rect_ok(t, w, clip, got); \
5031 parentdc_rect_ok(t, w, paint, got);
5033 #define parentdc_ok(t, got) \
5034 parentdc_win_ok(t, main, got); \
5035 parentdc_win_ok(t, child1, got); \
5036 parentdc_win_ok(t, child2, got);
5038 static void test_csparentdc(void)
5040 WNDCLASSA clsMain, cls;
5041 HWND hwndMain, hwnd1, hwnd2;
5042 RECT rc;
5044 struct parentdc_test test_answer;
5046 #define nothing_todo {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
5047 const struct parentdc_test test1 =
5049 {{0, 0, 150, 150}, {0, 0, 150, 150}, {0, 0, 150, 150}}, nothing_todo,
5050 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5051 {{0, 0, 40, 40}, {-40, -40, 110, 110}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5054 const struct parentdc_test test2 =
5056 {{0, 0, 150, 150}, {0, 0, 50, 50}, {0, 0, 50, 50}}, nothing_todo,
5057 {{0, 0, 40, 40}, {-20, -20, 30, 30}, {0, 0, 30, 30}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5058 {{0, 0, 40, 40}, {-40, -40, 10, 10}, {0, 0, 10, 10}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5061 const struct parentdc_test test3 =
5063 {{0, 0, 150, 150}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5064 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5065 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5068 const struct parentdc_test test4 =
5070 {{0, 0, 150, 150}, {40, 40, 50, 50}, {40, 40, 50, 50}}, nothing_todo,
5071 {{0, 0, 40, 40}, {20, 20, 30, 30}, {20, 20, 30, 30}}, nothing_todo,
5072 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5075 const struct parentdc_test test5 =
5077 {{0, 0, 150, 150}, {20, 20, 60, 60}, {20, 20, 60, 60}}, nothing_todo,
5078 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5079 {{0, 0, 40, 40}, {-20, -20, 20, 20}, {0, 0, 20, 20}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
5082 const struct parentdc_test test6 =
5084 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5085 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
5086 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5089 const struct parentdc_test test7 =
5091 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5092 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
5093 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
5095 #undef nothing_todo
5097 clsMain.style = CS_DBLCLKS;
5098 clsMain.lpfnWndProc = parentdc_window_procA;
5099 clsMain.cbClsExtra = 0;
5100 clsMain.cbWndExtra = 0;
5101 clsMain.hInstance = GetModuleHandleA(0);
5102 clsMain.hIcon = 0;
5103 clsMain.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5104 clsMain.hbrBackground = GetStockObject(WHITE_BRUSH);
5105 clsMain.lpszMenuName = NULL;
5106 clsMain.lpszClassName = "ParentDcMainWindowClass";
5108 if(!RegisterClassA(&clsMain)) {
5109 trace("Register failed %d\n", GetLastError());
5110 return;
5113 cls.style = CS_DBLCLKS | CS_PARENTDC;
5114 cls.lpfnWndProc = parentdc_window_procA;
5115 cls.cbClsExtra = 0;
5116 cls.cbWndExtra = 0;
5117 cls.hInstance = GetModuleHandleA(0);
5118 cls.hIcon = 0;
5119 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5120 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5121 cls.lpszMenuName = NULL;
5122 cls.lpszClassName = "ParentDcWindowClass";
5124 if(!RegisterClassA(&cls)) {
5125 trace("Register failed %d\n", GetLastError());
5126 return;
5129 SetRect(&rc, 0, 0, 150, 150);
5130 AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
5131 hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
5132 CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL);
5133 SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main);
5134 hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD,
5135 20, 20, 40, 40, hwndMain, NULL, 0, NULL);
5136 SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1);
5137 hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD,
5138 40, 40, 40, 40, hwndMain, NULL, 0, NULL);
5139 SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2);
5140 ShowWindow(hwndMain, SW_SHOW);
5141 ShowWindow(hwnd1, SW_SHOW);
5142 ShowWindow(hwnd2, SW_SHOW);
5143 SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
5144 flush_events( TRUE );
5146 zero_parentdc_test(&test_answer);
5147 InvalidateRect(hwndMain, NULL, TRUE);
5148 flush_events( TRUE );
5149 parentdc_ok(test1, test_answer);
5151 zero_parentdc_test(&test_answer);
5152 SetRect(&rc, 0, 0, 50, 50);
5153 InvalidateRect(hwndMain, &rc, TRUE);
5154 flush_events( TRUE );
5155 parentdc_ok(test2, test_answer);
5157 zero_parentdc_test(&test_answer);
5158 SetRect(&rc, 0, 0, 10, 10);
5159 InvalidateRect(hwndMain, &rc, TRUE);
5160 flush_events( TRUE );
5161 parentdc_ok(test3, test_answer);
5163 zero_parentdc_test(&test_answer);
5164 SetRect(&rc, 40, 40, 50, 50);
5165 InvalidateRect(hwndMain, &rc, TRUE);
5166 flush_events( TRUE );
5167 parentdc_ok(test4, test_answer);
5169 zero_parentdc_test(&test_answer);
5170 SetRect(&rc, 20, 20, 60, 60);
5171 InvalidateRect(hwndMain, &rc, TRUE);
5172 flush_events( TRUE );
5173 parentdc_ok(test5, test_answer);
5175 zero_parentdc_test(&test_answer);
5176 SetRect(&rc, 0, 0, 10, 10);
5177 InvalidateRect(hwnd1, &rc, TRUE);
5178 flush_events( TRUE );
5179 parentdc_ok(test6, test_answer);
5181 zero_parentdc_test(&test_answer);
5182 SetRect(&rc, -5, -5, 65, 65);
5183 InvalidateRect(hwnd1, &rc, TRUE);
5184 flush_events( TRUE );
5185 parentdc_ok(test7, test_answer);
5187 DestroyWindow(hwndMain);
5188 DestroyWindow(hwnd1);
5189 DestroyWindow(hwnd2);
5192 static LRESULT WINAPI def_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5194 return DefWindowProcA(hwnd, msg, wparam, lparam);
5197 static LRESULT WINAPI def_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
5199 return DefWindowProcW(hwnd, msg, wparam, lparam);
5202 static void test_IsWindowUnicode(void)
5204 static const char ansi_class_nameA[] = "ansi class name";
5205 static const WCHAR ansi_class_nameW[] = {'a','n','s','i',' ','c','l','a','s','s',' ','n','a','m','e',0};
5206 static const char unicode_class_nameA[] = "unicode class name";
5207 static const WCHAR unicode_class_nameW[] = {'u','n','i','c','o','d','e',' ','c','l','a','s','s',' ','n','a','m','e',0};
5208 WNDCLASSA classA;
5209 WNDCLASSW classW;
5210 HWND hwnd;
5211 ATOM atom;
5213 memset(&classW, 0, sizeof(classW));
5214 classW.hInstance = GetModuleHandleA(0);
5215 classW.lpfnWndProc = def_window_procW;
5216 classW.lpszClassName = unicode_class_nameW;
5217 if (!RegisterClassW(&classW)) return; /* this catches Win9x as well */
5219 memset(&classA, 0, sizeof(classA));
5220 classA.hInstance = GetModuleHandleA(0);
5221 classA.lpfnWndProc = def_window_procA;
5222 classA.lpszClassName = ansi_class_nameA;
5223 atom = RegisterClassA(&classA);
5224 assert(atom);
5226 /* unicode class: window proc */
5227 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
5228 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5229 assert(hwnd);
5231 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5232 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5233 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5234 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5235 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5237 DestroyWindow(hwnd);
5239 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
5240 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5241 assert(hwnd);
5243 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5244 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5245 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5246 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5247 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5249 DestroyWindow(hwnd);
5251 /* ansi class: window proc */
5252 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
5253 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5254 assert(hwnd);
5256 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5257 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5258 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5259 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5260 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5262 DestroyWindow(hwnd);
5264 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
5265 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5266 assert(hwnd);
5268 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5269 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
5270 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5271 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
5272 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5274 DestroyWindow(hwnd);
5276 /* unicode class: class proc */
5277 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
5278 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5279 assert(hwnd);
5281 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5282 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
5283 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5284 /* do not restore class window proc back to unicode */
5286 DestroyWindow(hwnd);
5288 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
5289 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5290 assert(hwnd);
5292 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5293 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
5294 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5296 DestroyWindow(hwnd);
5298 /* ansi class: class proc */
5299 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
5300 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5301 assert(hwnd);
5303 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5304 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
5305 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
5306 /* do not restore class window proc back to ansi */
5308 DestroyWindow(hwnd);
5310 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
5311 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
5312 assert(hwnd);
5314 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5315 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
5316 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
5318 DestroyWindow(hwnd);
5321 static LRESULT CALLBACK minmax_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
5323 MINMAXINFO *minmax;
5325 if (msg != WM_GETMINMAXINFO)
5326 return DefWindowProcA(hwnd, msg, wp, lp);
5328 minmax = (MINMAXINFO *)lp;
5330 if ((GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD))
5332 minmax->ptReserved.x = 0;
5333 minmax->ptReserved.y = 0;
5334 minmax->ptMaxSize.x = 400;
5335 minmax->ptMaxSize.y = 400;
5336 minmax->ptMaxPosition.x = 300;
5337 minmax->ptMaxPosition.y = 300;
5338 minmax->ptMaxTrackSize.x = 200;
5339 minmax->ptMaxTrackSize.y = 200;
5340 minmax->ptMinTrackSize.x = 100;
5341 minmax->ptMinTrackSize.y = 100;
5343 else
5344 DefWindowProcA(hwnd, msg, wp, lp);
5345 return 1;
5348 static int expected_cx, expected_cy;
5349 static RECT expected_rect, broken_rect;
5351 static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
5353 switch(msg)
5355 case WM_GETMINMAXINFO:
5357 RECT rect;
5358 GetWindowRect( hwnd, &rect );
5359 ok( !rect.left && !rect.top && !rect.right && !rect.bottom,
5360 "wrong rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
5361 return DefWindowProcA(hwnd, msg, wp, lp);
5363 case WM_NCCREATE:
5364 case WM_CREATE:
5366 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
5367 RECT rect;
5368 GetWindowRect( hwnd, &rect );
5369 trace( "hwnd %p msg %x size %dx%d rect %d,%d-%d,%d\n",
5370 hwnd, msg, cs->cx, cs->cy, rect.left, rect.top, rect.right, rect.bottom );
5371 ok( cs->cx == expected_cx || broken(cs->cx == (short)expected_cx),
5372 "wrong x size %d/%d\n", cs->cx, expected_cx );
5373 ok( cs->cy == expected_cy || broken(cs->cy == (short)expected_cy),
5374 "wrong y size %d/%d\n", cs->cy, expected_cy );
5375 ok( (rect.right - rect.left == expected_rect.right - expected_rect.left &&
5376 rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) ||
5377 (rect.right - rect.left == min( 65535, expected_rect.right - expected_rect.left ) &&
5378 rect.bottom - rect.top == min( 65535, expected_rect.bottom - expected_rect.top )) ||
5379 broken( rect.right - rect.left == broken_rect.right - broken_rect.left &&
5380 rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) ||
5381 broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left &&
5382 rect.bottom - rect.top == (short)broken_rect.bottom - (short)broken_rect.top),
5383 "wrong rect %d,%d-%d,%d / %d,%d-%d,%d\n",
5384 rect.left, rect.top, rect.right, rect.bottom,
5385 expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom );
5386 return DefWindowProcA(hwnd, msg, wp, lp);
5388 case WM_NCCALCSIZE:
5390 RECT rect, *r = (RECT *)lp;
5391 GetWindowRect( hwnd, &rect );
5392 ok( !memcmp( &rect, r, sizeof(rect) ),
5393 "passed rect %d,%d-%d,%d doesn't match window rect %d,%d-%d,%d\n",
5394 r->left, r->top, r->right, r->bottom, rect.left, rect.top, rect.right, rect.bottom );
5395 return DefWindowProcA(hwnd, msg, wp, lp);
5397 default:
5398 return DefWindowProcA(hwnd, msg, wp, lp);
5402 static void test_CreateWindow(void)
5404 WNDCLASSA cls;
5405 HWND hwnd, parent;
5406 HMENU hmenu;
5407 RECT rc, rc_minmax;
5408 MINMAXINFO minmax;
5409 BOOL res;
5411 #define expect_menu(window, menu) \
5412 SetLastError(0xdeadbeef); \
5413 res = (GetMenu(window) == (HMENU)menu); \
5414 ok(res, "GetMenu error %d\n", GetLastError())
5416 #define expect_style(window, style)\
5417 ok((ULONG)GetWindowLongA(window, GWL_STYLE) == (style), "expected style %x != %x\n", (LONG)(style), GetWindowLongA(window, GWL_STYLE))
5419 #define expect_ex_style(window, ex_style)\
5420 ok((ULONG)GetWindowLongA(window, GWL_EXSTYLE) == (ex_style), "expected ex_style %x != %x\n", (LONG)(ex_style), GetWindowLongA(window, GWL_EXSTYLE))
5422 #define expect_gle_broken_9x(gle)\
5423 ok(GetLastError() == gle ||\
5424 broken(GetLastError() == 0xdeadbeef),\
5425 "IsMenu set error %d\n", GetLastError())
5427 hmenu = CreateMenu();
5428 assert(hmenu != 0);
5429 parent = GetDesktopWindow();
5430 assert(parent != 0);
5432 SetLastError(0xdeadbeef);
5433 res = IsMenu(hmenu);
5434 ok(res, "IsMenu error %d\n", GetLastError());
5436 /* WS_CHILD */
5437 SetLastError(0xdeadbeef);
5438 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD,
5439 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5440 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5441 expect_menu(hwnd, 1);
5442 expect_style(hwnd, WS_CHILD);
5443 expect_ex_style(hwnd, WS_EX_APPWINDOW);
5444 DestroyWindow(hwnd);
5446 SetLastError(0xdeadbeef);
5447 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_CAPTION,
5448 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5449 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5450 expect_menu(hwnd, 1);
5451 expect_style(hwnd, WS_CHILD | WS_CAPTION);
5452 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
5453 DestroyWindow(hwnd);
5455 SetLastError(0xdeadbeef);
5456 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD,
5457 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5458 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5459 expect_menu(hwnd, 1);
5460 expect_style(hwnd, WS_CHILD);
5461 expect_ex_style(hwnd, 0);
5462 DestroyWindow(hwnd);
5464 SetLastError(0xdeadbeef);
5465 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_CAPTION,
5466 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5467 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5468 expect_menu(hwnd, 1);
5469 expect_style(hwnd, WS_CHILD | WS_CAPTION);
5470 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5471 DestroyWindow(hwnd);
5473 /* WS_POPUP */
5474 SetLastError(0xdeadbeef);
5475 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5476 0, 0, 100, 100, parent, hmenu, 0, NULL);
5477 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5478 expect_menu(hwnd, hmenu);
5479 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
5480 expect_ex_style(hwnd, WS_EX_APPWINDOW);
5481 DestroyWindow(hwnd);
5482 SetLastError(0xdeadbeef);
5483 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5484 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5486 hmenu = CreateMenu();
5487 assert(hmenu != 0);
5488 SetLastError(0xdeadbeef);
5489 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP | WS_CAPTION,
5490 0, 0, 100, 100, parent, hmenu, 0, NULL);
5491 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5492 expect_menu(hwnd, hmenu);
5493 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5494 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
5495 DestroyWindow(hwnd);
5496 SetLastError(0xdeadbeef);
5497 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5498 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5500 hmenu = CreateMenu();
5501 assert(hmenu != 0);
5502 SetLastError(0xdeadbeef);
5503 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
5504 0, 0, 100, 100, parent, hmenu, 0, NULL);
5505 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5506 expect_menu(hwnd, hmenu);
5507 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
5508 expect_ex_style(hwnd, 0);
5509 DestroyWindow(hwnd);
5510 SetLastError(0xdeadbeef);
5511 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5512 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5514 hmenu = CreateMenu();
5515 assert(hmenu != 0);
5516 SetLastError(0xdeadbeef);
5517 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_CAPTION,
5518 0, 0, 100, 100, parent, hmenu, 0, NULL);
5519 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5520 expect_menu(hwnd, hmenu);
5521 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5522 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5523 DestroyWindow(hwnd);
5524 SetLastError(0xdeadbeef);
5525 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5526 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5528 /* WS_CHILD | WS_POPUP */
5529 SetLastError(0xdeadbeef);
5530 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
5531 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5532 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
5533 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5534 if (hwnd)
5535 DestroyWindow(hwnd);
5537 hmenu = CreateMenu();
5538 assert(hmenu != 0);
5539 SetLastError(0xdeadbeef);
5540 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
5541 0, 0, 100, 100, parent, hmenu, 0, NULL);
5542 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5543 expect_menu(hwnd, hmenu);
5544 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
5545 expect_ex_style(hwnd, WS_EX_APPWINDOW);
5546 DestroyWindow(hwnd);
5547 SetLastError(0xdeadbeef);
5548 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5549 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5551 SetLastError(0xdeadbeef);
5552 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
5553 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5554 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
5555 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5556 if (hwnd)
5557 DestroyWindow(hwnd);
5559 hmenu = CreateMenu();
5560 assert(hmenu != 0);
5561 SetLastError(0xdeadbeef);
5562 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
5563 0, 0, 100, 100, parent, hmenu, 0, NULL);
5564 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5565 expect_menu(hwnd, hmenu);
5566 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5567 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
5568 DestroyWindow(hwnd);
5569 SetLastError(0xdeadbeef);
5570 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5571 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5573 SetLastError(0xdeadbeef);
5574 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP,
5575 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5576 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
5577 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5578 if (hwnd)
5579 DestroyWindow(hwnd);
5581 hmenu = CreateMenu();
5582 assert(hmenu != 0);
5583 SetLastError(0xdeadbeef);
5584 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP,
5585 0, 0, 100, 100, parent, hmenu, 0, NULL);
5586 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5587 expect_menu(hwnd, hmenu);
5588 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
5589 expect_ex_style(hwnd, 0);
5590 DestroyWindow(hwnd);
5591 SetLastError(0xdeadbeef);
5592 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5593 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5595 SetLastError(0xdeadbeef);
5596 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
5597 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
5598 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
5599 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5600 if (hwnd)
5601 DestroyWindow(hwnd);
5603 hmenu = CreateMenu();
5604 assert(hmenu != 0);
5605 SetLastError(0xdeadbeef);
5606 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
5607 0, 0, 100, 100, parent, hmenu, 0, NULL);
5608 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5609 expect_menu(hwnd, hmenu);
5610 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
5611 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5612 DestroyWindow(hwnd);
5613 SetLastError(0xdeadbeef);
5614 ok(!IsMenu(hmenu), "IsMenu should fail\n");
5615 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
5617 /* test child window sizing */
5618 cls.style = 0;
5619 cls.lpfnWndProc = minmax_wnd_proc;
5620 cls.cbClsExtra = 0;
5621 cls.cbWndExtra = 0;
5622 cls.hInstance = GetModuleHandleA(NULL);
5623 cls.hIcon = 0;
5624 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
5625 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5626 cls.lpszMenuName = NULL;
5627 cls.lpszClassName = "MinMax_WndClass";
5628 RegisterClassA(&cls);
5630 SetLastError(0xdeadbeef);
5631 parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
5632 0, 0, 100, 100, 0, 0, 0, NULL);
5633 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
5634 expect_menu(parent, 0);
5635 expect_style(parent, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPSIBLINGS);
5636 expect_ex_style(parent, WS_EX_WINDOWEDGE);
5638 memset(&minmax, 0, sizeof(minmax));
5639 SendMessageA(parent, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
5640 SetRect(&rc_minmax, 0, 0, minmax.ptMaxSize.x, minmax.ptMaxSize.y);
5641 ok(IsRectEmpty(&rc_minmax), "ptMaxSize is not empty\n");
5642 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
5643 ok(IsRectEmpty(&rc_minmax), "ptMaxTrackSize is not empty\n");
5645 GetWindowRect(parent, &rc);
5646 ok(!IsRectEmpty(&rc), "parent window rect is empty\n");
5647 GetClientRect(parent, &rc);
5648 ok(!IsRectEmpty(&rc), "parent client rect is empty\n");
5650 InflateRect(&rc, 200, 200);
5651 trace("creating child with rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
5653 SetLastError(0xdeadbeef);
5654 hwnd = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
5655 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
5656 parent, (HMENU)1, 0, NULL);
5657 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
5658 expect_menu(hwnd, 1);
5659 expect_style(hwnd, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
5660 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
5662 memset(&minmax, 0, sizeof(minmax));
5663 SendMessageA(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
5664 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
5666 GetWindowRect(hwnd, &rc);
5667 OffsetRect(&rc, -rc.left, -rc.top);
5668 ok(EqualRect(&rc, &rc_minmax), "rects don't match: (%d,%d-%d,%d) and (%d,%d-%d,%d)\n",
5669 rc.left, rc.top, rc.right, rc.bottom,
5670 rc_minmax.left, rc_minmax.top, rc_minmax.right, rc_minmax.bottom);
5671 DestroyWindow(hwnd);
5673 cls.lpfnWndProc = winsizes_wnd_proc;
5674 cls.lpszClassName = "Sizes_WndClass";
5675 RegisterClassA(&cls);
5677 expected_cx = expected_cy = 200000;
5678 SetRect( &expected_rect, 0, 0, 200000, 200000 );
5679 broken_rect = expected_rect;
5680 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL);
5681 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5682 GetClientRect( hwnd, &rc );
5683 ok( rc.right == 200000 || rc.right == 65535 || broken(rc.right == (short)200000),
5684 "invalid rect right %u\n", rc.right );
5685 ok( rc.bottom == 200000 || rc.bottom == 65535 || broken(rc.bottom == (short)200000),
5686 "invalid rect bottom %u\n", rc.bottom );
5687 DestroyWindow(hwnd);
5689 expected_cx = expected_cy = -10;
5690 SetRectEmpty(&expected_rect);
5691 SetRect( &broken_rect, 0, 0, -10, -10 );
5692 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL);
5693 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5694 GetClientRect( hwnd, &rc );
5695 ok( rc.right == 0, "invalid rect right %u\n", rc.right );
5696 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
5697 DestroyWindow(hwnd);
5699 expected_cx = expected_cy = -200000;
5700 SetRectEmpty(&expected_rect);
5701 SetRect( &broken_rect, 0, 0, -200000, -200000 );
5702 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL);
5703 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5704 GetClientRect( hwnd, &rc );
5705 ok( rc.right == 0, "invalid rect right %u\n", rc.right );
5706 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
5707 DestroyWindow(hwnd);
5709 /* we need a parent at 0,0 so that child coordinates match */
5710 DestroyWindow(parent);
5711 parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
5712 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
5714 expected_cx = 100;
5715 expected_cy = 0x7fffffff;
5716 SetRect( &expected_rect, 10, 10, 110, 0x7fffffff );
5717 SetRect( &broken_rect, 10, 10, 110, 0x7fffffffU + 10 );
5718 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 10, 10, 100, 0x7fffffff, parent, 0, 0, NULL);
5719 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5720 GetClientRect( hwnd, &rc );
5721 ok( rc.right == 100, "invalid rect right %u\n", rc.right );
5722 ok( rc.bottom == 0x7fffffff - 10 || rc.bottom ==65535 || broken(rc.bottom == 0),
5723 "invalid rect bottom %u\n", rc.bottom );
5724 DestroyWindow(hwnd);
5726 expected_cx = 0x7fffffff;
5727 expected_cy = 0x7fffffff;
5728 SetRect( &expected_rect, 20, 10, 0x7fffffff, 0x7fffffff );
5729 SetRect( &broken_rect, 20, 10, 0x7fffffffU + 20, 0x7fffffffU + 10 );
5730 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL);
5731 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5732 GetClientRect( hwnd, &rc );
5733 ok( rc.right == 0x7fffffff - 20 || rc.right == 65535 || broken(rc.right == 0),
5734 "invalid rect right %u\n", rc.right );
5735 ok( rc.bottom == 0x7fffffff - 10 || rc.right == 65535 || broken(rc.bottom == 0),
5736 "invalid rect bottom %u\n", rc.bottom );
5737 DestroyWindow(hwnd);
5739 /* top level window */
5740 expected_cx = expected_cy = 200000;
5741 SetRect( &expected_rect, 0, 0, GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK) );
5742 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_OVERLAPPEDWINDOW, 300000, 300000, 200000, 200000, 0, 0, 0, NULL);
5743 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5744 GetClientRect( hwnd, &rc );
5745 ok( rc.right <= expected_cx, "invalid rect right %u\n", rc.right );
5746 ok( rc.bottom <= expected_cy, "invalid rect bottom %u\n", rc.bottom );
5747 DestroyWindow(hwnd);
5749 if (pGetLayout && pSetLayout)
5751 HDC hdc = GetDC( parent );
5752 pSetLayout( hdc, LAYOUT_RTL );
5753 if (pGetLayout( hdc ))
5755 ReleaseDC( parent, hdc );
5756 DestroyWindow( parent );
5757 SetLastError( 0xdeadbeef );
5758 parent = CreateWindowExA(WS_EX_APPWINDOW | WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP,
5759 0, 0, 100, 100, 0, 0, 0, NULL);
5760 ok( parent != 0, "creation failed err %u\n", GetLastError());
5761 expect_ex_style( parent, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
5762 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
5763 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5764 expect_ex_style( hwnd, WS_EX_LAYOUTRTL );
5765 DestroyWindow( hwnd );
5766 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 20, 20, parent, 0, 0, NULL);
5767 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5768 expect_ex_style( hwnd, 0 );
5769 DestroyWindow( hwnd );
5770 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT );
5771 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
5772 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5773 expect_ex_style( hwnd, 0 );
5774 DestroyWindow( hwnd );
5776 if (pGetProcessDefaultLayout && pSetProcessDefaultLayout)
5778 DWORD layout;
5780 SetLastError( 0xdeadbeef );
5781 ok( !pGetProcessDefaultLayout( NULL ), "GetProcessDefaultLayout succeeded\n" );
5782 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
5783 SetLastError( 0xdeadbeef );
5784 res = pGetProcessDefaultLayout( &layout );
5785 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5786 ok( layout == 0, "GetProcessDefaultLayout wrong layout %x\n", layout );
5787 SetLastError( 0xdeadbeef );
5788 res = pSetProcessDefaultLayout( 7 );
5789 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ());
5790 res = pGetProcessDefaultLayout( &layout );
5791 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5792 ok( layout == 7, "GetProcessDefaultLayout wrong layout %x\n", layout );
5793 SetLastError( 0xdeadbeef );
5794 res = pSetProcessDefaultLayout( LAYOUT_RTL );
5795 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ());
5796 res = pGetProcessDefaultLayout( &layout );
5797 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5798 ok( layout == LAYOUT_RTL, "GetProcessDefaultLayout wrong layout %x\n", layout );
5799 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5800 0, 0, 100, 100, 0, 0, 0, NULL);
5801 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5802 expect_ex_style( hwnd, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
5803 DestroyWindow( hwnd );
5804 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5805 0, 0, 100, 100, parent, 0, 0, NULL);
5806 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5807 expect_ex_style( hwnd, WS_EX_APPWINDOW );
5808 DestroyWindow( hwnd );
5809 pSetProcessDefaultLayout( 0 );
5811 else win_skip( "SetProcessDefaultLayout not supported\n" );
5813 else win_skip( "SetLayout not supported\n" );
5815 else win_skip( "SetLayout not available\n" );
5817 DestroyWindow(parent);
5819 UnregisterClassA("MinMax_WndClass", GetModuleHandleA(NULL));
5820 UnregisterClassA("Sizes_WndClass", GetModuleHandleA(NULL));
5822 #undef expect_gle_broken_9x
5823 #undef expect_menu
5824 #undef expect_style
5825 #undef expect_ex_style
5828 /* function that remembers whether the system the test is running on sets the
5829 * last error for user32 functions to make the tests stricter */
5830 static int check_error(DWORD actual, DWORD expected)
5832 static int sets_last_error = -1;
5833 if (sets_last_error == -1)
5834 sets_last_error = (actual != 0xdeadbeef);
5835 return (!sets_last_error && (actual == 0xdeadbeef)) || (actual == expected);
5838 static void test_SetWindowLong(void)
5840 LONG_PTR retval;
5841 WNDPROC old_window_procW;
5843 SetLastError(0xdeadbeef);
5844 retval = SetWindowLongPtrA(NULL, GWLP_WNDPROC, 0);
5845 ok(!retval, "SetWindowLongPtr on invalid window handle should have returned 0 instead of 0x%lx\n", retval);
5846 ok(check_error(GetLastError(), ERROR_INVALID_WINDOW_HANDLE),
5847 "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instead of %d\n", GetLastError());
5849 SetLastError(0xdeadbeef);
5850 retval = SetWindowLongPtrA(hwndMain, 0xdeadbeef, 0);
5851 ok(!retval, "SetWindowLongPtr on invalid index should have returned 0 instead of 0x%lx\n", retval);
5852 ok(check_error(GetLastError(), ERROR_INVALID_INDEX),
5853 "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instead of %d\n", GetLastError());
5855 SetLastError(0xdeadbeef);
5856 retval = SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0);
5857 ok((WNDPROC)retval == main_window_procA || broken(!retval), /* win9x */
5858 "SetWindowLongPtr on invalid window proc should have returned address of main_window_procA instead of 0x%lx\n", retval);
5859 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
5860 retval = GetWindowLongPtrA(hwndMain, GWLP_WNDPROC);
5861 ok((WNDPROC)retval == main_window_procA,
5862 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
5863 ok(!IsWindowUnicode(hwndMain), "hwndMain shouldn't be Unicode\n");
5865 old_window_procW = (WNDPROC)GetWindowLongPtrW(hwndMain, GWLP_WNDPROC);
5866 SetLastError(0xdeadbeef);
5867 retval = SetWindowLongPtrW(hwndMain, GWLP_WNDPROC, 0);
5868 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
5870 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
5871 ok(retval != 0, "SetWindowLongPtr error %d\n", GetLastError());
5872 ok((WNDPROC)retval == old_window_procW,
5873 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
5874 ok(IsWindowUnicode(hwndMain), "hwndMain should now be Unicode\n");
5876 /* set it back to ANSI */
5877 SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0);
5881 static void test_ShowWindow(void)
5883 HWND hwnd;
5884 DWORD style;
5885 RECT rcMain, rc, rcMinimized;
5886 LPARAM ret;
5888 SetRect(&rcMain, 120, 120, 210, 210);
5890 hwnd = CreateWindowExA(0, "MainWindowClass", NULL,
5891 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
5892 WS_MAXIMIZEBOX | WS_POPUP,
5893 rcMain.left, rcMain.top,
5894 rcMain.right - rcMain.left, rcMain.bottom - rcMain.top,
5895 0, 0, 0, NULL);
5896 assert(hwnd);
5898 style = GetWindowLongA(hwnd, GWL_STYLE);
5899 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5900 ok(!(style & WS_VISIBLE), "window should not be visible\n");
5901 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5902 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5903 GetWindowRect(hwnd, &rc);
5904 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5905 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5906 rc.left, rc.top, rc.right, rc.bottom);
5908 ret = ShowWindow(hwnd, SW_SHOW);
5909 ok(!ret, "not expected ret: %lu\n", ret);
5910 style = GetWindowLongA(hwnd, GWL_STYLE);
5911 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5912 ok(style & WS_VISIBLE, "window should be visible\n");
5913 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5914 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5915 GetWindowRect(hwnd, &rc);
5916 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5917 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5918 rc.left, rc.top, rc.right, rc.bottom);
5920 ret = ShowWindow(hwnd, SW_MINIMIZE);
5921 ok(ret, "not expected ret: %lu\n", ret);
5922 style = GetWindowLongA(hwnd, GWL_STYLE);
5923 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5924 ok(style & WS_VISIBLE, "window should be visible\n");
5925 ok(style & WS_MINIMIZE, "window should be minimized\n");
5926 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5927 GetWindowRect(hwnd, &rcMinimized);
5928 ok(!EqualRect(&rcMain, &rcMinimized), "rects shouldn't match\n");
5929 /* shouldn't be able to resize minimized windows */
5930 ret = SetWindowPos(hwnd, 0, 0, 0,
5931 (rcMinimized.right - rcMinimized.left) * 2,
5932 (rcMinimized.bottom - rcMinimized.top) * 2,
5933 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
5934 ok(ret, "not expected ret: %lu\n", ret);
5935 GetWindowRect(hwnd, &rc);
5936 ok(EqualRect(&rc, &rcMinimized), "rects should match\n");
5938 ShowWindow(hwnd, SW_RESTORE);
5939 ok(ret, "not expected ret: %lu\n", ret);
5940 style = GetWindowLongA(hwnd, GWL_STYLE);
5941 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5942 ok(style & WS_VISIBLE, "window should be visible\n");
5943 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5944 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5945 GetWindowRect(hwnd, &rc);
5946 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5947 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5948 rc.left, rc.top, rc.right, rc.bottom);
5950 ret = EnableWindow(hwnd, FALSE);
5951 ok(!ret, "not expected ret: %lu\n", ret);
5952 style = GetWindowLongA(hwnd, GWL_STYLE);
5953 ok(style & WS_DISABLED, "window should be disabled\n");
5955 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
5956 ok(!ret, "not expected ret: %lu\n", ret);
5957 style = GetWindowLongA(hwnd, GWL_STYLE);
5958 ok(style & WS_DISABLED, "window should be disabled\n");
5959 ok(style & WS_VISIBLE, "window should be visible\n");
5960 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5961 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5962 GetWindowRect(hwnd, &rc);
5963 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5964 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5965 rc.left, rc.top, rc.right, rc.bottom);
5967 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
5968 ok(!ret, "not expected ret: %lu\n", ret);
5969 style = GetWindowLongA(hwnd, GWL_STYLE);
5970 ok(style & WS_DISABLED, "window should be disabled\n");
5971 ok(style & WS_VISIBLE, "window should be visible\n");
5972 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5973 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5974 GetWindowRect(hwnd, &rc);
5975 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5976 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5977 rc.left, rc.top, rc.right, rc.bottom);
5979 ret = ShowWindow(hwnd, SW_MINIMIZE);
5980 ok(ret, "not expected ret: %lu\n", ret);
5981 style = GetWindowLongA(hwnd, GWL_STYLE);
5982 ok(style & WS_DISABLED, "window should be disabled\n");
5983 ok(style & WS_VISIBLE, "window should be visible\n");
5984 ok(style & WS_MINIMIZE, "window should be minimized\n");
5985 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5986 GetWindowRect(hwnd, &rc);
5987 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
5989 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
5990 ok(!ret, "not expected ret: %lu\n", ret);
5991 style = GetWindowLongA(hwnd, GWL_STYLE);
5992 ok(style & WS_DISABLED, "window should be disabled\n");
5993 ok(style & WS_VISIBLE, "window should be visible\n");
5994 ok(style & WS_MINIMIZE, "window should be minimized\n");
5995 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5996 GetWindowRect(hwnd, &rc);
5997 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
5999 ret = ShowWindow(hwnd, SW_RESTORE);
6000 ok(ret, "not expected ret: %lu\n", ret);
6001 style = GetWindowLongA(hwnd, GWL_STYLE);
6002 ok(style & WS_DISABLED, "window should be disabled\n");
6003 ok(style & WS_VISIBLE, "window should be visible\n");
6004 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
6005 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
6006 GetWindowRect(hwnd, &rc);
6007 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
6008 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
6009 rc.left, rc.top, rc.right, rc.bottom);
6011 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
6012 ok(!ret, "not expected ret: %lu\n", ret);
6013 ok(IsWindow(hwnd), "window should exist\n");
6015 ret = EnableWindow(hwnd, TRUE);
6016 ok(ret, "not expected ret: %lu\n", ret);
6018 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
6019 ok(!ret, "not expected ret: %lu\n", ret);
6020 ok(!IsWindow(hwnd), "window should not exist\n");
6023 static DWORD CALLBACK gettext_msg_thread( LPVOID arg )
6025 HWND hwnd = arg;
6026 char buf[32];
6027 INT buf_len;
6029 /* test GetWindowTextA */
6030 num_gettext_msgs = 0;
6031 memset( buf, 0, sizeof(buf) );
6032 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6033 ok( buf_len != 0, "expected a nonempty window text\n" );
6034 ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
6035 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6037 return 0;
6040 static DWORD CALLBACK settext_msg_thread( LPVOID arg )
6042 HWND hwnd = arg;
6043 BOOL success;
6045 /* test SetWindowTextA */
6046 num_settext_msgs = 0;
6047 success = SetWindowTextA( hwnd, "thread_caption" );
6048 ok( success, "SetWindowTextA failed\n" );
6049 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6051 return 0;
6054 static void test_gettext(void)
6056 DWORD tid, num_msgs;
6057 WCHAR bufW[32];
6058 HANDLE thread;
6059 BOOL success;
6060 char buf[32];
6061 INT buf_len;
6062 HWND hwnd, hwnd2;
6063 LRESULT r;
6064 MSG msg;
6066 hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
6067 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
6069 /* test GetWindowTextA */
6070 num_gettext_msgs = 0;
6071 memset( buf, 0, sizeof(buf) );
6072 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6073 ok( buf_len != 0, "expected a nonempty window text\n" );
6074 ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
6075 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6077 /* other process window */
6078 strcpy( buf, "a" );
6079 buf_len = GetWindowTextA( GetDesktopWindow(), buf, sizeof(buf) );
6080 ok( buf_len == 0, "expected a nonempty window text\n" );
6081 ok( *buf == 0, "got wrong window text '%s'\n", buf );
6083 strcpy( buf, "blah" );
6084 buf_len = GetWindowTextA( GetDesktopWindow(), buf, 0 );
6085 ok( buf_len == 0, "expected a nonempty window text\n" );
6086 ok( !strcmp(buf, "blah"), "got wrong window text '%s'\n", buf );
6088 bufW[0] = 0xcc;
6089 buf_len = GetWindowTextW( GetDesktopWindow(), bufW, 0 );
6090 ok( buf_len == 0, "expected a nonempty window text\n" );
6091 ok( bufW[0] == 0xcc, "got %x\n", bufW[0] );
6093 g_wm_gettext_override.enabled = TRUE;
6095 num_gettext_msgs = 0;
6096 memset( buf, 0xcc, sizeof(buf) );
6097 g_wm_gettext_override.buff = buf;
6098 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6099 ok( buf_len == 0, "got %d\n", buf_len );
6100 ok( *buf == 0, "got %x\n", *buf );
6101 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6103 num_gettext_msgs = 0;
6104 strcpy( buf, "blah" );
6105 g_wm_gettext_override.buff = buf;
6106 buf_len = GetWindowTextA( hwnd, buf, 0 );
6107 ok( buf_len == 0, "got %d\n", buf_len );
6108 ok( !strcmp(buf, "blah"), "got %s\n", buf );
6109 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6111 g_wm_gettext_override.enabled = FALSE;
6113 /* same for W window */
6114 hwnd2 = CreateWindowExW( 0, mainclassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL );
6115 ok( hwnd2 != 0, "CreateWindowExA error %d\n", GetLastError() );
6117 g_wm_gettext_override.enabled = TRUE;
6119 num_gettext_msgs = 0;
6120 memset( bufW, 0xcc, sizeof(bufW) );
6121 g_wm_gettext_override.buffW = bufW;
6122 buf_len = GetWindowTextW( hwnd2, bufW, sizeof(bufW)/sizeof(WCHAR) );
6123 ok( buf_len == 0, "got %d\n", buf_len );
6124 ok( *bufW == 0, "got %x\n", *bufW );
6125 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6127 num_gettext_msgs = 0;
6128 memset( bufW, 0xcc, sizeof(bufW) );
6129 g_wm_gettext_override.buffW = bufW;
6130 buf_len = GetWindowTextW( hwnd2, bufW, 0 );
6131 ok( buf_len == 0, "got %d\n", buf_len );
6132 ok( *bufW == 0xcccc, "got %x\n", *bufW );
6133 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6135 g_wm_gettext_override.enabled = FALSE;
6137 DestroyWindow( hwnd2 );
6139 /* test WM_GETTEXT */
6140 num_gettext_msgs = 0;
6141 memset( buf, 0, sizeof(buf) );
6142 r = SendMessageA( hwnd, WM_GETTEXT, sizeof(buf), (LONG_PTR)buf );
6143 ok( r != 0, "expected a nonempty window text\n" );
6144 ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf );
6145 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6147 /* test SetWindowTextA */
6148 num_settext_msgs = 0;
6149 success = SetWindowTextA( hwnd, "new_caption" );
6150 ok( success, "SetWindowTextA failed\n" );
6151 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6153 num_gettext_msgs = 0;
6154 memset( buf, 0, sizeof(buf) );
6155 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6156 ok( buf_len != 0, "expected a nonempty window text\n" );
6157 ok( !strcmp(buf, "new_caption"), "got wrong window text '%s'\n", buf );
6158 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6160 /* test WM_SETTEXT */
6161 num_settext_msgs = 0;
6162 r = SendMessageA( hwnd, WM_SETTEXT, 0, (ULONG_PTR)"another_caption" );
6163 ok( r != 0, "WM_SETTEXT failed\n" );
6164 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs );
6166 num_gettext_msgs = 0;
6167 memset( buf, 0, sizeof(buf) );
6168 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6169 ok( buf_len != 0, "expected a nonempty window text\n" );
6170 ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf );
6171 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6173 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6174 DispatchMessageA( &msg );
6176 /* test interthread GetWindowTextA */
6177 num_msgs = 0;
6178 thread = CreateThread( NULL, 0, gettext_msg_thread, hwnd, 0, &tid );
6179 ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
6180 while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
6182 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6183 DispatchMessageA( &msg );
6184 num_msgs++;
6186 CloseHandle( thread );
6187 ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
6189 /* test interthread SetWindowText */
6190 num_msgs = 0;
6191 thread = CreateThread( NULL, 0, settext_msg_thread, hwnd, 0, &tid );
6192 ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError());
6193 while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0)
6195 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE ))
6196 DispatchMessageA( &msg );
6197 num_msgs++;
6199 CloseHandle( thread );
6200 ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs );
6202 num_gettext_msgs = 0;
6203 memset( buf, 0, sizeof(buf) );
6204 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) );
6205 ok( buf_len != 0, "expected a nonempty window text\n" );
6206 ok( !strcmp(buf, "thread_caption"), "got wrong window text '%s'\n", buf );
6207 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
6209 /* seems to crash on every modern Windows version */
6210 if (0)
6212 r = SendMessageA( hwnd, WM_GETTEXT, 0x10, 0x1000);
6213 ok( r == 0, "settext should return zero\n");
6215 r = SendMessageA( hwnd, WM_GETTEXT, 0x10000, 0);
6216 ok( r == 0, "settext should return zero (%ld)\n", r);
6218 r = SendMessageA( hwnd, WM_GETTEXT, 0xff000000, 0x1000);
6219 ok( r == 0, "settext should return zero (%ld)\n", r);
6221 r = SendMessageA( hwnd, WM_GETTEXT, 0x1000, 0xff000000);
6222 ok( r == 0, "settext should return zero (%ld)\n", r);
6225 DestroyWindow(hwnd);
6229 static void test_GetUpdateRect(void)
6231 MSG msg;
6232 BOOL ret, parent_wm_paint, grandparent_wm_paint;
6233 RECT rc1, rc2;
6234 HWND hgrandparent, hparent, hchild;
6235 WNDCLASSA cls;
6236 static const char classNameA[] = "GetUpdateRectClass";
6238 hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW,
6239 0, 0, 100, 100, NULL, NULL, 0, NULL);
6241 hparent = CreateWindowA("static", "parent", WS_CHILD|WS_VISIBLE,
6242 0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
6244 hchild = CreateWindowA("static", "child", WS_CHILD|WS_VISIBLE,
6245 10, 10, 30, 30, hparent, NULL, 0, NULL);
6247 ShowWindow(hgrandparent, SW_SHOW);
6248 UpdateWindow(hgrandparent);
6249 flush_events( TRUE );
6251 ShowWindow(hchild, SW_HIDE);
6252 SetRectEmpty(&rc2);
6253 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6254 ok(!ret, "GetUpdateRect returned not empty region\n");
6255 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
6256 rc1.left, rc1.top, rc1.right, rc1.bottom,
6257 rc2.left, rc2.top, rc2.right, rc2.bottom);
6259 SetRect(&rc2, 10, 10, 40, 40);
6260 ret = GetUpdateRect(hparent, &rc1, FALSE);
6261 ok(ret, "GetUpdateRect returned empty region\n");
6262 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
6263 rc1.left, rc1.top, rc1.right, rc1.bottom,
6264 rc2.left, rc2.top, rc2.right, rc2.bottom);
6266 parent_wm_paint = FALSE;
6267 grandparent_wm_paint = FALSE;
6268 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
6270 if (msg.message == WM_PAINT)
6272 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
6273 if (msg.hwnd == hparent) parent_wm_paint = TRUE;
6275 DispatchMessageA(&msg);
6277 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
6278 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
6280 DestroyWindow(hgrandparent);
6282 cls.style = 0;
6283 cls.lpfnWndProc = DefWindowProcA;
6284 cls.cbClsExtra = 0;
6285 cls.cbWndExtra = 0;
6286 cls.hInstance = GetModuleHandleA(0);
6287 cls.hIcon = 0;
6288 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6289 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6290 cls.lpszMenuName = NULL;
6291 cls.lpszClassName = classNameA;
6293 if(!RegisterClassA(&cls)) {
6294 trace("Register failed %d\n", GetLastError());
6295 return;
6298 hgrandparent = CreateWindowA(classNameA, "grandparent", WS_OVERLAPPEDWINDOW,
6299 0, 0, 100, 100, NULL, NULL, 0, NULL);
6301 hparent = CreateWindowA(classNameA, "parent", WS_CHILD|WS_VISIBLE,
6302 0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
6304 hchild = CreateWindowA(classNameA, "child", WS_CHILD|WS_VISIBLE,
6305 10, 10, 30, 30, hparent, NULL, 0, NULL);
6307 ShowWindow(hgrandparent, SW_SHOW);
6308 UpdateWindow(hgrandparent);
6309 flush_events( TRUE );
6311 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6312 ok(!ret, "GetUpdateRect returned not empty region\n");
6314 ShowWindow(hchild, SW_HIDE);
6316 SetRectEmpty(&rc2);
6317 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
6318 ok(!ret, "GetUpdateRect returned not empty region\n");
6319 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
6320 rc1.left, rc1.top, rc1.right, rc1.bottom,
6321 rc2.left, rc2.top, rc2.right, rc2.bottom);
6323 SetRect(&rc2, 10, 10, 40, 40);
6324 ret = GetUpdateRect(hparent, &rc1, FALSE);
6325 ok(ret, "GetUpdateRect returned empty region\n");
6326 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
6327 rc1.left, rc1.top, rc1.right, rc1.bottom,
6328 rc2.left, rc2.top, rc2.right, rc2.bottom);
6330 parent_wm_paint = FALSE;
6331 grandparent_wm_paint = FALSE;
6332 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
6334 if (msg.message == WM_PAINT)
6336 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
6337 if (msg.hwnd == hparent) parent_wm_paint = TRUE;
6339 DispatchMessageA(&msg);
6341 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
6342 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
6344 DestroyWindow(hgrandparent);
6348 static LRESULT CALLBACK TestExposedRegion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
6350 if(msg == WM_PAINT)
6352 PAINTSTRUCT ps;
6353 RECT updateRect;
6354 DWORD waitResult;
6355 HWND win;
6356 const int waitTime = 2000;
6358 BeginPaint(hwnd, &ps);
6360 /* create and destroy window to create an exposed region on this window */
6361 win = CreateWindowA("static", "win", WS_VISIBLE,
6362 10,10,50,50, NULL, NULL, 0, NULL);
6363 DestroyWindow(win);
6365 waitResult = MsgWaitForMultipleObjects( 0, NULL, FALSE, waitTime, QS_PAINT );
6367 ValidateRect(hwnd, NULL);
6368 EndPaint(hwnd, &ps);
6370 if(waitResult != WAIT_TIMEOUT)
6372 GetUpdateRect(hwnd, &updateRect, FALSE);
6373 ok(IsRectEmpty(&updateRect), "Exposed rect should be empty\n");
6376 return 1;
6378 return DefWindowProcA(hwnd, msg, wParam, lParam);
6381 static void test_Expose(void)
6383 WNDCLASSA cls;
6384 HWND mw;
6386 memset(&cls, 0, sizeof(WNDCLASSA));
6387 cls.lpfnWndProc = TestExposedRegion_WndProc;
6388 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6389 cls.lpszClassName = "TestExposeClass";
6390 RegisterClassA(&cls);
6392 mw = CreateWindowA("TestExposeClass", "MainWindow", WS_VISIBLE|WS_OVERLAPPEDWINDOW,
6393 0, 0, 200, 100, NULL, NULL, 0, NULL);
6395 UpdateWindow(mw);
6396 DestroyWindow(mw);
6399 static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
6401 static UINT ncredrawflags;
6402 PAINTSTRUCT ps;
6404 switch(msg)
6406 case WM_CREATE:
6407 ncredrawflags = *(UINT *) (((CREATESTRUCTA *)lParam)->lpCreateParams);
6408 return 0;
6409 case WM_NCPAINT:
6410 RedrawWindow(hwnd, NULL, NULL, ncredrawflags);
6411 break;
6412 case WM_PAINT:
6413 BeginPaint(hwnd, &ps);
6414 EndPaint(hwnd, &ps);
6415 return 0;
6417 return DefWindowProcA(hwnd, msg, wParam, lParam);
6420 static void run_NCRedrawLoop(UINT flags)
6422 HWND hwnd;
6423 MSG msg;
6425 UINT loopcount = 0;
6427 hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
6428 WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
6429 NULL, NULL, 0, &flags);
6430 ShowWindow(hwnd, SW_SHOW);
6431 UpdateWindow(hwnd);
6432 flush_events( FALSE );
6433 while (PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE))
6435 if (msg.message == WM_PAINT) loopcount++;
6436 if (loopcount >= 100) break;
6437 TranslateMessage(&msg);
6438 DispatchMessageA(&msg);
6439 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT);
6441 todo_wine_if (flags == (RDW_INVALIDATE | RDW_FRAME))
6442 ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
6443 DestroyWindow(hwnd);
6446 static void test_NCRedraw(void)
6448 WNDCLASSA wndclass;
6450 wndclass.lpszClassName = "TestNCRedrawClass";
6451 wndclass.style = CS_HREDRAW | CS_VREDRAW;
6452 wndclass.lpfnWndProc = TestNCRedraw_WndProc;
6453 wndclass.cbClsExtra = 0;
6454 wndclass.cbWndExtra = 0;
6455 wndclass.hInstance = 0;
6456 wndclass.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
6457 wndclass.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6458 wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
6459 wndclass.lpszMenuName = NULL;
6461 RegisterClassA(&wndclass);
6463 run_NCRedrawLoop(RDW_INVALIDATE | RDW_FRAME);
6464 run_NCRedrawLoop(RDW_INVALIDATE);
6467 static void test_GetWindowModuleFileName(void)
6469 HWND hwnd;
6470 HINSTANCE hinst;
6471 UINT ret1, ret2;
6472 char buf1[MAX_PATH], buf2[MAX_PATH];
6474 if (!pGetWindowModuleFileNameA)
6476 win_skip("GetWindowModuleFileNameA is not available\n");
6477 return;
6480 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL);
6481 assert(hwnd);
6483 hinst = (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE);
6484 ok(hinst == 0 || broken(hinst == GetModuleHandleA(NULL)), /* win9x */ "expected 0, got %p\n", hinst);
6486 buf1[0] = 0;
6487 SetLastError(0xdeadbeef);
6488 ret1 = GetModuleFileNameA(hinst, buf1, sizeof(buf1));
6489 ok(ret1, "GetModuleFileName error %u\n", GetLastError());
6491 buf2[0] = 0;
6492 SetLastError(0xdeadbeef);
6493 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
6494 ok(ret2 || broken(!ret2), /* nt4 sp 3 */
6495 "GetWindowModuleFileNameA error %u\n", GetLastError());
6497 if (ret2)
6499 ok(ret1 == ret2 || broken(ret2 == ret1 + 1), /* win98 */ "%u != %u\n", ret1, ret2);
6500 ok(!strcmp(buf1, buf2), "%s != %s\n", buf1, buf2);
6502 hinst = GetModuleHandleA(NULL);
6504 SetLastError(0xdeadbeef);
6505 ret2 = GetModuleFileNameA(hinst, buf2, ret1 - 2);
6506 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */
6507 "expected %u, got %u\n", ret1 - 2, ret2);
6508 ok(GetLastError() == 0xdeadbeef /* XP */ ||
6509 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
6510 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
6512 SetLastError(0xdeadbeef);
6513 ret2 = GetModuleFileNameA(hinst, buf2, 0);
6514 ok(!ret2, "GetModuleFileName should return 0\n");
6515 ok(GetLastError() == 0xdeadbeef /* XP */ ||
6516 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
6517 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
6519 SetLastError(0xdeadbeef);
6520 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, ret1 - 2);
6521 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3) /* win98 */ || broken(!ret2), /* nt4 sp3 */
6522 "expected %u, got %u\n", ret1 - 2, ret2);
6523 ok(GetLastError() == 0xdeadbeef /* XP */ ||
6524 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
6525 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
6527 SetLastError(0xdeadbeef);
6528 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, 0);
6529 ok(!ret2, "expected 0, got %u\n", ret2);
6530 ok(GetLastError() == 0xdeadbeef /* XP */ ||
6531 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
6532 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
6534 DestroyWindow(hwnd);
6536 buf2[0] = 0;
6537 hwnd = (HWND)0xdeadbeef;
6538 SetLastError(0xdeadbeef);
6539 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
6540 ok(!ret1, "expected 0, got %u\n", ret1);
6541 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), /* win9x */
6542 "expected ERROR_INVALID_WINDOW_HANDLE, got %u\n", GetLastError());
6544 hwnd = FindWindowA("Shell_TrayWnd", NULL);
6545 ok(IsWindow(hwnd) || broken(!hwnd), "got invalid tray window %p\n", hwnd);
6546 SetLastError(0xdeadbeef);
6547 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
6548 ok(!ret1 || broken(ret1), /* win98 */ "expected 0, got %u\n", ret1);
6550 if (!ret1) /* inter-process GetWindowModuleFileName works on win9x, so don't test the desktop there */
6552 ret1 = GetModuleFileNameA(0, buf1, sizeof(buf1));
6553 hwnd = GetDesktopWindow();
6554 ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd);
6555 SetLastError(0xdeadbeef);
6556 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
6557 ok(!ret2 ||
6558 ret1 == ret2 || /* vista */
6559 broken(ret2), /* some win98 return user.exe as file name */
6560 "expected 0 or %u, got %u %s\n", ret1, ret2, buf2);
6564 static void test_hwnd_message(void)
6566 static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0};
6567 static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0};
6569 HWND parent = 0, hwnd, found;
6570 RECT rect;
6572 /* HWND_MESSAGE is not supported below w2k, but win9x return != 0
6573 on CreateWindowExA and crash later in the test.
6574 Use UNICODE here to fail on win9x */
6575 hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, WS_CAPTION | WS_VISIBLE,
6576 100, 100, 200, 200, HWND_MESSAGE, 0, 0, NULL);
6577 if (!hwnd)
6579 win_skip("CreateWindowExW with parent HWND_MESSAGE failed\n");
6580 return;
6583 ok( !GetParent(hwnd), "GetParent should return 0 for message only windows\n" );
6584 if (pGetAncestor)
6586 char buffer[100];
6587 HWND root, desktop = GetDesktopWindow();
6589 parent = pGetAncestor(hwnd, GA_PARENT);
6590 ok(parent != 0, "GetAncestor(GA_PARENT) should not return 0 for message windows\n");
6591 ok(parent != desktop, "GetAncestor(GA_PARENT) should not return desktop for message windows\n");
6592 root = pGetAncestor(hwnd, GA_ROOT);
6593 ok(root == hwnd, "GetAncestor(GA_ROOT) should return hwnd for message windows\n");
6594 ok( !pGetAncestor(parent, GA_PARENT) || broken(pGetAncestor(parent, GA_PARENT) != 0), /* win2k */
6595 "parent shouldn't have parent %p\n", pGetAncestor(parent, GA_PARENT) );
6596 trace("parent %p root %p desktop %p\n", parent, root, desktop);
6597 if (!GetClassNameA( parent, buffer, sizeof(buffer) )) buffer[0] = 0;
6598 ok( !lstrcmpiA( buffer, "Message" ), "wrong parent class '%s'\n", buffer );
6599 GetWindowRect( parent, &rect );
6600 ok( rect.left == 0 && rect.right == 100 && rect.top == 0 && rect.bottom == 100,
6601 "wrong parent rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
6603 GetWindowRect( hwnd, &rect );
6604 ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300,
6605 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
6607 /* test FindWindow behavior */
6609 found = FindWindowExA( 0, 0, 0, "message window" );
6610 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
6611 SetLastError(0xdeadbeef);
6612 found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" );
6613 ok( found == 0, "found message window %p/%p\n", found, hwnd );
6614 ok( GetLastError() == 0xdeadbeef, "expected deadbeef, got %d\n", GetLastError() );
6615 if (parent)
6617 found = FindWindowExA( parent, 0, 0, "message window" );
6618 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
6621 /* test IsChild behavior */
6623 if (parent) ok( !IsChild( parent, hwnd ), "HWND_MESSAGE is child of top window\n" );
6625 /* test IsWindowVisible behavior */
6627 ok( !IsWindowVisible( hwnd ), "HWND_MESSAGE window is visible\n" );
6628 if (parent) ok( !IsWindowVisible( parent ), "HWND_MESSAGE parent is visible\n" );
6630 DestroyWindow(hwnd);
6633 static void test_layered_window(void)
6635 HWND hwnd;
6636 COLORREF key = 0;
6637 BYTE alpha = 0;
6638 DWORD flags = 0;
6639 POINT pt = { 0, 0 };
6640 SIZE sz = { 200, 200 };
6641 HDC hdc;
6642 HBITMAP hbm;
6643 BOOL ret;
6645 if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes || !pUpdateLayeredWindow)
6647 win_skip( "layered windows not supported\n" );
6648 return;
6651 hdc = CreateCompatibleDC( 0 );
6652 hbm = CreateCompatibleBitmap( hdc, 200, 200 );
6653 SelectObject( hdc, hbm );
6655 hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION,
6656 100, 100, 200, 200, 0, 0, 0, NULL);
6657 assert( hwnd );
6658 SetLastError( 0xdeadbeef );
6659 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6660 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
6661 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
6662 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6663 ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" );
6664 ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA );
6665 ok( !ret, "SetLayeredWindowAttributes should fail on non-layered window\n" );
6666 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
6667 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6668 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
6669 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6670 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
6671 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6672 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
6673 ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA );
6674 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
6675 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6676 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
6677 ok( key == 0x123456 || key == 0, "wrong color key %x\n", key );
6678 ok( alpha == 44, "wrong alpha %u\n", alpha );
6679 ok( flags == LWA_ALPHA, "wrong flags %x\n", flags );
6680 SetLastError( 0xdeadbeef );
6681 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6682 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
6683 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
6685 /* clearing WS_EX_LAYERED resets attributes */
6686 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
6687 SetLastError( 0xdeadbeef );
6688 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6689 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
6690 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6691 ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" );
6692 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
6693 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6694 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
6695 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6696 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
6697 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE | ULW_EX_NORESIZE );
6698 ok( !ret, "UpdateLayeredWindow should fail with ex flag\n" );
6699 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
6700 if (pUpdateLayeredWindowIndirect)
6702 UPDATELAYEREDWINDOWINFO info;
6703 info.cbSize = sizeof(info);
6704 info.hdcDst = 0;
6705 info.pptDst = NULL;
6706 info.psize = &sz;
6707 info.hdcSrc = hdc;
6708 info.pptSrc = &pt;
6709 info.crKey = 0;
6710 info.pblend = NULL;
6711 info.dwFlags = ULW_OPAQUE | ULW_EX_NORESIZE;
6712 info.prcDirty = NULL;
6713 ret = pUpdateLayeredWindowIndirect( hwnd, &info );
6714 ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
6715 sz.cx--;
6716 SetLastError(0);
6717 ret = pUpdateLayeredWindowIndirect( hwnd, &info );
6718 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
6719 /* particular error code differs from version to version, could be ERROR_INCORRECT_SIZE,
6720 ERROR_MR_MID_NOT_FOUND or ERROR_GEN_FAILURE (Win8/Win10) */
6721 ok( GetLastError() != 0, "wrong error %u\n", GetLastError() );
6722 info.dwFlags = ULW_OPAQUE;
6723 ret = pUpdateLayeredWindowIndirect( hwnd, &info );
6724 ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" );
6725 sz.cx++;
6726 info.dwFlags = ULW_OPAQUE | 0xf00;
6727 ret = pUpdateLayeredWindowIndirect( hwnd, &info );
6728 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
6729 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
6730 info.cbSize--;
6731 info.dwFlags = ULW_OPAQUE;
6732 ret = pUpdateLayeredWindowIndirect( hwnd, &info );
6733 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
6734 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
6735 ret = pUpdateLayeredWindowIndirect( hwnd, NULL );
6736 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" );
6737 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() );
6740 ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA );
6741 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
6742 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6743 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
6744 ok( key == 0x654321, "wrong color key %x\n", key );
6745 ok( alpha == 22, "wrong alpha %u\n", alpha );
6746 ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags );
6747 SetLastError( 0xdeadbeef );
6748 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
6749 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
6750 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
6752 ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY );
6753 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
6754 alpha = 0;
6755 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6756 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
6757 ok( key == 0x888888, "wrong color key %x\n", key );
6758 /* alpha not changed on vista if LWA_ALPHA is not set */
6759 ok( alpha == 22 || alpha == 33, "wrong alpha %u\n", alpha );
6760 ok( flags == LWA_COLORKEY, "wrong flags %x\n", flags );
6762 /* color key may or may not be changed without LWA_COLORKEY */
6763 ret = pSetLayeredWindowAttributes( hwnd, 0x999999, 44, 0 );
6764 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
6765 alpha = 0;
6766 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6767 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
6768 ok( key == 0x888888 || key == 0x999999, "wrong color key %x\n", key );
6769 ok( alpha == 22 || alpha == 44, "wrong alpha %u\n", alpha );
6770 ok( flags == 0, "wrong flags %x\n", flags );
6772 /* default alpha and color key is 0 */
6773 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
6774 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
6775 ret = pSetLayeredWindowAttributes( hwnd, 0x222222, 55, 0 );
6776 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
6777 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
6778 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
6779 ok( key == 0 || key == 0x222222, "wrong color key %x\n", key );
6780 ok( alpha == 0 || alpha == 55, "wrong alpha %u\n", alpha );
6781 ok( flags == 0, "wrong flags %x\n", flags );
6783 DestroyWindow( hwnd );
6784 DeleteDC( hdc );
6785 DeleteObject( hbm );
6788 static MONITORINFO mi;
6790 static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
6792 switch (msg)
6794 case WM_NCCREATE:
6796 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
6797 ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top &&
6798 cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom,
6799 "expected %d,%d-%d,%d, got %d,%d-%d,%d\n",
6800 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6801 cs->x, cs->y, cs->cx, cs->cy);
6802 break;
6804 case WM_GETMINMAXINFO:
6806 MINMAXINFO *minmax = (MINMAXINFO *)lp;
6807 ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left);
6808 ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top);
6809 ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right);
6810 ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom);
6811 break;
6814 return DefWindowProcA(hwnd, msg, wp, lp);
6817 static void test_fullscreen(void)
6819 static const DWORD t_style[] = {
6820 WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME
6822 static const DWORD t_ex_style[] = {
6823 0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW
6825 WNDCLASSA cls;
6826 HWND hwnd;
6827 int i, j;
6828 POINT pt;
6829 RECT rc;
6830 HMONITOR hmon;
6831 LRESULT ret;
6833 if (!pGetMonitorInfoA || !pMonitorFromPoint)
6835 win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n");
6836 return;
6839 pt.x = pt.y = 0;
6840 SetLastError(0xdeadbeef);
6841 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
6842 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError());
6844 mi.cbSize = sizeof(mi);
6845 SetLastError(0xdeadbeef);
6846 ret = pGetMonitorInfoA(hmon, &mi);
6847 ok(ret, "GetMonitorInfo error %u\n", GetLastError());
6848 trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n",
6849 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6850 mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom);
6852 cls.style = 0;
6853 cls.lpfnWndProc = fullscreen_wnd_proc;
6854 cls.cbClsExtra = 0;
6855 cls.cbWndExtra = 0;
6856 cls.hInstance = GetModuleHandleA(NULL);
6857 cls.hIcon = 0;
6858 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
6859 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6860 cls.lpszMenuName = NULL;
6861 cls.lpszClassName = "fullscreen_class";
6862 RegisterClassA(&cls);
6864 for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++)
6866 DWORD style, ex_style;
6868 /* avoid a WM interaction */
6869 assert(!(t_style[i] & WS_VISIBLE));
6871 for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++)
6873 int fixup;
6875 style = t_style[i];
6876 ex_style = t_ex_style[j];
6878 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6879 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6880 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6881 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6882 GetWindowRect(hwnd, &rc);
6883 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6884 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6885 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6886 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6887 DestroyWindow(hwnd);
6889 style = t_style[i] | WS_MAXIMIZE;
6890 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6891 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6892 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6893 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6894 GetWindowRect(hwnd, &rc);
6895 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6896 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6897 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6898 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6899 DestroyWindow(hwnd);
6901 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION;
6902 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6903 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6904 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6905 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6906 GetWindowRect(hwnd, &rc);
6907 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6908 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6909 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6910 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6911 DestroyWindow(hwnd);
6913 style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX;
6914 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6915 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6916 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6917 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6918 GetWindowRect(hwnd, &rc);
6919 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6920 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6921 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6922 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6923 DestroyWindow(hwnd);
6925 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX;
6926 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6927 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6928 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6929 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6930 GetWindowRect(hwnd, &rc);
6931 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6932 /* Windows makes a maximized window slightly larger (to hide the borders?) */
6933 fixup = min(abs(rc.left), abs(rc.top));
6934 InflateRect(&rc, -fixup, -fixup);
6935 ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
6936 rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
6937 "%#x/%#x: window rect %d,%d-%d,%d must be in %d,%d-%d,%d\n",
6938 ex_style, style, rc.left, rc.top, rc.right, rc.bottom,
6939 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom);
6940 DestroyWindow(hwnd);
6942 style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX;
6943 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6944 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6945 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL);
6946 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6947 GetWindowRect(hwnd, &rc);
6948 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6949 /* Windows makes a maximized window slightly larger (to hide the borders?) */
6950 fixup = min(abs(rc.left), abs(rc.top));
6951 InflateRect(&rc, -fixup, -fixup);
6952 if (style & (WS_CHILD | WS_POPUP))
6953 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6954 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6955 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6956 else
6957 ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top &&
6958 rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom,
6959 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6960 DestroyWindow(hwnd);
6964 UnregisterClassA("fullscreen_class", GetModuleHandleA(NULL));
6967 static BOOL test_thick_child_got_minmax;
6968 static const char * test_thick_child_name;
6969 static LONG test_thick_child_style;
6970 static LONG test_thick_child_exStyle;
6972 static LRESULT WINAPI test_thick_child_size_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
6974 MINMAXINFO* minmax;
6975 int expectedMinTrackX;
6976 int expectedMinTrackY;
6977 int actualMinTrackX;
6978 int actualMinTrackY;
6979 int expectedMaxTrackX;
6980 int expectedMaxTrackY;
6981 int actualMaxTrackX;
6982 int actualMaxTrackY;
6983 int expectedMaxSizeX;
6984 int expectedMaxSizeY;
6985 int actualMaxSizeX;
6986 int actualMaxSizeY;
6987 int expectedPosX;
6988 int expectedPosY;
6989 int actualPosX;
6990 int actualPosY;
6991 LONG adjustedStyle;
6992 RECT rect;
6993 switch (msg)
6995 case WM_GETMINMAXINFO:
6997 minmax = (MINMAXINFO *)lparam;
6998 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
6999 dump_minmax_info( minmax );
7001 test_thick_child_got_minmax = TRUE;
7004 adjustedStyle = test_thick_child_style;
7005 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
7006 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
7007 GetClientRect(GetParent(hwnd), &rect);
7008 AdjustWindowRectEx(&rect, adjustedStyle, FALSE, test_thick_child_exStyle);
7010 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
7012 expectedMinTrackX = GetSystemMetrics(SM_CXMINTRACK);
7013 expectedMinTrackY = GetSystemMetrics(SM_CYMINTRACK);
7015 else
7017 expectedMinTrackX = -2 * rect.left;
7018 expectedMinTrackY = -2 * rect.top;
7020 actualMinTrackX = minmax->ptMinTrackSize.x;
7021 actualMinTrackY = minmax->ptMinTrackSize.y;
7023 ok(actualMinTrackX == expectedMinTrackX && actualMinTrackY == expectedMinTrackY,
7024 "expected minTrack %dx%d, actual minTrack %dx%d for %s\n",
7025 expectedMinTrackX, expectedMinTrackY, actualMinTrackX, actualMinTrackY,
7026 test_thick_child_name);
7028 actualMaxTrackX = minmax->ptMaxTrackSize.x;
7029 actualMaxTrackY = minmax->ptMaxTrackSize.y;
7030 expectedMaxTrackX = GetSystemMetrics(SM_CXMAXTRACK);
7031 expectedMaxTrackY = GetSystemMetrics(SM_CYMAXTRACK);
7032 ok(actualMaxTrackX == expectedMaxTrackX && actualMaxTrackY == expectedMaxTrackY,
7033 "expected maxTrack %dx%d, actual maxTrack %dx%d for %s\n",
7034 expectedMaxTrackX, expectedMaxTrackY, actualMaxTrackX, actualMaxTrackY,
7035 test_thick_child_name);
7037 expectedMaxSizeX = rect.right - rect.left;
7038 expectedMaxSizeY = rect.bottom - rect.top;
7039 actualMaxSizeX = minmax->ptMaxSize.x;
7040 actualMaxSizeY = minmax->ptMaxSize.y;
7042 ok(actualMaxSizeX == expectedMaxSizeX && actualMaxSizeY == expectedMaxSizeY,
7043 "expected maxSize %dx%d, actual maxSize %dx%d for %s\n",
7044 expectedMaxSizeX, expectedMaxSizeY, actualMaxSizeX, actualMaxSizeY,
7045 test_thick_child_name);
7048 expectedPosX = rect.left;
7049 expectedPosY = rect.top;
7050 actualPosX = minmax->ptMaxPosition.x;
7051 actualPosY = minmax->ptMaxPosition.y;
7052 ok(actualPosX == expectedPosX && actualPosY == expectedPosY,
7053 "expected maxPosition (%d/%d), actual maxPosition (%d/%d) for %s\n",
7054 expectedPosX, expectedPosY, actualPosX, actualPosY, test_thick_child_name);
7056 break;
7060 return DefWindowProcA(hwnd, msg, wparam, lparam);
7063 #define NUMBER_OF_THICK_CHILD_TESTS 16
7064 static void test_thick_child_size(HWND parentWindow)
7066 BOOL success;
7067 RECT childRect;
7068 RECT adjustedParentRect;
7069 HWND childWindow;
7070 LONG childWidth;
7071 LONG childHeight;
7072 LONG expectedWidth;
7073 LONG expectedHeight;
7074 WNDCLASSA cls;
7075 static const char className[] = "THICK_CHILD_CLASS";
7076 int i;
7077 LONG adjustedStyle;
7078 static const LONG styles[NUMBER_OF_THICK_CHILD_TESTS] = {
7079 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7080 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7081 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7082 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7083 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7084 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7085 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7086 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7087 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7088 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7089 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7090 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7091 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
7092 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
7093 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
7094 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
7097 static const LONG exStyles[NUMBER_OF_THICK_CHILD_TESTS] = {
7102 WS_EX_DLGMODALFRAME,
7103 WS_EX_DLGMODALFRAME,
7104 WS_EX_DLGMODALFRAME,
7105 WS_EX_DLGMODALFRAME,
7106 WS_EX_STATICEDGE,
7107 WS_EX_STATICEDGE,
7108 WS_EX_STATICEDGE,
7109 WS_EX_STATICEDGE,
7110 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7111 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7112 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7113 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
7115 static const char *styleName[NUMBER_OF_THICK_CHILD_TESTS] = {
7116 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME",
7117 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME",
7118 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER",
7119 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER",
7120 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_DLGMODALFRAME",
7121 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_DLGMODALFRAME",
7122 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
7123 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
7124 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME exstyle= WS_EX_STATICEDGE",
7125 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE",
7126 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
7127 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
7128 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7129 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7130 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7131 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
7134 cls.style = 0;
7135 cls.lpfnWndProc = test_thick_child_size_winproc;
7136 cls.cbClsExtra = 0;
7137 cls.cbWndExtra = 0;
7138 cls.hInstance = GetModuleHandleA(0);
7139 cls.hIcon = 0;
7140 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
7141 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
7142 cls.lpszMenuName = NULL;
7143 cls.lpszClassName = className;
7144 SetLastError(0xdeadbeef);
7145 success = RegisterClassA(&cls);
7146 ok(success,"RegisterClassA failed, error: %u\n", GetLastError());
7148 for(i = 0; i < NUMBER_OF_THICK_CHILD_TESTS; i++)
7150 test_thick_child_name = styleName[i];
7151 test_thick_child_style = styles[i];
7152 test_thick_child_exStyle = exStyles[i];
7153 test_thick_child_got_minmax = FALSE;
7155 SetLastError(0xdeadbeef);
7156 childWindow = CreateWindowExA( exStyles[i], className, "", styles[i], 0, 0, 0, 0, parentWindow, 0, GetModuleHandleA(0), NULL );
7157 ok(childWindow != NULL, "Failed to create child window, error: %u\n", GetLastError());
7159 ok(test_thick_child_got_minmax, "Got no WM_GETMINMAXINFO\n");
7161 SetLastError(0xdeadbeef);
7162 success = GetWindowRect(childWindow, &childRect);
7163 ok(success,"GetWindowRect call failed, error: %u\n", GetLastError());
7164 childWidth = childRect.right - childRect.left;
7165 childHeight = childRect.bottom - childRect.top;
7167 adjustedStyle = styles[i];
7168 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
7169 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
7170 GetClientRect(GetParent(childWindow), &adjustedParentRect);
7171 AdjustWindowRectEx(&adjustedParentRect, adjustedStyle, FALSE, test_thick_child_exStyle);
7174 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
7176 expectedWidth = GetSystemMetrics(SM_CXMINTRACK);
7177 expectedHeight = GetSystemMetrics(SM_CYMINTRACK);
7179 else
7181 expectedWidth = -2 * adjustedParentRect.left;
7182 expectedHeight = -2 * adjustedParentRect.top;
7185 ok((childWidth == expectedWidth) && (childHeight == expectedHeight),
7186 "size of window (%s) is wrong: expected size %dx%d != actual size %dx%d\n",
7187 test_thick_child_name, expectedWidth, expectedHeight, childWidth, childHeight);
7189 SetLastError(0xdeadbeef);
7190 success = DestroyWindow(childWindow);
7191 ok(success,"DestroyWindow call failed, error: %u\n", GetLastError());
7193 ok(UnregisterClassA(className, GetModuleHandleA(NULL)),"UnregisterClass call failed\n");
7196 static void test_handles( HWND full_hwnd )
7198 HWND hwnd = full_hwnd;
7199 BOOL ret;
7200 RECT rect;
7202 SetLastError( 0xdeadbeef );
7203 ret = GetWindowRect( hwnd, &rect );
7204 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7206 #ifdef _WIN64
7207 if ((ULONG_PTR)full_hwnd >> 32)
7208 hwnd = (HWND)((ULONG_PTR)full_hwnd & ~0u);
7209 else
7210 hwnd = (HWND)((ULONG_PTR)full_hwnd | ((ULONG_PTR)~0u << 32));
7211 SetLastError( 0xdeadbeef );
7212 ret = GetWindowRect( hwnd, &rect );
7213 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7215 hwnd = (HWND)(((ULONG_PTR)full_hwnd & ~0u) | ((ULONG_PTR)0x1234 << 32));
7216 SetLastError( 0xdeadbeef );
7217 ret = GetWindowRect( hwnd, &rect );
7218 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
7220 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x9876 << 16));
7221 SetLastError( 0xdeadbeef );
7222 ret = GetWindowRect( hwnd, &rect );
7223 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
7224 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
7226 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x12345678 << 16));
7227 SetLastError( 0xdeadbeef );
7228 ret = GetWindowRect( hwnd, &rect );
7229 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
7230 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
7231 #endif
7234 static void test_winregion(void)
7236 HWND hwnd;
7237 RECT r;
7238 int ret, width;
7239 HRGN hrgn;
7241 if (!pGetWindowRgnBox)
7243 win_skip("GetWindowRgnBox not supported\n");
7244 return;
7247 hwnd = CreateWindowExA(0, "static", NULL, WS_VISIBLE, 10, 10, 10, 10, NULL, 0, 0, NULL);
7248 /* NULL prect */
7249 SetLastError(0xdeadbeef);
7250 ret = pGetWindowRgnBox(hwnd, NULL);
7251 ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
7252 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
7254 hrgn = CreateRectRgn(2, 3, 10, 15);
7255 ok( hrgn != NULL, "Region creation failed\n");
7256 if (hrgn)
7258 SetWindowRgn(hwnd, hrgn, FALSE);
7260 SetLastError(0xdeadbeef);
7261 ret = pGetWindowRgnBox(hwnd, NULL);
7262 ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
7263 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
7265 r.left = r.top = r.right = r.bottom = 0;
7266 ret = pGetWindowRgnBox(hwnd, &r);
7267 ok( ret == SIMPLEREGION, "Expected SIMPLEREGION, got %d\n", ret);
7268 ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15,
7269 "Expected (2,3,10,15), got (%d,%d,%d,%d)\n", r.left, r.top,
7270 r.right, r.bottom);
7271 if (pMirrorRgn)
7273 hrgn = CreateRectRgn(2, 3, 10, 15);
7274 ret = pMirrorRgn( hwnd, hrgn );
7275 ok( ret == TRUE, "MirrorRgn failed %u\n", ret );
7276 r.left = r.top = r.right = r.bottom = 0;
7277 GetWindowRect( hwnd, &r );
7278 width = r.right - r.left;
7279 r.left = r.top = r.right = r.bottom = 0;
7280 ret = GetRgnBox( hrgn, &r );
7281 ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret );
7282 ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15,
7283 "Wrong rectangle (%d,%d,%d,%d) for width %d\n", r.left, r.top, r.right, r.bottom, width );
7285 else win_skip( "MirrorRgn not supported\n" );
7287 DestroyWindow(hwnd);
7290 static void test_rtl_layout(void)
7292 HWND parent, child;
7293 RECT r;
7294 POINT pt;
7296 if (!pSetProcessDefaultLayout)
7298 win_skip( "SetProcessDefaultLayout not supported\n" );
7299 return;
7302 parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL);
7303 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL);
7305 GetWindowRect( parent, &r );
7306 ok( r.left == 100 && r.right == 400, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7307 GetClientRect( parent, &r );
7308 ok( r.left == 0 && r.right == 300, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7309 GetClientRect( child, &r );
7310 ok( r.left == 0 && r.right == 20, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7311 MapWindowPoints( child, parent, (POINT *)&r, 2 );
7312 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7313 GetWindowRect( child, &r );
7314 ok( r.left == 370 && r.right == 390, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7315 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7316 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7317 GetWindowRect( child, &r );
7318 MapWindowPoints( NULL, parent, (POINT *)&r, 1 );
7319 MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 );
7320 ok( r.left == 30 && r.right == 10, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7321 pt.x = pt.y = 12;
7322 MapWindowPoints( child, parent, &pt, 1 );
7323 ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y );
7324 SetWindowPos( parent, 0, 0, 0, 250, 250, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
7325 GetWindowRect( parent, &r );
7326 ok( r.left == 100 && r.right == 350, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7327 GetWindowRect( child, &r );
7328 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7329 SetWindowLongW( parent, GWL_EXSTYLE, 0 );
7330 GetWindowRect( child, &r );
7331 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7332 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7333 ok( r.left == 220 && r.right == 240, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7334 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_LAYOUTRTL );
7335 GetWindowRect( child, &r );
7336 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7337 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7338 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7339 SetWindowPos( child, 0, 0, 0, 30, 30, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
7340 GetWindowRect( child, &r );
7341 ok( r.left == 310 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7342 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
7343 ok( r.left == 10 && r.right == 40, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
7344 DestroyWindow( child );
7345 DestroyWindow( parent );
7348 static void test_FlashWindow(void)
7350 HWND hwnd;
7351 BOOL ret;
7352 if (!pFlashWindow)
7354 win_skip( "FlashWindow not supported\n" );
7355 return;
7358 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP,
7359 0, 0, 0, 0, 0, 0, 0, NULL );
7360 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7362 SetLastError( 0xdeadbeef );
7363 ret = pFlashWindow( NULL, TRUE );
7364 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
7365 "FlashWindow returned with %d\n", GetLastError() );
7367 DestroyWindow( hwnd );
7369 SetLastError( 0xdeadbeef );
7370 ret = pFlashWindow( hwnd, TRUE );
7371 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER,
7372 "FlashWindow returned with %d\n", GetLastError() );
7375 static void test_FlashWindowEx(void)
7377 HWND hwnd;
7378 FLASHWINFO finfo;
7379 BOOL prev, ret;
7381 if (!pFlashWindowEx)
7383 win_skip( "FlashWindowEx not supported\n" );
7384 return;
7387 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP,
7388 0, 0, 0, 0, 0, 0, 0, NULL );
7389 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7391 finfo.cbSize = sizeof(FLASHWINFO);
7392 finfo.dwFlags = FLASHW_TIMER;
7393 finfo.uCount = 3;
7394 finfo.dwTimeout = 200;
7395 finfo.hwnd = NULL;
7396 SetLastError(0xdeadbeef);
7397 ret = pFlashWindowEx(&finfo);
7398 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7399 "FlashWindowEx returned with %d\n", GetLastError());
7401 finfo.hwnd = hwnd;
7402 SetLastError(0xdeadbeef);
7403 ret = pFlashWindowEx(NULL);
7404 ok(!ret && GetLastError() == ERROR_NOACCESS,
7405 "FlashWindowEx returned with %d\n", GetLastError());
7407 SetLastError(0xdeadbeef);
7408 ret = pFlashWindowEx(&finfo);
7409 todo_wine ok(!ret, "previous window state should not be active\n");
7411 finfo.cbSize = sizeof(FLASHWINFO) - 1;
7412 SetLastError(0xdeadbeef);
7413 ret = pFlashWindowEx(&finfo);
7414 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7415 "FlashWindowEx succeeded\n");
7417 finfo.cbSize = sizeof(FLASHWINFO) + 1;
7418 SetLastError(0xdeadbeef);
7419 ret = pFlashWindowEx(&finfo);
7420 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7421 "FlashWindowEx succeeded\n");
7422 finfo.cbSize = sizeof(FLASHWINFO);
7424 DestroyWindow( hwnd );
7426 SetLastError(0xdeadbeef);
7427 ret = pFlashWindowEx(&finfo);
7428 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7429 "FlashWindowEx returned with %d\n", GetLastError());
7431 ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize);
7432 ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd);
7433 ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags);
7434 ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount);
7435 ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout);
7437 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_VISIBLE | WS_POPUPWINDOW,
7438 0, 0, 0, 0, 0, 0, 0, NULL );
7439 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7440 finfo.hwnd = hwnd;
7442 SetLastError(0xdeadbeef);
7443 ret = pFlashWindowEx(NULL);
7444 ok(!ret && GetLastError() == ERROR_NOACCESS,
7445 "FlashWindowEx returned with %d\n", GetLastError());
7447 SetLastError(0xdeadbeef);
7448 prev = pFlashWindowEx(&finfo);
7450 ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize);
7451 ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd);
7452 ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags);
7453 ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount);
7454 ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout);
7456 finfo.dwFlags = FLASHW_STOP;
7457 SetLastError(0xdeadbeef);
7458 ret = pFlashWindowEx(&finfo);
7459 ok(prev != ret, "previous window state should be different\n");
7461 DestroyWindow( hwnd );
7464 static void test_FindWindowEx(void)
7466 HWND hwnd, found;
7468 hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
7469 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7471 num_gettext_msgs = 0;
7472 found = FindWindowExA( 0, 0, "MainWindowClass", "" );
7473 ok( found == NULL, "expected a NULL hwnd\n" );
7474 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
7476 num_gettext_msgs = 0;
7477 found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
7478 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
7479 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
7481 num_gettext_msgs = 0;
7482 found = FindWindowExA( 0, 0, "MainWindowClass", "caption" );
7483 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
7484 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
7486 DestroyWindow( hwnd );
7488 hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
7489 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
7491 num_gettext_msgs = 0;
7492 found = FindWindowExA( 0, 0, "MainWindowClass", "" );
7493 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
7494 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
7496 num_gettext_msgs = 0;
7497 found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
7498 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
7499 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs );
7501 DestroyWindow( hwnd );
7503 /* test behaviour with a window title that is an empty character */
7504 found = FindWindowExA( 0, 0, "Shell_TrayWnd", "" );
7505 ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
7506 found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL );
7507 ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
7510 static void test_GetLastActivePopup(void)
7512 HWND hwndOwner, hwndPopup1, hwndPopup2;
7514 hwndOwner = CreateWindowExA(0, "MainWindowClass", NULL,
7515 WS_VISIBLE | WS_POPUPWINDOW,
7516 100, 100, 200, 200,
7517 NULL, 0, GetModuleHandleA(NULL), NULL);
7518 hwndPopup1 = CreateWindowExA(0, "MainWindowClass", NULL,
7519 WS_VISIBLE | WS_POPUPWINDOW,
7520 100, 100, 200, 200,
7521 hwndOwner, 0, GetModuleHandleA(NULL), NULL);
7522 hwndPopup2 = CreateWindowExA(0, "MainWindowClass", NULL,
7523 WS_VISIBLE | WS_POPUPWINDOW,
7524 100, 100, 200, 200,
7525 hwndPopup1, 0, GetModuleHandleA(NULL), NULL);
7526 ok( GetLastActivePopup(hwndOwner) == hwndPopup2, "wrong last active popup\n" );
7527 DestroyWindow( hwndPopup2 );
7528 DestroyWindow( hwndPopup1 );
7529 DestroyWindow( hwndOwner );
7532 static LRESULT WINAPI my_httrasparent_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
7534 if (msg == WM_NCHITTEST) return HTTRANSPARENT;
7535 return DefWindowProcA(hwnd, msg, wp, lp);
7538 static LRESULT WINAPI my_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
7540 return DefWindowProcA(hwnd, msg, wp, lp);
7543 static void create_window_tree(HWND parent, HWND *window, int size)
7545 static const DWORD style[] = { 0, WS_VISIBLE, WS_DISABLED, WS_VISIBLE | WS_DISABLED };
7546 int i, pos;
7548 memset(window, 0, size * sizeof(window[0]));
7550 pos = 0;
7551 for (i = 0; i < sizeof(style)/sizeof(style[0]); i++)
7553 assert(pos < size);
7554 window[pos] = CreateWindowExA(0, "my_window", NULL, style[i] | WS_CHILD,
7555 0, 0, 100, 100, parent, 0, 0, NULL);
7556 ok(window[pos] != 0, "CreateWindowEx failed\n");
7557 pos++;
7558 assert(pos < size);
7559 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_window", NULL, style[i] | WS_CHILD,
7560 0, 0, 100, 100, parent, 0, 0, NULL);
7561 ok(window[pos] != 0, "CreateWindowEx failed\n");
7562 pos++;
7564 assert(pos < size);
7565 window[pos] = CreateWindowExA(0, "my_httrasparent", NULL, style[i] | WS_CHILD,
7566 0, 0, 100, 100, parent, 0, 0, NULL);
7567 ok(window[pos] != 0, "CreateWindowEx failed\n");
7568 pos++;
7569 assert(pos < size);
7570 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_httrasparent", NULL, style[i] | WS_CHILD,
7571 0, 0, 100, 100, parent, 0, 0, NULL);
7572 ok(window[pos] != 0, "CreateWindowEx failed\n");
7573 pos++;
7575 assert(pos < size);
7576 window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
7577 0, 0, 100, 100, parent, 0, 0, NULL);
7578 ok(window[pos] != 0, "CreateWindowEx failed\n");
7579 pos++;
7580 assert(pos < size);
7581 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
7582 0, 0, 100, 100, parent, 0, 0, NULL);
7583 ok(window[pos] != 0, "CreateWindowEx failed\n");
7584 pos++;
7585 assert(pos < size);
7586 window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
7587 0, 0, 100, 100, parent, 0, 0, NULL);
7588 ok(window[pos] != 0, "CreateWindowEx failed\n");
7589 pos++;
7590 assert(pos < size);
7591 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
7592 0, 0, 100, 100, parent, 0, 0, NULL);
7593 ok(window[pos] != 0, "CreateWindowEx failed\n");
7594 pos++;
7596 assert(pos < size);
7597 window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
7598 0, 0, 100, 100, parent, 0, 0, NULL);
7599 ok(window[pos] != 0, "CreateWindowEx failed\n");
7600 pos++;
7601 assert(pos < size);
7602 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX,
7603 0, 0, 100, 100, parent, 0, 0, NULL);
7604 ok(window[pos] != 0, "CreateWindowEx failed\n");
7605 pos++;
7606 assert(pos < size);
7607 window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
7608 0, 0, 100, 100, parent, 0, 0, NULL);
7609 ok(window[pos] != 0, "CreateWindowEx failed\n");
7610 pos++;
7611 assert(pos < size);
7612 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON,
7613 0, 0, 100, 100, parent, 0, 0, NULL);
7614 ok(window[pos] != 0, "CreateWindowEx failed\n");
7615 pos++;
7617 assert(pos < size);
7618 window[pos] = CreateWindowExA(0, "Static", NULL, style[i] | WS_CHILD,
7619 0, 0, 100, 100, parent, 0, 0, NULL);
7620 ok(window[pos] != 0, "CreateWindowEx failed\n");
7621 pos++;
7622 assert(pos < size);
7623 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Static", NULL, style[i] | WS_CHILD,
7624 0, 0, 100, 100, parent, 0, 0, NULL);
7625 ok(window[pos] != 0, "CreateWindowEx failed\n");
7626 pos++;
7630 struct window_attributes
7632 char class_name[128];
7633 BOOL is_visible, is_enabled, is_groupbox, is_httransparent, is_extransparent;
7636 static void get_window_attributes(HWND hwnd, struct window_attributes *attrs)
7638 DWORD style, ex_style, hittest;
7640 style = GetWindowLongA(hwnd, GWL_STYLE);
7641 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
7642 attrs->class_name[0] = 0;
7643 GetClassNameA(hwnd, attrs->class_name, sizeof(attrs->class_name));
7644 hittest = SendMessageA(hwnd, WM_NCHITTEST, 0, 0);
7646 attrs->is_visible = (style & WS_VISIBLE) != 0;
7647 attrs->is_enabled = (style & WS_DISABLED) == 0;
7648 attrs->is_groupbox = !lstrcmpiA(attrs->class_name, "Button") && (style & BS_TYPEMASK) == BS_GROUPBOX;
7649 attrs->is_httransparent = hittest == HTTRANSPARENT;
7650 attrs->is_extransparent = (ex_style & WS_EX_TRANSPARENT) != 0;
7653 static int window_to_index(HWND hwnd, HWND *window, int size)
7655 int i;
7657 for (i = 0; i < size; i++)
7659 if (!window[i]) break;
7660 if (window[i] == hwnd) return i;
7662 return -1;
7665 static void test_child_window_from_point(void)
7667 static const int real_child_pos[] = { 14,15,16,17,18,19,20,21,24,25,26,27,42,43,
7668 44,45,46,47,48,49,52,53,54,55,51,50,23,22,-1 };
7669 static const int real_child_pos_nt4[] = { 14,15,16,17,20,21,24,25,26,27,42,43,44,45,
7670 48,49,52,53,54,55,51,50,47,46,23,22,19,18,-1 };
7671 WNDCLASSA cls;
7672 HWND hwnd, parent, window[100];
7673 POINT pt;
7674 int found_invisible, found_disabled, found_groupbox, found_httransparent, found_extransparent;
7675 int ret, i;
7677 ret = GetClassInfoA(0, "Button", &cls);
7678 ok(ret, "GetClassInfo(Button) failed\n");
7679 cls.lpszClassName = "my_button";
7680 ret = RegisterClassA(&cls);
7681 ok(ret, "RegisterClass(my_button) failed\n");
7683 cls.lpszClassName = "my_httrasparent";
7684 cls.lpfnWndProc = my_httrasparent_proc;
7685 ret = RegisterClassA(&cls);
7686 ok(ret, "RegisterClass(my_httrasparent) failed\n");
7688 cls.lpszClassName = "my_window";
7689 cls.lpfnWndProc = my_window_proc;
7690 ret = RegisterClassA(&cls);
7691 ok(ret, "RegisterClass(my_window) failed\n");
7693 parent = CreateWindowExA(0, "MainWindowClass", NULL,
7694 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE,
7695 100, 100, 200, 200,
7696 0, 0, GetModuleHandleA(NULL), NULL);
7697 ok(parent != 0, "CreateWindowEx failed\n");
7698 trace("parent %p\n", parent);
7700 create_window_tree(parent, window, sizeof(window)/sizeof(window[0]));
7702 found_invisible = 0;
7703 found_disabled = 0;
7704 found_groupbox = 0;
7705 found_httransparent = 0;
7706 found_extransparent = 0;
7708 /* FIXME: also test WindowFromPoint, ChildWindowFromPoint, ChildWindowFromPointEx */
7709 for (i = 0; i < sizeof(real_child_pos)/sizeof(real_child_pos[0]); i++)
7711 struct window_attributes attrs;
7713 pt.x = pt.y = 50;
7714 hwnd = RealChildWindowFromPoint(parent, pt);
7715 ok(hwnd != 0, "RealChildWindowFromPoint failed\n");
7716 ret = window_to_index(hwnd, window, sizeof(window)/sizeof(window[0]));
7717 /* FIXME: remove once Wine is fixed */
7718 todo_wine_if (ret != real_child_pos[i])
7719 ok(ret == real_child_pos[i] || broken(ret == real_child_pos_nt4[i]), "expected %d, got %d\n", real_child_pos[i], ret);
7721 get_window_attributes(hwnd, &attrs);
7722 if (!attrs.is_visible) found_invisible++;
7723 if (!attrs.is_enabled) found_disabled++;
7724 if (attrs.is_groupbox) found_groupbox++;
7725 if (attrs.is_httransparent) found_httransparent++;
7726 if (attrs.is_extransparent) found_extransparent++;
7728 if (ret != real_child_pos[i] && ret != -1)
7730 trace("found hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n",
7731 hwnd, attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent);
7732 get_window_attributes(window[real_child_pos[i]], &attrs);
7733 trace("expected hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n",
7734 window[real_child_pos[i]], attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent);
7736 if (ret == -1)
7738 ok(hwnd == parent, "expected %p, got %p\n", parent, hwnd);
7739 break;
7741 DestroyWindow(hwnd);
7744 DestroyWindow(parent);
7746 ok(!found_invisible, "found %d invisible windows\n", found_invisible);
7747 ok(found_disabled, "found %d disabled windows\n", found_disabled);
7748 todo_wine
7749 ok(found_groupbox == 4, "found %d groupbox windows\n", found_groupbox);
7750 ok(found_httransparent, "found %d httransparent windows\n", found_httransparent);
7751 todo_wine
7752 ok(found_extransparent, "found %d extransparent windows\n", found_extransparent);
7754 ret = UnregisterClassA("my_button", cls.hInstance);
7755 ok(ret, "UnregisterClass(my_button) failed\n");
7756 ret = UnregisterClassA("my_httrasparent", cls.hInstance);
7757 ok(ret, "UnregisterClass(my_httrasparent) failed\n");
7758 ret = UnregisterClassA("my_window", cls.hInstance);
7759 ok(ret, "UnregisterClass(my_window) failed\n");
7762 static void simulate_click(int x, int y)
7764 INPUT input[2];
7765 UINT events_no;
7767 SetCursorPos(x, y);
7768 memset(input, 0, sizeof(input));
7769 input[0].type = INPUT_MOUSE;
7770 U(input[0]).mi.dx = x;
7771 U(input[0]).mi.dy = y;
7772 U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
7773 input[1].type = INPUT_MOUSE;
7774 U(input[1]).mi.dx = x;
7775 U(input[1]).mi.dy = y;
7776 U(input[1]).mi.dwFlags = MOUSEEVENTF_LEFTUP;
7777 events_no = SendInput(2, input, sizeof(input[0]));
7778 ok(events_no == 2, "SendInput returned %d\n", events_no);
7781 static WNDPROC def_static_proc;
7782 static BOOL got_hittest;
7783 static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
7785 if(msg == WM_NCHITTEST)
7786 got_hittest = TRUE;
7787 if(msg == WM_LBUTTONDOWN)
7788 ok(0, "unexpected call\n");
7790 return def_static_proc(hwnd, msg, wp, lp);
7793 static void window_from_point_proc(HWND parent)
7795 HANDLE start_event, end_event;
7796 HANDLE win, child_static, child_button;
7797 BOOL got_click;
7798 DWORD ret;
7799 POINT pt;
7800 MSG msg;
7802 start_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_start");
7803 ok(start_event != 0, "OpenEvent failed\n");
7804 end_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_end");
7805 ok(end_event != 0, "OpenEvent failed\n");
7807 child_static = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
7808 0, 0, 100, 100, parent, 0, NULL, NULL);
7809 ok(child_static != 0, "CreateWindowEx failed\n");
7810 pt.x = pt.y = 150;
7811 win = WindowFromPoint(pt);
7812 ok(win == parent, "WindowFromPoint returned %p, expected %p\n", win, parent);
7814 child_button = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
7815 100, 0, 100, 100, parent, 0, NULL, NULL);
7816 ok(child_button != 0, "CreateWindowEx failed\n");
7817 pt.x = 250;
7818 win = WindowFromPoint(pt);
7819 ok(win == child_button, "WindowFromPoint returned %p, expected %p\n", win, child_button);
7821 /* without this window simulate click test keeps sending WM_NCHITTEST
7822 * message to child_static in an infinite loop */
7823 win = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
7824 0, 0, 100, 100, parent, 0, NULL, NULL);
7825 ok(win != 0, "CreateWindowEx failed\n");
7826 def_static_proc = (void*)SetWindowLongPtrA(child_static,
7827 GWLP_WNDPROC, (LONG_PTR)static_hook_proc);
7828 flush_events(TRUE);
7829 SetEvent(start_event);
7831 got_hittest = FALSE;
7832 got_click = FALSE;
7833 while(!got_click && wait_for_message(&msg)) {
7834 if(msg.message == WM_LBUTTONUP) {
7835 ok(msg.hwnd == win, "msg.hwnd = %p, expected %p\n", msg.hwnd, win);
7836 got_click = TRUE;
7838 DispatchMessageA(&msg);
7840 ok(got_hittest, "transparent window didn't get WM_NCHITTEST message\n");
7841 ok(got_click, "button under static window didn't get WM_LBUTTONUP\n");
7843 ret = WaitForSingleObject(end_event, 5000);
7844 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret);
7846 CloseHandle(start_event);
7847 CloseHandle(end_event);
7850 static void test_window_from_point(const char *argv0)
7852 HWND hwnd, child, win;
7853 POINT pt;
7854 PROCESS_INFORMATION info;
7855 STARTUPINFOA startup;
7856 char cmd[MAX_PATH];
7857 HANDLE start_event, end_event;
7859 hwnd = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP | WS_VISIBLE,
7860 100, 100, 200, 100, 0, 0, NULL, NULL);
7861 ok(hwnd != 0, "CreateWindowEx failed\n");
7863 pt.x = pt.y = 150;
7864 win = WindowFromPoint(pt);
7865 pt.x = 250;
7866 if(win == hwnd)
7867 win = WindowFromPoint(pt);
7868 if(win != hwnd) {
7869 skip("there's another window covering test window\n");
7870 DestroyWindow(hwnd);
7871 return;
7874 child = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE,
7875 0, 0, 100, 100, hwnd, 0, NULL, NULL);
7876 ok(child != 0, "CreateWindowEx failed\n");
7877 pt.x = pt.y = 150;
7878 win = WindowFromPoint(pt);
7879 ok(win == hwnd, "WindowFromPoint returned %p, expected %p\n", win, hwnd);
7880 DestroyWindow(child);
7882 child = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE,
7883 0, 0, 100, 100, hwnd, 0, NULL, NULL);
7884 ok(child != 0, "CreateWindowEx failed\n");
7885 win = WindowFromPoint(pt);
7886 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
7887 DestroyWindow(child);
7889 start_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_start");
7890 ok(start_event != 0, "CreateEvent failed\n");
7891 end_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_end");
7892 ok(start_event != 0, "CreateEvent failed\n");
7894 sprintf(cmd, "%s win create_children %p\n", argv0, hwnd);
7895 memset(&startup, 0, sizeof(startup));
7896 startup.cb = sizeof(startup);
7897 ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
7898 &startup, &info), "CreateProcess failed.\n");
7899 ok(wait_for_event(start_event, 1000), "didn't get start_event\n");
7901 child = GetWindow(hwnd, GW_CHILD);
7902 win = WindowFromPoint(pt);
7903 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
7905 simulate_click(150, 150);
7906 flush_events(TRUE);
7908 child = GetWindow(child, GW_HWNDNEXT);
7909 pt.x = 250;
7910 win = WindowFromPoint(pt);
7911 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child);
7913 SetEvent(end_event);
7914 winetest_wait_child_process(info.hProcess);
7915 CloseHandle(start_event);
7916 CloseHandle(end_event);
7917 CloseHandle(info.hProcess);
7918 CloseHandle(info.hThread);
7920 DestroyWindow(hwnd);
7923 static void test_map_points(void)
7925 BOOL ret;
7926 POINT p;
7927 HWND wnd, wnd0, dwnd;
7928 INT n;
7929 DWORD err;
7930 POINT pos = { 100, 200 };
7931 int width = 150;
7932 int height = 150;
7933 RECT window_rect;
7934 RECT client_rect;
7936 /* Create test windows */
7937 wnd = CreateWindowA("static", "test1", WS_POPUP, pos.x, pos.y, width, height, NULL, NULL, NULL, NULL);
7938 ok(wnd != NULL, "Failed %p\n", wnd);
7939 wnd0 = CreateWindowA("static", "test2", WS_POPUP, 0, 0, width, height, NULL, NULL, NULL, NULL);
7940 ok(wnd0 != NULL, "Failed %p\n", wnd);
7941 dwnd = CreateWindowA("static", "test3", 0, 200, 300, 150, 150, NULL, NULL, NULL, NULL);
7942 DestroyWindow(dwnd);
7943 ok(dwnd != NULL, "Failed %p\n", dwnd);
7945 /* Verify window rect and client rect (they should have the same width and height) */
7946 GetWindowRect(wnd, &window_rect);
7947 ok(window_rect.left == pos.x, "left is %d instead of %d\n", window_rect.left, pos.x);
7948 ok(window_rect.top == pos.y, "top is %d instead of %d\n", window_rect.top, pos.y);
7949 ok(window_rect.right == pos.x + width, "right is %d instead of %d\n", window_rect.right, pos.x + width);
7950 ok(window_rect.bottom == pos.y + height, "bottom is %d instead of %d\n", window_rect.bottom, pos.y + height);
7951 GetClientRect(wnd, &client_rect);
7952 ok(client_rect.left == 0, "left is %d instead of 0\n", client_rect.left);
7953 ok(client_rect.top == 0, "top is %d instead of 0\n", client_rect.top);
7954 ok(client_rect.right == width, "right is %d instead of %d\n", client_rect.right, width);
7955 ok(client_rect.bottom == height, "bottom is %d instead of %d\n", client_rect.bottom, height);
7957 /* Test MapWindowPoints */
7959 /* MapWindowPoints(NULL or wnd, NULL or wnd, NULL, 1); crashes on Windows */
7961 SetLastError(0xdeadbeef);
7962 n = MapWindowPoints(NULL, NULL, NULL, 0);
7963 err = GetLastError();
7964 ok(n == 0, "Got %d, expected %d\n", n, 0);
7965 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
7967 SetLastError(0xdeadbeef);
7968 n = MapWindowPoints(wnd, wnd, NULL, 0);
7969 err = GetLastError();
7970 ok(n == 0, "Got %d, expected %d\n", n, 0);
7971 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
7973 n = MapWindowPoints(wnd, NULL, NULL, 0);
7974 ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n",
7975 n, MAKELONG(window_rect.left, window_rect.top));
7977 n = MapWindowPoints(NULL, wnd, NULL, 0);
7978 ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n",
7979 n, MAKELONG(-window_rect.left, -window_rect.top));
7981 SetLastError(0xdeadbeef);
7982 p.x = p.y = 100;
7983 n = MapWindowPoints(dwnd, NULL, &p, 1);
7984 err = GetLastError();
7985 ok(n == 0, "Got %d, expected %d\n", n, 0);
7986 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
7987 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
7989 SetLastError(0xdeadbeef);
7990 p.x = p.y = 100;
7991 n = MapWindowPoints(dwnd, wnd, &p, 1);
7992 err = GetLastError();
7993 ok(n == 0, "Got %d, expected %d\n", n, 0);
7994 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
7995 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
7997 SetLastError(0xdeadbeef);
7998 p.x = p.y = 100;
7999 n = MapWindowPoints(NULL, dwnd, &p, 1);
8000 err = GetLastError();
8001 ok(n == 0, "Got %d, expected %d\n", n, 0);
8002 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8003 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8005 SetLastError(0xdeadbeef);
8006 p.x = p.y = 100;
8007 n = MapWindowPoints(wnd, dwnd, &p, 1);
8008 err = GetLastError();
8009 ok(n == 0, "Got %d, expected %d\n", n, 0);
8010 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8011 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8013 SetLastError(0xdeadbeef);
8014 p.x = p.y = 100;
8015 n = MapWindowPoints(dwnd, dwnd, &p, 1);
8016 err = GetLastError();
8017 ok(n == 0, "Got %d, expected %d\n", n, 0);
8018 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8019 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8021 SetLastError(0xdeadbeef);
8022 p.x = p.y = 100;
8023 n = MapWindowPoints(NULL, NULL, &p, 1);
8024 err = GetLastError();
8025 ok(n == 0, "Got %d, expected %d\n", n, 0);
8026 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8027 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8029 SetLastError(0xdeadbeef);
8030 p.x = p.y = 100;
8031 n = MapWindowPoints(wnd, wnd, &p, 1);
8032 err = GetLastError();
8033 ok(n == 0, "Got %d, expected %d\n", n, 0);
8034 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8035 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8037 p.x = p.y = 100;
8038 n = MapWindowPoints(wnd, NULL, &p, 1);
8039 ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n",
8040 n, MAKELONG(window_rect.left, window_rect.top));
8041 ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8042 p.x, p.y, window_rect.left + 100, window_rect.top + 100);
8044 p.x = p.y = 100;
8045 n = MapWindowPoints(NULL, wnd, &p, 1);
8046 ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n",
8047 n, MAKELONG(-window_rect.left, -window_rect.top));
8048 ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8049 p.x, p.y, -window_rect.left + 100, -window_rect.top + 100);
8051 SetLastError(0xdeadbeef);
8052 p.x = p.y = 0;
8053 n = MapWindowPoints(wnd0, NULL, &p, 1);
8054 err = GetLastError();
8055 ok(n == 0, "Got %x, expected 0\n", n);
8056 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8057 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8059 SetLastError(0xdeadbeef);
8060 p.x = p.y = 0;
8061 n = MapWindowPoints(NULL, wnd0, &p, 1);
8062 err = GetLastError();
8063 ok(n == 0, "Got %x, expected 0\n", n);
8064 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8065 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef);
8067 /* Test ClientToScreen */
8069 /* ClientToScreen(wnd, NULL); crashes on Windows */
8071 SetLastError(0xdeadbeef);
8072 ret = ClientToScreen(NULL, NULL);
8073 err = GetLastError();
8074 ok(!ret, "Should fail\n");
8075 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8077 SetLastError(0xdeadbeef);
8078 p.x = p.y = 100;
8079 ret = ClientToScreen(NULL, &p);
8080 err = GetLastError();
8081 ok(!ret, "Should fail\n");
8082 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8083 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8085 SetLastError(0xdeadbeef);
8086 p.x = p.y = 100;
8087 ret = ClientToScreen(dwnd, &p);
8088 err = GetLastError();
8089 ok(!ret, "Should fail\n");
8090 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8091 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8093 p.x = p.y = 100;
8094 ret = ClientToScreen(wnd, &p);
8095 ok(ret, "Failed with error %u\n", GetLastError());
8096 ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n",
8097 p.x, p.y, window_rect.left + 100, window_rect.top + 100);
8099 p.x = p.y = 0;
8100 ret = ClientToScreen(wnd0, &p);
8101 ok(ret, "Failed with error %u\n", GetLastError());
8102 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8104 /* Test ScreenToClient */
8106 /* ScreenToClient(wnd, NULL); crashes on Windows */
8108 SetLastError(0xdeadbeef);
8109 ret = ScreenToClient(NULL, NULL);
8110 err = GetLastError();
8111 ok(!ret, "Should fail\n");
8112 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8114 SetLastError(0xdeadbeef);
8115 p.x = p.y = 100;
8116 ret = ScreenToClient(NULL, &p);
8117 err = GetLastError();
8118 ok(!ret, "Should fail\n");
8119 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8120 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8122 SetLastError(0xdeadbeef);
8123 p.x = p.y = 100;
8124 ret = ScreenToClient(dwnd, &p);
8125 err = GetLastError();
8126 ok(!ret, "Should fail\n");
8127 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100);
8128 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE);
8130 p.x = p.y = 100;
8131 ret = ScreenToClient(wnd, &p);
8132 ok(ret, "Failed with error %u\n", GetLastError());
8133 ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got(%d, %d), expected (%d, %d)\n",
8134 p.x, p.y, -window_rect.left + 100, -window_rect.top + 100);
8136 p.x = p.y = 0;
8137 ret = ScreenToClient(wnd0, &p);
8138 ok(ret, "Failed with error %u\n", GetLastError());
8139 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y);
8141 DestroyWindow(wnd);
8142 DestroyWindow(wnd0);
8145 static void test_update_region(void)
8147 HWND hwnd, parent, child;
8148 HRGN rgn1, rgn2;
8149 const RECT rc = {15, 15, 40, 40};
8150 const POINT wnd_orig = {30, 20};
8151 const POINT child_orig = {10, 5};
8153 parent = CreateWindowExA(0, "MainWindowClass", NULL,
8154 WS_VISIBLE | WS_CLIPCHILDREN,
8155 0, 0, 300, 150, NULL, NULL, GetModuleHandleA(0), 0);
8156 hwnd = CreateWindowExA(0, "MainWindowClass", NULL,
8157 WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD,
8158 0, 0, 200, 100, parent, NULL, GetModuleHandleA(0), 0);
8159 child = CreateWindowExA(0, "MainWindowClass", NULL,
8160 WS_VISIBLE | WS_CHILD,
8161 child_orig.x, child_orig.y, 100, 50,
8162 hwnd, NULL, GetModuleHandleA(0), 0);
8163 assert(parent && hwnd && child);
8165 ValidateRgn(parent, NULL);
8166 ValidateRgn(hwnd, NULL);
8167 InvalidateRect(hwnd, &rc, FALSE);
8168 ValidateRgn(child, NULL);
8170 rgn1 = CreateRectRgn(0, 0, 0, 0);
8171 ok(GetUpdateRgn(parent, rgn1, FALSE) == NULLREGION,
8172 "has invalid area after ValidateRgn(NULL)\n");
8173 GetUpdateRgn(hwnd, rgn1, FALSE);
8174 rgn2 = CreateRectRgnIndirect(&rc);
8175 ok(EqualRgn(rgn1, rgn2), "assigned and retrieved update regions are different\n");
8176 ok(GetUpdateRgn(child, rgn2, FALSE) == NULLREGION,
8177 "has invalid area after ValidateRgn(NULL)\n");
8179 SetWindowPos(hwnd, 0, wnd_orig.x, wnd_orig.y, 0, 0,
8180 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE);
8182 /* parent now has non-simple update region, it consist of
8183 * two rects, that was exposed after hwnd moving ... */
8184 SetRectRgn(rgn1, 0, 0, 200, wnd_orig.y);
8185 SetRectRgn(rgn2, 0, 0, wnd_orig.x, 100);
8186 CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
8187 /* ... and mapped hwnd's invalid area, that hwnd has before moving */
8188 SetRectRgn(rgn2, rc.left + wnd_orig.x, rc.top + wnd_orig.y,
8189 rc.right + wnd_orig.x, rc.bottom + wnd_orig.y);
8190 CombineRgn(rgn1, rgn1, rgn2, RGN_OR);
8191 GetUpdateRgn(parent, rgn2, FALSE);
8192 todo_wine
8193 ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8195 /* hwnd has the same invalid region as before moving */
8196 SetRectRgn(rgn1, rc.left, rc.top, rc.right, rc.bottom);
8197 GetUpdateRgn(hwnd, rgn2, FALSE);
8198 ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8200 /* hwnd's invalid area maps to child during moving */
8201 SetRectRgn(rgn1, rc.left - child_orig.x , rc.top - child_orig.y,
8202 rc.right - child_orig.x, rc.bottom - child_orig.y);
8203 GetUpdateRgn(child, rgn2, FALSE);
8204 todo_wine
8205 ok(EqualRgn(rgn1, rgn2), "wrong update region\n");
8207 DeleteObject(rgn1);
8208 DeleteObject(rgn2);
8209 DestroyWindow(parent);
8212 static void test_window_without_child_style(void)
8214 HWND hwnd;
8216 hwnd = CreateWindowExA(0, "edit", NULL, WS_VISIBLE|WS_CHILD,
8217 0, 0, 50, 50, hwndMain, NULL, 0, NULL);
8218 ok(hwnd != NULL, "CreateWindow failed\n");
8220 ok(SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & (~WS_CHILD)),
8221 "can't remove WS_CHILD style\n");
8223 SetActiveWindow(hwndMain);
8224 PostMessageW(hwnd, WM_LBUTTONUP, 0, 0);
8225 SendMessageW(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
8226 check_active_state(hwnd, hwnd, hwnd);
8227 flush_events(TRUE);
8229 DestroyWindow(hwnd);
8233 struct smresult_thread_data
8235 HWND main_hwnd;
8236 HWND thread_hwnd;
8237 HANDLE thread_started;
8238 HANDLE thread_got_wm_app;
8239 HANDLE main_in_wm_app_1;
8240 HANDLE thread_replied;
8244 static LRESULT WINAPI smresult_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
8246 switch (msg)
8248 case WM_APP:
8250 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8252 ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
8254 SendNotifyMessageA(data->main_hwnd, WM_APP+1, 0, lparam);
8256 /* Don't return until the main thread is processing our sent message. */
8257 ok(WaitForSingleObject(data->main_in_wm_app_1, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8259 /* Break the PeekMessage loop so we can notify the main thread after we return. */
8260 SetEvent(data->thread_got_wm_app);
8262 return 0x240408ea;
8264 case WM_APP+1:
8266 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8267 LRESULT res;
8269 ok(hwnd == data->main_hwnd, "unexpected hwnd %p\n", hwnd);
8271 /* Ask the thread to reply to our WM_APP message. */
8272 SetEvent(data->main_in_wm_app_1);
8274 /* Wait until the thread has sent a reply. */
8275 ok(WaitForSingleObject(data->thread_replied, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8277 /* Send another message while we have a reply queued for the current one. */
8278 res = SendMessageA(data->thread_hwnd, WM_APP+2, 0, lparam);
8279 ok(res == 0x449b0190, "unexpected result %lx\n", res);
8281 return 0;
8283 case WM_APP+2:
8285 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam;
8287 ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd);
8289 /* Don't return until we know the main thread is processing sent messages. */
8290 SendMessageA(data->main_hwnd, WM_NULL, 0, 0);
8292 return 0x449b0190;
8294 case WM_CLOSE:
8295 PostQuitMessage(0);
8296 break;
8298 return DefWindowProcA(hwnd, msg, wparam, lparam);
8301 static DWORD WINAPI smresult_thread_proc(void *param)
8303 MSG msg;
8304 struct smresult_thread_data *data = param;
8306 data->thread_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
8307 100, 100, 200, 200, 0, 0, 0, NULL);
8308 ok(data->thread_hwnd != 0, "Failed to create overlapped window\n");
8310 SetEvent(data->thread_started);
8312 /* Loop until we've processed WM_APP. */
8313 while (WaitForSingleObject(data->thread_got_wm_app, 0) != WAIT_OBJECT_0)
8315 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
8317 TranslateMessage(&msg);
8318 DispatchMessageA(&msg);
8320 else
8322 MsgWaitForMultipleObjects(1, &data->thread_got_wm_app, FALSE, INFINITE, QS_SENDMESSAGE);
8326 /* Notify the main thread that we replied to its WM_APP message. */
8327 SetEvent(data->thread_replied);
8329 while (GetMessageA(&msg, 0, 0, 0))
8331 TranslateMessage(&msg);
8332 DispatchMessageA(&msg);
8335 return 0;
8338 static void test_smresult(void)
8340 WNDCLASSA cls;
8341 HANDLE hThread;
8342 DWORD tid;
8343 struct smresult_thread_data data;
8344 BOOL ret;
8345 LRESULT res;
8347 cls.style = CS_DBLCLKS;
8348 cls.lpfnWndProc = smresult_wndproc;
8349 cls.cbClsExtra = 0;
8350 cls.cbWndExtra = 0;
8351 cls.hInstance = GetModuleHandleA(0);
8352 cls.hIcon = 0;
8353 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
8354 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
8355 cls.lpszMenuName = NULL;
8356 cls.lpszClassName = "SmresultClass";
8358 ret = RegisterClassA(&cls);
8359 ok(ret, "RegisterClassA failed\n");
8361 data.thread_started = CreateEventA(NULL, TRUE, FALSE, NULL);
8362 ok(data.thread_started != NULL, "CreateEventA failed\n");
8364 data.thread_got_wm_app = CreateEventA(NULL, TRUE, FALSE, NULL);
8365 ok(data.thread_got_wm_app != NULL, "CreateEventA failed\n");
8367 data.main_in_wm_app_1 = CreateEventA(NULL, TRUE, FALSE, NULL);
8368 ok(data.main_in_wm_app_1 != NULL, "CreateEventA failed\n");
8370 data.thread_replied = CreateEventA(NULL, TRUE, FALSE, NULL);
8371 ok(data.thread_replied != NULL, "CreateEventA failed\n");
8373 data.main_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW,
8374 100, 100, 200, 200, 0, 0, 0, NULL);
8376 hThread = CreateThread(NULL, 0, smresult_thread_proc, &data, 0, &tid);
8377 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError());
8379 ok(WaitForSingleObject(data.thread_started, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8381 res = SendMessageA(data.thread_hwnd, WM_APP, 0, (LPARAM)&data);
8382 ok(res == 0x240408ea, "unexpected result %lx\n", res);
8384 SendMessageA(data.thread_hwnd, WM_CLOSE, 0, 0);
8386 DestroyWindow(data.main_hwnd);
8388 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n");
8390 CloseHandle(data.thread_started);
8391 CloseHandle(data.thread_got_wm_app);
8392 CloseHandle(data.main_in_wm_app_1);
8393 CloseHandle(data.thread_replied);
8396 static void test_GetMessagePos(void)
8398 HWND button;
8399 DWORD pos;
8400 MSG msg;
8402 button = CreateWindowExA(0, "button", "button", WS_VISIBLE,
8403 100, 100, 100, 100, 0, 0, 0, NULL);
8404 ok(button != 0, "CreateWindowExA failed\n");
8406 SetCursorPos(120, 140);
8407 flush_events(TRUE);
8408 pos = GetMessagePos();
8409 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8411 SetCursorPos(340, 320);
8412 pos = GetMessagePos();
8413 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8415 SendMessageW(button, WM_APP, 0, 0);
8416 pos = GetMessagePos();
8417 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos);
8419 PostMessageA(button, WM_APP, 0, 0);
8420 GetMessageA(&msg, button, 0, 0);
8421 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8422 pos = GetMessagePos();
8423 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8425 PostMessageA(button, WM_APP, 0, 0);
8426 SetCursorPos(350, 330);
8427 GetMessageA(&msg, button, 0, 0);
8428 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8429 pos = GetMessagePos();
8430 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8432 PostMessageA(button, WM_APP, 0, 0);
8433 SetCursorPos(320, 340);
8434 PostMessageA(button, WM_APP+1, 0, 0);
8435 pos = GetMessagePos();
8436 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos);
8437 GetMessageA(&msg, button, 0, 0);
8438 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message);
8439 pos = GetMessagePos();
8440 ok(pos == MAKELONG(350, 330), "pos = %08x\n", pos);
8441 GetMessageA(&msg, button, 0, 0);
8442 ok(msg.message == WM_APP+1, "msg.message = %x\n", msg.message);
8443 pos = GetMessagePos();
8444 ok(pos == MAKELONG(320, 340), "pos = %08x\n", pos);
8446 SetTimer(button, 1, 250, NULL);
8447 SetCursorPos(330, 350);
8448 GetMessageA(&msg, button, 0, 0);
8449 while (msg.message == WM_PAINT)
8451 UpdateWindow( button );
8452 GetMessageA(&msg, button, 0, 0);
8454 ok(msg.message == WM_TIMER, "msg.message = %x\n", msg.message);
8455 pos = GetMessagePos();
8456 ok(pos == MAKELONG(330, 350), "pos = %08x\n", pos);
8457 KillTimer(button, 1);
8459 DestroyWindow(button);
8462 #define SET_FOREGROUND_STEAL_1 0x01
8463 #define SET_FOREGROUND_SET_1 0x02
8464 #define SET_FOREGROUND_STEAL_2 0x04
8465 #define SET_FOREGROUND_SET_2 0x08
8466 #define SET_FOREGROUND_INJECT 0x10
8468 struct set_foreground_thread_params
8470 UINT msg_quit, msg_command;
8471 HWND window1, window2, thread_window;
8472 HANDLE command_executed;
8475 static DWORD WINAPI set_foreground_thread(void *params)
8477 struct set_foreground_thread_params *p = params;
8478 MSG msg;
8480 p->thread_window = CreateWindowExA(0, "static", "thread window", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8481 0, 0, 10, 10, 0, 0, 0, NULL);
8482 SetEvent(p->command_executed);
8484 while(GetMessageA(&msg, 0, 0, 0))
8486 if (msg.message == p->msg_quit)
8487 break;
8489 if (msg.message == p->msg_command)
8491 if (msg.wParam & SET_FOREGROUND_STEAL_1)
8493 SetForegroundWindow(p->thread_window);
8494 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
8496 if (msg.wParam & SET_FOREGROUND_INJECT)
8498 SendNotifyMessageA(p->window1, WM_ACTIVATEAPP, 0, 0);
8500 if (msg.wParam & SET_FOREGROUND_SET_1)
8502 SetForegroundWindow(p->window1);
8503 check_wnd_state(0, p->window1, 0, 0);
8505 if (msg.wParam & SET_FOREGROUND_STEAL_2)
8507 SetForegroundWindow(p->thread_window);
8508 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0);
8510 if (msg.wParam & SET_FOREGROUND_SET_2)
8512 SetForegroundWindow(p->window2);
8513 check_wnd_state(0, p->window2, 0, 0);
8516 SetEvent(p->command_executed);
8517 continue;
8520 TranslateMessage(&msg);
8521 DispatchMessageA(&msg);
8524 DestroyWindow(p->thread_window);
8525 return 0;
8528 static void test_activateapp(HWND window1)
8530 HWND window2, test_window;
8531 HANDLE thread;
8532 struct set_foreground_thread_params thread_params;
8533 DWORD tid;
8534 MSG msg;
8536 window2 = CreateWindowExA(0, "static", "window 2", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
8537 300, 0, 10, 10, 0, 0, 0, NULL);
8538 thread_params.msg_quit = WM_USER;
8539 thread_params.msg_command = WM_USER + 1;
8540 thread_params.window1 = window1;
8541 thread_params.window2 = window2;
8542 thread_params.command_executed = CreateEventW(NULL, FALSE, FALSE, NULL);
8544 thread = CreateThread(NULL, 0, set_foreground_thread, &thread_params, 0, &tid);
8545 WaitForSingleObject(thread_params.command_executed, INFINITE);
8547 SetForegroundWindow(window1);
8548 check_wnd_state(window1, window1, window1, 0);
8549 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8551 /* Steal foreground: WM_ACTIVATEAPP(0) is delivered. */
8552 app_activated = app_deactivated = FALSE;
8553 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1, 0);
8554 WaitForSingleObject(thread_params.command_executed, INFINITE);
8555 test_window = GetForegroundWindow();
8556 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
8557 thread_params.thread_window, test_window);
8558 /* Active and Focus window are sometimes 0 on KDE. Ignore them.
8559 * check_wnd_state(window1, thread_params.thread_window, window1, 0); */
8560 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8561 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8562 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8563 check_wnd_state(0, thread_params.thread_window, 0, 0);
8564 test_window = GetForegroundWindow();
8565 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
8566 thread_params.thread_window, test_window);
8567 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8568 /* This message is reliable on Windows and inside a virtual desktop.
8569 * It is unreliable on KDE (50/50) and never arrives on FVWM.
8570 * ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); */
8572 /* Set foreground: WM_ACTIVATEAPP (1) is delivered. */
8573 app_activated = app_deactivated = FALSE;
8574 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1, 0);
8575 WaitForSingleObject(thread_params.command_executed, INFINITE);
8576 check_wnd_state(0, 0, 0, 0);
8577 test_window = GetForegroundWindow();
8578 ok(!test_window, "Expected foreground window 0, got %p\n", test_window);
8579 ok(!app_activated, "Received WM_ACTIVATEAPP(!= 0), did not expect it.\n");
8580 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8581 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8582 check_wnd_state(window1, window1, window1, 0);
8583 test_window = GetForegroundWindow();
8584 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8585 window1, test_window);
8586 ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
8587 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8589 /* Steal foreground then set it back: No messages are delivered. */
8590 app_activated = app_deactivated = FALSE;
8591 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_1, 0);
8592 WaitForSingleObject(thread_params.command_executed, INFINITE);
8593 test_window = GetForegroundWindow();
8594 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8595 window1, test_window);
8596 check_wnd_state(window1, window1, window1, 0);
8597 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8598 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8599 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8600 test_window = GetForegroundWindow();
8601 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8602 window1, test_window);
8603 check_wnd_state(window1, window1, window1, 0);
8604 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8605 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8607 /* This is not implemented with a plain WM_ACTIVATEAPP filter. */
8608 app_activated = app_deactivated = FALSE;
8609 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1
8610 | SET_FOREGROUND_INJECT | SET_FOREGROUND_SET_1, 0);
8611 WaitForSingleObject(thread_params.command_executed, INFINITE);
8612 test_window = GetForegroundWindow();
8613 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8614 window1, test_window);
8615 check_wnd_state(window1, window1, window1, 0);
8616 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8617 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8618 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8619 test_window = GetForegroundWindow();
8620 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8621 window1, test_window);
8622 check_wnd_state(window1, window1, window1, 0);
8623 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8624 ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
8626 SetForegroundWindow(thread_params.thread_window);
8628 /* Set foreground then remove: Both messages are delivered. */
8629 app_activated = app_deactivated = FALSE;
8630 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1 | SET_FOREGROUND_STEAL_2, 0);
8631 WaitForSingleObject(thread_params.command_executed, INFINITE);
8632 test_window = GetForegroundWindow();
8633 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
8634 thread_params.thread_window, test_window);
8635 check_wnd_state(0, thread_params.thread_window, 0, 0);
8636 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8637 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8638 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8639 test_window = GetForegroundWindow();
8640 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n",
8641 thread_params.thread_window, test_window);
8642 /* Active and focus are window1 on wine because the internal WM_WINE_SETACTIVEWINDOW(0)
8643 * message is never generated. GetCapture() returns 0 though, so we'd get a test success
8644 * in todo_wine in the line below.
8645 * todo_wine check_wnd_state(0, thread_params.thread_window, 0, 0); */
8646 ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n");
8647 todo_wine ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n");
8649 SetForegroundWindow(window1);
8650 test_window = GetForegroundWindow();
8651 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8652 window1, test_window);
8653 check_wnd_state(window1, window1, window1, 0);
8655 /* Switch to a different window from the same thread? No messages. */
8656 app_activated = app_deactivated = FALSE;
8657 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_2, 0);
8658 WaitForSingleObject(thread_params.command_executed, INFINITE);
8659 test_window = GetForegroundWindow();
8660 ok(test_window == window1, "Expected foreground window %p, got %p\n",
8661 window1, test_window);
8662 check_wnd_state(window1, window1, window1, 0);
8663 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8664 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8665 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
8666 test_window = GetForegroundWindow();
8667 ok(test_window == window2, "Expected foreground window %p, got %p\n",
8668 window2, test_window);
8669 check_wnd_state(window2, window2, window2, 0);
8670 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n");
8671 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n");
8673 PostThreadMessageA(tid, thread_params.msg_quit, 0, 0);
8674 WaitForSingleObject(thread, INFINITE);
8676 CloseHandle(thread_params.command_executed);
8677 DestroyWindow(window2);
8680 static LRESULT WINAPI winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
8682 if(!hwnd) {
8683 int *count = (int*)lparam;
8684 (*count)++;
8686 return 0;
8689 static LRESULT WINAPI winproc_convA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
8691 if(msg == WM_SETTEXT)
8693 const char *text = (const char*)lparam;
8695 ok(!wparam, "wparam = %08lx\n", wparam);
8696 ok(!strcmp(text, "text"), "WM_SETTEXT lparam = %s\n", text);
8697 return 1;
8699 return 0;
8702 static const WCHAR textW[] = {'t','e','x','t',0};
8703 static LRESULT WINAPI winproc_convW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
8705 if(msg == WM_SETTEXT)
8707 const WCHAR *text = (const WCHAR*)lparam;
8709 ok(!wparam, "wparam = %08lx\n", wparam);
8710 ok(!lstrcmpW(text, textW), "WM_SETTEXT lparam = %s\n", wine_dbgstr_w(text));
8711 return 1;
8713 return 0;
8716 static void test_winproc_handles(const char *argv0)
8718 static const WCHAR winproc_testW[] = {'w','i','n','p','r','o','c','_','t','e','s','t',0};
8720 HINSTANCE hinst = GetModuleHandleA(NULL);
8721 WNDCLASSA wnd_classA;
8722 WNDCLASSW wnd_classW;
8723 int count;
8724 PROCESS_INFORMATION info;
8725 STARTUPINFOA startup;
8726 char cmd[MAX_PATH];
8728 memset(&wnd_classA, 0, sizeof(wnd_classA));
8729 wnd_classA.lpszClassName = "winproc_test";
8730 wnd_classA.lpfnWndProc = winproc;
8731 ok(RegisterClassA(&wnd_classA),
8732 "RegisterClass failed with error %d\n", GetLastError());
8734 ok(GetClassInfoW(hinst, winproc_testW, &wnd_classW),
8735 "GetClassInfoW failed with error %d\n", GetLastError());
8736 ok(wnd_classA.lpfnWndProc != wnd_classW.lpfnWndProc,
8737 "winproc pointers should not be identical\n");
8739 count = 0;
8740 CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
8741 ok(count == 1, "winproc should be called once (%d)\n", count);
8742 count = 0;
8743 CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
8744 ok(count == 1, "winproc should be called once (%d)\n", count);
8746 ok(UnregisterClassW(winproc_testW, hinst),
8747 "UnregisterClass failed with error %d\n", GetLastError());
8748 /* crashes on 64-bit windows because lpfnWndProc handle is already freed */
8749 if (sizeof(void*) == 4)
8751 count = 0;
8752 CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
8753 todo_wine ok(!count, "winproc should not be called (%d)\n", count);
8754 CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count);
8755 todo_wine ok(!count, "winproc should not be called (%d)\n", count);
8758 sprintf(cmd, "%s win winproc_limit", argv0);
8759 memset(&startup, 0, sizeof(startup));
8760 startup.cb = sizeof(startup);
8761 ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL,
8762 &startup, &info), "CreateProcess failed.\n");
8763 winetest_wait_child_process(info.hProcess);
8764 CloseHandle(info.hProcess);
8765 CloseHandle(info.hThread);
8768 static void test_winproc_limit(void)
8770 WNDPROC winproc_handle;
8771 HWND hwnd;
8772 int i;
8774 hwnd = CreateWindowExA(0, "static", "test", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0);
8775 ok(hwnd != 0, "CreateWindowEx failed\n");
8777 ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc),
8778 "SetWindowLongPtr failed\n");
8779 winproc_handle = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC);
8780 ok(winproc_handle != winproc, "winproc pointers should not be identical\n");
8782 /* run out of winproc slots */
8783 for(i = 2; i<0xffff; i++)
8785 ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, i), "SetWindowLongPtr failed (%d)\n", i);
8786 if(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == i)
8787 break;
8789 ok(i != 0xffff, "unable to run out of winproc slots\n");
8791 ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convA),
8792 "SetWindowLongPtr failed with error %d\n", GetLastError());
8793 ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
8794 ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
8796 ok(SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convW),
8797 "SetWindowLongPtr failed with error %d\n", GetLastError());
8798 ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n");
8799 ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n");
8801 /* Show that there's no message conversion when CallWindowProc is used */
8802 ok(CallWindowProcA(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
8803 "winproc_convW returned error\n");
8804 ok(CallWindowProcW(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1,
8805 "winproc_convW returned error\n");
8807 i = 0;
8808 CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
8809 ok(i == 1, "winproc should be called once (%d)\n", i);
8810 i = 0;
8811 CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
8812 ok(i == 1, "winproc should be called once (%d)\n", i);
8814 DestroyWindow(hwnd);
8816 i = 0;
8817 CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i);
8818 ok(i == 1, "winproc should be called once (%d)\n", i);
8819 i = 0;
8820 CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i);
8821 ok(i == 1, "winproc should be called once (%d)\n", i);
8824 START_TEST(win)
8826 char **argv;
8827 int argc = winetest_get_mainargs( &argv );
8828 HMODULE user32 = GetModuleHandleA( "user32.dll" );
8829 HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
8830 pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" );
8831 pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" );
8832 pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" );
8833 pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" );
8834 pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" );
8835 pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" );
8836 pUpdateLayeredWindowIndirect = (void *)GetProcAddress( user32, "UpdateLayeredWindowIndirect" );
8837 pGetMonitorInfoA = (void *)GetProcAddress( user32, "GetMonitorInfoA" );
8838 pMonitorFromPoint = (void *)GetProcAddress( user32, "MonitorFromPoint" );
8839 pGetWindowRgnBox = (void *)GetProcAddress( user32, "GetWindowRgnBox" );
8840 pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" );
8841 pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" );
8842 pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" );
8843 pFlashWindow = (void *)GetProcAddress( user32, "FlashWindow" );
8844 pFlashWindowEx = (void *)GetProcAddress( user32, "FlashWindowEx" );
8845 pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" );
8846 pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" );
8847 pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" );
8849 if (argc==4 && !strcmp(argv[2], "create_children"))
8851 HWND hwnd;
8853 sscanf(argv[3], "%p", &hwnd);
8854 window_from_point_proc(hwnd);
8855 return;
8858 if (argc==3 && !strcmp(argv[2], "winproc_limit"))
8860 test_winproc_limit();
8861 return;
8864 if (!RegisterWindowClasses()) assert(0);
8866 hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
8867 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
8868 WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE,
8869 100, 100, 200, 200,
8870 0, 0, GetModuleHandleA(NULL), NULL);
8871 assert( hwndMain );
8873 if(!SetForegroundWindow(hwndMain)) {
8874 /* workaround for foreground lock timeout */
8875 simulate_click(101, 101);
8876 ok(SetForegroundWindow(hwndMain), "SetForegroundWindow failed\n");
8879 SetLastError(0xdeafbeef);
8880 GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC);
8881 is_win9x = (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
8883 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
8884 if (!hhook) win_skip( "Cannot set CBT hook, skipping some tests\n" );
8886 /* make sure that these tests are executed first */
8887 test_FindWindowEx();
8888 test_SetParent();
8890 hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
8891 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
8892 WS_MAXIMIZEBOX | WS_POPUP,
8893 100, 100, 200, 200,
8894 0, 0, GetModuleHandleA(NULL), NULL);
8895 assert( hwndMain2 );
8897 our_pid = GetWindowThreadProcessId(hwndMain, NULL);
8899 /* Add the tests below this line */
8900 test_child_window_from_point();
8901 test_window_from_point(argv[0]);
8902 test_thick_child_size(hwndMain);
8903 test_fullscreen();
8904 test_hwnd_message();
8905 test_nonclient_area(hwndMain);
8906 test_params();
8907 test_GetWindowModuleFileName();
8908 test_capture_1();
8909 test_capture_2();
8910 test_capture_3(hwndMain, hwndMain2);
8911 test_capture_4();
8912 test_rtl_layout();
8913 test_FlashWindow();
8914 test_FlashWindowEx();
8916 test_CreateWindow();
8917 test_parent_owner();
8918 test_enum_thread_windows();
8920 test_mdi();
8921 test_icons();
8922 test_SetWindowPos(hwndMain, hwndMain2);
8923 test_SetMenu(hwndMain);
8924 test_SetFocus(hwndMain);
8925 test_SetActiveWindow(hwndMain);
8926 test_NCRedraw();
8928 test_children_zorder(hwndMain);
8929 test_popup_zorder(hwndMain2, hwndMain, WS_POPUP);
8930 test_popup_zorder(hwndMain2, hwndMain, 0);
8931 test_GetLastActivePopup();
8932 test_keyboard_input(hwndMain);
8933 test_mouse_input(hwndMain);
8934 test_validatergn(hwndMain);
8935 test_nccalcscroll( hwndMain);
8936 test_scrollwindow( hwndMain);
8937 test_scrollvalidate( hwndMain);
8938 test_scrolldc( hwndMain);
8939 test_scroll();
8940 test_IsWindowUnicode();
8941 test_vis_rgn(hwndMain);
8943 test_AdjustWindowRect();
8944 test_window_styles();
8945 test_dialog_styles();
8946 test_redrawnow();
8947 test_csparentdc();
8948 test_SetWindowLong();
8949 test_ShowWindow();
8950 test_gettext();
8951 test_GetUpdateRect();
8952 test_Expose();
8953 test_layered_window();
8955 test_SetForegroundWindow(hwndMain);
8956 test_shell_window();
8957 test_handles( hwndMain );
8958 test_winregion();
8959 test_map_points();
8960 test_update_region();
8961 test_window_without_child_style();
8962 test_smresult();
8963 test_GetMessagePos();
8964 test_activateapp(hwndMain);
8965 test_winproc_handles(argv[0]);
8967 /* add the tests above this line */
8968 if (hhook) UnhookWindowsHookEx(hhook);
8970 DestroyWindow(hwndMain2);
8971 DestroyWindow(hwndMain);