[USER32_WINETEST] Sync with Wine Staging 1.7.55 except clipboard tests. CORE-10536
[reactos.git] / rostests / winetests / user32 / win.c
1 /*
2 * Unit tests for window handling
3 *
4 * Copyright 2002 Bill Medland
5 * Copyright 2002 Alexandre Julliard
6 * Copyright 2003 Dmitry Timoshkov
7 *
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.
12 *
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.
17 *
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
21 */
22
23 /* To get ICON_SMALL2 with the MSVC headers */
24 //#define _WIN32_WINNT 0x0501
25
26 #include <assert.h>
27 #include <stdlib.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35
36 #include "wine/test.h"
37
38 #ifndef SPI_GETDESKWALLPAPER
39 #define SPI_GETDESKWALLPAPER 0x0073
40 #endif
41
42 #define LONG_PTR INT_PTR
43 #define ULONG_PTR UINT_PTR
44
45 void dump_region(HRGN hrgn);
46
47 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
48 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
49 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT);
50 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*);
51 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
52 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
53 static BOOL (WINAPI *pUpdateLayeredWindowIndirect)(HWND,const UPDATELAYEREDWINDOWINFO*);
54 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
55 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
56 static int (WINAPI *pGetWindowRgnBox)(HWND,LPRECT);
57 static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*);
58 static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout );
59 static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout );
60 static BOOL (WINAPI *pFlashWindow)( HWND hwnd, BOOL bInvert );
61 static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi );
62 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
63 static DWORD (WINAPI *pGetLayout)(HDC hdc);
64 static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn);
65
66 static BOOL test_lbuttondown_flag;
67 static DWORD num_gettext_msgs;
68 static DWORD num_settext_msgs;
69 static HWND hwndMessage;
70 static HWND hwndMain, hwndMain2;
71 static HHOOK hhook;
72 static BOOL app_activated, app_deactivated;
73
74 static const char* szAWRClass = "Winsize";
75 static HMENU hmenu;
76 static DWORD our_pid;
77
78 static BOOL is_win9x = FALSE;
79
80 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
81
82 static void dump_minmax_info( const MINMAXINFO *minmax )
83 {
84 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
85 minmax->ptReserved.x, minmax->ptReserved.y,
86 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
87 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
88 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
89 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
90 }
91
92 /* try to make sure pending X events have been processed before continuing */
93 static void flush_events( BOOL remove_messages )
94 {
95 MSG msg;
96 int diff = 200;
97 int min_timeout = 100;
98 DWORD time = GetTickCount() + diff;
99
100 while (diff > 0)
101 {
102 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
103 if (remove_messages)
104 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg );
105 diff = time - GetTickCount();
106 min_timeout = 50;
107 }
108 }
109
110 static BOOL wait_for_event(HANDLE event, int timeout)
111 {
112 DWORD end_time = GetTickCount() + timeout;
113 MSG msg;
114
115 do {
116 if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
117 return TRUE;
118 while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
119 DispatchMessageA(&msg);
120 timeout = end_time - GetTickCount();
121 }while(timeout > 0);
122
123 return FALSE;
124 }
125
126 /* check the values returned by the various parent/owner functions on a given window */
127 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
128 HWND gw_owner, HWND ga_root, HWND ga_root_owner )
129 {
130 HWND res;
131
132 if (pGetAncestor)
133 {
134 res = pGetAncestor( hwnd, GA_PARENT );
135 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
136 }
137 res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
138 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
139 res = GetParent( hwnd );
140 ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
141 res = GetWindow( hwnd, GW_OWNER );
142 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
143 if (pGetAncestor)
144 {
145 res = pGetAncestor( hwnd, GA_ROOT );
146 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
147 res = pGetAncestor( hwnd, GA_ROOTOWNER );
148 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
149 }
150 }
151
152 #define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
153 static void check_wnd_state_(const char *file, int line,
154 HWND active, HWND foreground, HWND focus, HWND capture)
155 {
156 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
157 /* only check foreground if it belongs to the current thread */
158 /* foreground can be moved to a different app pretty much at any time */
159 if (foreground && GetForegroundWindow() &&
160 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
161 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
162 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
163 ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
164 }
165
166 /* same as above but without capture test */
167 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
168 static void check_active_state_(const char *file, int line,
169 HWND active, HWND foreground, HWND focus)
170 {
171 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
172 /* only check foreground if it belongs to the current thread */
173 /* foreground can be moved to a different app pretty much at any time */
174 if (foreground && GetForegroundWindow() &&
175 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
176 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
177 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
178 }
179
180 static BOOL ignore_message( UINT message )
181 {
182 /* these are always ignored */
183 return (message >= 0xc000 ||
184 message == WM_GETICON ||
185 message == WM_GETOBJECT ||
186 message == WM_TIMECHANGE ||
187 message == WM_DEVICECHANGE);
188 }
189
190 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
191 {
192 (*(LPINT)lParam)++;
193 trace("EnumChildProc on %p\n", hwndChild);
194 if (*(LPINT)lParam > 1) return FALSE;
195 return TRUE;
196 }
197
198 /* will search for the given window */
199 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam)
200 {
201 trace("EnumChildProc1 on %p\n", hwndChild);
202 if ((HWND)lParam == hwndChild) return FALSE;
203 return TRUE;
204 }
205
206 static HWND create_tool_window( LONG style, HWND parent )
207 {
208 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
209 0, 0, 100, 100, parent, 0, 0, NULL );
210 ok( ret != 0, "Creation failed\n" );
211 return ret;
212 }
213
214 /* test parent and owner values for various combinations */
215 static void test_parent_owner(void)
216 {
217 LONG style;
218 HWND test, owner, ret;
219 HWND desktop = GetDesktopWindow();
220 HWND child = create_tool_window( WS_CHILD, hwndMain );
221 INT numChildren;
222
223 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
224
225 /* child without parent, should fail */
226 SetLastError(0xdeadbeef);
227 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
228 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
229 ok( !test, "WS_CHILD without parent created\n" );
230 ok( GetLastError() == ERROR_TLW_WITH_WSCHILD ||
231 broken(GetLastError() == 0xdeadbeef), /* win9x */
232 "CreateWindowExA error %u\n", GetLastError() );
233
234 /* desktop window */
235 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
236 style = GetWindowLongA( desktop, GWL_STYLE );
237 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
238 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
239 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
240
241 /* normal child window */
242 test = create_tool_window( WS_CHILD, hwndMain );
243 trace( "created child %p\n", test );
244 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
245 SetWindowLongA( test, GWL_STYLE, 0 );
246 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
247 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
248 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
249 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
250 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
251 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
252 DestroyWindow( test );
253
254 /* normal child window with WS_MAXIMIZE */
255 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
256 DestroyWindow( test );
257
258 /* normal child window with WS_THICKFRAME */
259 test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
260 DestroyWindow( test );
261
262 /* popup window with WS_THICKFRAME */
263 test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
264 DestroyWindow( test );
265
266 /* child of desktop */
267 test = create_tool_window( WS_CHILD, desktop );
268 trace( "created child of desktop %p\n", test );
269 check_parents( test, desktop, 0, desktop, 0, test, desktop );
270 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
271 check_parents( test, desktop, 0, 0, 0, test, test );
272 SetWindowLongA( test, GWL_STYLE, 0 );
273 check_parents( test, desktop, 0, 0, 0, test, test );
274 DestroyWindow( test );
275
276 /* child of desktop with WS_MAXIMIZE */
277 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
278 DestroyWindow( test );
279
280 /* child of desktop with WS_MINIMIZE */
281 test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
282 DestroyWindow( test );
283
284 /* child of child */
285 test = create_tool_window( WS_CHILD, child );
286 trace( "created child of child %p\n", test );
287 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
288 SetWindowLongA( test, GWL_STYLE, 0 );
289 check_parents( test, child, child, 0, 0, hwndMain, test );
290 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
291 check_parents( test, child, child, 0, 0, hwndMain, test );
292 DestroyWindow( test );
293
294 /* child of child with WS_MAXIMIZE */
295 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
296 DestroyWindow( test );
297
298 /* child of child with WS_MINIMIZE */
299 test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
300 DestroyWindow( test );
301
302 /* not owned top-level window */
303 test = create_tool_window( 0, 0 );
304 trace( "created top-level %p\n", test );
305 check_parents( test, desktop, 0, 0, 0, test, test );
306 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
307 check_parents( test, desktop, 0, 0, 0, test, test );
308 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
309 check_parents( test, desktop, 0, desktop, 0, test, desktop );
310 DestroyWindow( test );
311
312 /* not owned top-level window with WS_MAXIMIZE */
313 test = create_tool_window( WS_MAXIMIZE, 0 );
314 DestroyWindow( test );
315
316 /* owned top-level window */
317 test = create_tool_window( 0, hwndMain );
318 trace( "created owned top-level %p\n", test );
319 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
320 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
321 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
322 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
323 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
324 DestroyWindow( test );
325
326 /* owned top-level window with WS_MAXIMIZE */
327 test = create_tool_window( WS_MAXIMIZE, hwndMain );
328 DestroyWindow( test );
329
330 /* not owned popup */
331 test = create_tool_window( WS_POPUP, 0 );
332 trace( "created popup %p\n", test );
333 check_parents( test, desktop, 0, 0, 0, test, test );
334 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
335 check_parents( test, desktop, 0, desktop, 0, test, desktop );
336 SetWindowLongA( test, GWL_STYLE, 0 );
337 check_parents( test, desktop, 0, 0, 0, test, test );
338 DestroyWindow( test );
339
340 /* not owned popup with WS_MAXIMIZE */
341 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
342 DestroyWindow( test );
343
344 /* owned popup */
345 test = create_tool_window( WS_POPUP, hwndMain );
346 trace( "created owned popup %p\n", test );
347 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
348 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
349 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
350 SetWindowLongA( test, GWL_STYLE, 0 );
351 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
352 DestroyWindow( test );
353
354 /* owned popup with WS_MAXIMIZE */
355 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
356 DestroyWindow( test );
357
358 /* top-level window owned by child (same as owned by top-level) */
359 test = create_tool_window( 0, child );
360 trace( "created top-level owned by child %p\n", test );
361 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
362 DestroyWindow( test );
363
364 /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
365 test = create_tool_window( WS_MAXIMIZE, child );
366 DestroyWindow( test );
367
368 /* popup owned by desktop (same as not owned) */
369 test = create_tool_window( WS_POPUP, desktop );
370 trace( "created popup owned by desktop %p\n", test );
371 check_parents( test, desktop, 0, 0, 0, test, test );
372 DestroyWindow( test );
373
374 /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
375 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
376 DestroyWindow( test );
377
378 /* popup owned by child (same as owned by top-level) */
379 test = create_tool_window( WS_POPUP, child );
380 trace( "created popup owned by child %p\n", test );
381 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
382 DestroyWindow( test );
383
384 /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
385 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
386 DestroyWindow( test );
387
388 /* not owned popup with WS_CHILD (same as WS_POPUP only) */
389 test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
390 trace( "created WS_CHILD popup %p\n", test );
391 check_parents( test, desktop, 0, 0, 0, test, test );
392 DestroyWindow( test );
393
394 /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
395 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
396 DestroyWindow( test );
397
398 /* owned popup with WS_CHILD (same as WS_POPUP only) */
399 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
400 trace( "created owned WS_CHILD popup %p\n", test );
401 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
402 DestroyWindow( test );
403
404 /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
405 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
406 DestroyWindow( test );
407
408 /******************** parent changes *************************/
409 trace( "testing parent changes\n" );
410
411 /* desktop window */
412 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
413 if (0)
414 {
415 /* this test succeeds on NT but crashes on win9x systems */
416 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
417 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
418 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
419 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
420 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
421 }
422 /* normal child window */
423 test = create_tool_window( WS_CHILD, hwndMain );
424 trace( "created child %p\n", test );
425
426 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
427 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
428 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
429
430 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
431 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
432 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
433
434 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
435 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
436 check_parents( test, desktop, 0, desktop, 0, test, desktop );
437
438 /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
439 if (!is_win9x)
440 {
441 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test );
442 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
443 check_parents( test, desktop, 0, desktop, 0, test, desktop );
444 }
445 else
446 win_skip("Test creates circular window tree under Win9x/WinMe\n" );
447
448 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
449 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
450 check_parents( test, desktop, child, desktop, child, test, desktop );
451
452 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
453 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
454 check_parents( test, desktop, 0, desktop, 0, test, desktop );
455 DestroyWindow( test );
456
457 /* not owned top-level window */
458 test = create_tool_window( 0, 0 );
459 trace( "created top-level %p\n", test );
460
461 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
462 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
463 check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
464
465 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
466 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
467 check_parents( test, desktop, child, 0, child, test, test );
468
469 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
470 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
471 check_parents( test, desktop, 0, 0, 0, test, test );
472 DestroyWindow( test );
473
474 /* not owned popup */
475 test = create_tool_window( WS_POPUP, 0 );
476 trace( "created popup %p\n", test );
477
478 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
479 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
480 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
481
482 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
483 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
484 check_parents( test, desktop, child, child, child, test, hwndMain );
485
486 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
487 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
488 check_parents( test, desktop, 0, 0, 0, test, test );
489 DestroyWindow( test );
490
491 /* normal child window */
492 test = create_tool_window( WS_CHILD, hwndMain );
493 trace( "created child %p\n", test );
494
495 ret = SetParent( test, desktop );
496 ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
497 check_parents( test, desktop, 0, desktop, 0, test, desktop );
498
499 ret = SetParent( test, child );
500 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
501 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
502
503 ret = SetParent( test, hwndMain2 );
504 ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
505 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
506 DestroyWindow( test );
507
508 /* not owned top-level window */
509 test = create_tool_window( 0, 0 );
510 trace( "created top-level %p\n", test );
511
512 ret = SetParent( test, child );
513 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
514 check_parents( test, child, child, 0, 0, hwndMain, test );
515
516 if (!is_win9x)
517 {
518 ShowWindow( test, SW_SHOW );
519 ret = SetParent( test, test );
520 ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL );
521 ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" );
522 check_parents( test, child, child, 0, 0, hwndMain, test );
523 }
524 else
525 win_skip( "Test crashes on Win9x/WinMe\n" );
526 DestroyWindow( test );
527
528 /* owned popup */
529 test = create_tool_window( WS_POPUP, hwndMain2 );
530 trace( "created owned popup %p\n", test );
531
532 ret = SetParent( test, child );
533 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
534 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
535
536 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
537 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
538 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
539 DestroyWindow( test );
540
541 /**************** test owner destruction *******************/
542
543 /* owned child popup */
544 owner = create_tool_window( 0, 0 );
545 test = create_tool_window( WS_POPUP, owner );
546 trace( "created owner %p and popup %p\n", owner, test );
547 ret = SetParent( test, child );
548 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
549 check_parents( test, child, child, owner, owner, hwndMain, owner );
550 /* window is now child of 'child' but owned by 'owner' */
551 DestroyWindow( owner );
552 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
553 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
554 * while Win95, Win2k, WinXP do.
555 */
556 /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
557 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
558 DestroyWindow(test);
559
560 /* owned top-level popup */
561 owner = create_tool_window( 0, 0 );
562 test = create_tool_window( WS_POPUP, owner );
563 trace( "created owner %p and popup %p\n", owner, test );
564 check_parents( test, desktop, owner, owner, owner, test, owner );
565 DestroyWindow( owner );
566 ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
567
568 /* top-level popup owned by child */
569 owner = create_tool_window( WS_CHILD, hwndMain2 );
570 test = create_tool_window( WS_POPUP, 0 );
571 trace( "created owner %p and popup %p\n", owner, test );
572 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
573 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
574 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
575 DestroyWindow( owner );
576 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
577 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
578 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
579 * while Win95, Win2k, WinXP do.
580 */
581 /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
582 DestroyWindow(test);
583
584 /* final cleanup */
585 DestroyWindow(child);
586
587
588 owner = create_tool_window( WS_OVERLAPPED, 0 );
589 test = create_tool_window( WS_POPUP, desktop );
590
591 ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
592 numChildren = 0;
593 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
594 "EnumChildWindows should have returned FALSE\n" );
595 ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
596
597 SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
598 ret = SetParent( test, owner );
599 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
600
601 numChildren = 0;
602 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
603 "EnumChildWindows should have returned TRUE\n" );
604 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
605
606 child = create_tool_window( WS_CHILD, owner );
607 numChildren = 0;
608 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
609 "EnumChildWindows should have returned FALSE\n" );
610 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
611 DestroyWindow( child );
612
613 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
614 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
615 numChildren = 0;
616 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
617 "EnumChildWindows should have returned TRUE\n" );
618 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
619
620 ret = SetParent( child, owner );
621 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
622 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
623 numChildren = 0;
624 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
625 "EnumChildWindows should have returned FALSE\n" );
626 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
627
628 ret = SetParent( child, NULL );
629 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
630 ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
631 numChildren = 0;
632 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
633 "EnumChildWindows should have returned TRUE\n" );
634 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
635
636 /* even GW_OWNER == owner it's still a desktop's child */
637 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
638 "EnumChildWindows should have found %p and returned FALSE\n", child );
639
640 DestroyWindow( child );
641 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
642
643 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
644 "EnumChildWindows should have found %p and returned FALSE\n", child );
645
646 DestroyWindow( child );
647 DestroyWindow( test );
648 DestroyWindow( owner );
649 }
650
651 static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam)
652 {
653 (*(LPINT)lParam)++;
654 if (*(LPINT)lParam > 2) return FALSE;
655 return TRUE;
656 }
657 static DWORD CALLBACK enum_thread( void *arg )
658 {
659 INT count;
660 HWND hwnd[3];
661 BOOL ret;
662 MSG msg;
663
664 if (pGetGUIThreadInfo)
665 {
666 GUITHREADINFO info;
667 info.cbSize = sizeof(info);
668 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
669 ok( ret || broken(!ret), /* win9x */
670 "GetGUIThreadInfo failed without message queue\n" );
671 SetLastError( 0xdeadbeef );
672 info.cbSize = sizeof(info) + 1;
673 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
674 ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" );
675 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
676 broken(GetLastError() == 0xdeadbeef), /* win9x */
677 "wrong error %u\n", GetLastError() );
678 }
679
680 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */
681
682 count = 0;
683 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
684 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
685 ok( count == 0, "count should be 0 got %d\n", count );
686
687 hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP,
688 0, 0, 100, 100, 0, 0, 0, NULL );
689 count = 0;
690 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
691 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
692 if (count != 2) /* Vista gives us two windows for the price of one */
693 {
694 ok( count == 1, "count should be 1 got %d\n", count );
695 hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP,
696 0, 0, 100, 100, 0, 0, 0, NULL );
697 }
698 else hwnd[2] = 0;
699
700 hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP,
701 0, 0, 100, 100, 0, 0, 0, NULL );
702 count = 0;
703 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
704 ok( !ret, "EnumThreadWindows should have returned FALSE\n" );
705 ok( count == 3, "count should be 3 got %d\n", count );
706
707 if (hwnd[2]) DestroyWindow(hwnd[2]);
708 DestroyWindow(hwnd[1]);
709 DestroyWindow(hwnd[0]);
710 return 0;
711 }
712
713 /* test EnumThreadWindows in a separate thread */
714 static void test_enum_thread_windows(void)
715 {
716 DWORD id;
717 HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id );
718 ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" );
719 CloseHandle( handle );
720 }
721
722 static struct wm_gettext_override_data
723 {
724 BOOL enabled; /* when 1 bypasses default procedure */
725 char *buff; /* expected text buffer pointer */
726 WCHAR *buffW; /* same, for W test */
727 } g_wm_gettext_override;
728
729 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
730 {
731 switch (msg)
732 {
733 case WM_GETMINMAXINFO:
734 {
735 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
736 break;
737 }
738 case WM_WINDOWPOSCHANGING:
739 {
740 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
741 if (!(winpos->flags & SWP_NOMOVE))
742 {
743 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
744 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
745 }
746 /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
747 if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
748 {
749 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
750 winpos->cx == 32768, /* win7 doesn't truncate */
751 "bad winpos->cx %d\n", winpos->cx);
752 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
753 winpos->cy == 40000, /* win7 doesn't truncate */
754 "bad winpos->cy %d\n", winpos->cy);
755 }
756 break;
757 }
758 case WM_WINDOWPOSCHANGED:
759 {
760 RECT rc1, rc2;
761 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
762 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
763 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
764
765 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
766 winpos->cx == 32768, /* win7 doesn't truncate */
767 "bad winpos->cx %d\n", winpos->cx);
768 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
769 winpos->cy == 40000, /* win7 doesn't truncate */
770 "bad winpos->cy %d\n", winpos->cy);
771
772 GetWindowRect(hwnd, &rc1);
773 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
774 /* note: winpos coordinates are relative to parent */
775 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
776 if (0)
777 {
778 /* Uncomment this once the test succeeds in all cases */
779 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
780 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
781
782 GetClientRect(hwnd, &rc2);
783 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
784 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
785 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
786 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
787 }
788 break;
789 }
790 case WM_NCCREATE:
791 {
792 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
793 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
794
795 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
796 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
797 else
798 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
799 break;
800 }
801 case WM_COMMAND:
802 if (test_lbuttondown_flag)
803 {
804 ShowWindow((HWND)wparam, SW_SHOW);
805 flush_events( FALSE );
806 }
807 break;
808 case WM_GETTEXT:
809 num_gettext_msgs++;
810 if (g_wm_gettext_override.enabled)
811 {
812 char *text = (char*)lparam;
813 ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text);
814 ok(*text == 0, "expected empty string buffer %x\n", *text);
815 return 0;
816 }
817 break;
818 case WM_SETTEXT:
819 num_settext_msgs++;
820 break;
821 case WM_ACTIVATEAPP:
822 if (wparam) app_activated = TRUE;
823 else app_deactivated = TRUE;
824 break;
825 }
826
827 return DefWindowProcA(hwnd, msg, wparam, lparam);
828 }
829
830 static LRESULT WINAPI main_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
831 {
832 switch (msg)
833 {
834 case WM_GETTEXT:
835 num_gettext_msgs++;
836 if (g_wm_gettext_override.enabled)
837 {
838 WCHAR *text = (WCHAR*)lparam;
839 ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text);
840 ok(*text == 0, "expected empty string buffer %x\n", *text);
841 return 0;
842 }
843 break;
844 }
845
846 return DefWindowProcA(hwnd, msg, wparam, lparam);
847 }
848
849 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
850 {
851 switch (msg)
852 {
853 case WM_GETMINMAXINFO:
854 {
855 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
856 break;
857 }
858 case WM_NCCREATE:
859 {
860 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
861 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
862
863 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
864 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
865 else
866 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
867 break;
868 }
869 }
870
871 return DefWindowProcA(hwnd, msg, wparam, lparam);
872 }
873
874 static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0};
875
876 static BOOL RegisterWindowClasses(void)
877 {
878 WNDCLASSW clsW;
879 WNDCLASSA cls;
880
881 cls.style = CS_DBLCLKS;
882 cls.lpfnWndProc = main_window_procA;
883 cls.cbClsExtra = 0;
884 cls.cbWndExtra = 0;
885 cls.hInstance = GetModuleHandleA(0);
886 cls.hIcon = 0;
887 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
888 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
889 cls.lpszMenuName = NULL;
890 cls.lpszClassName = "MainWindowClass";
891
892 if(!RegisterClassA(&cls)) return FALSE;
893
894 clsW.style = CS_DBLCLKS;
895 clsW.lpfnWndProc = main_window_procW;
896 clsW.cbClsExtra = 0;
897 clsW.cbWndExtra = 0;
898 clsW.hInstance = GetModuleHandleA(0);
899 clsW.hIcon = 0;
900 clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
901 clsW.hbrBackground = GetStockObject(WHITE_BRUSH);
902 clsW.lpszMenuName = NULL;
903 clsW.lpszClassName = mainclassW;
904
905 if(!RegisterClassW(&clsW)) return FALSE;
906
907 cls.style = 0;
908 cls.lpfnWndProc = tool_window_procA;
909 cls.cbClsExtra = 0;
910 cls.cbWndExtra = 0;
911 cls.hInstance = GetModuleHandleA(0);
912 cls.hIcon = 0;
913 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
914 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
915 cls.lpszMenuName = NULL;
916 cls.lpszClassName = "ToolWindowClass";
917
918 if(!RegisterClassA(&cls)) return FALSE;
919
920 return TRUE;
921 }
922
923 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info)
924 {
925 RECT rcWindow, rcClient;
926 DWORD status;
927
928 ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook);
929
930 GetWindowRect(hwnd, &rcWindow);
931 ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook);
932
933 GetClientRect(hwnd, &rcClient);
934 /* translate to screen coordinates */
935 MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
936 ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook);
937
938 ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
939 "wrong dwStyle: %08x != %08x for %p in hook %s\n",
940 info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook);
941 /* Windows reports some undocumented exstyles in WINDOWINFO, but
942 * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE).
943 */
944 ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
945 "wrong dwExStyle: %08x != %08x for %p in hook %s\n",
946 info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook);
947 status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
948 if (GetForegroundWindow())
949 ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n",
950 info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook);
951
952 /* win2k and XP return broken border info in GetWindowInfo most of
953 * the time, so there is no point in testing it.
954 */
955 if (0)
956 {
957 UINT border;
958 ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
959 "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
960 border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
961 ok(info->cyWindowBorders == border,
962 "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
963 }
964 ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n",
965 hwnd, hook);
966 ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
967 info->wCreatorVersion == 0x0500 /* Vista */,
968 "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
969 }
970
971 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
972 {
973 AdjustWindowRectEx(rc, style, menu, exstyle);
974 /* AdjustWindowRectEx does not include scroll bars */
975 if (style & WS_VSCROLL)
976 {
977 if(exstyle & WS_EX_LEFTSCROLLBAR)
978 rc->left -= GetSystemMetrics(SM_CXVSCROLL);
979 else
980 rc->right += GetSystemMetrics(SM_CXVSCROLL);
981 }
982 if (style & WS_HSCROLL)
983 rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
984 }
985
986 static void test_nonclient_area(HWND hwnd)
987 {
988 DWORD style, exstyle;
989 RECT rc_window, rc_client, rc;
990 BOOL menu;
991 LRESULT ret;
992
993 style = GetWindowLongA(hwnd, GWL_STYLE);
994 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
995 menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
996
997 GetWindowRect(hwnd, &rc_window);
998 GetClientRect(hwnd, &rc_client);
999
1000 /* avoid some cases when things go wrong */
1001 if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
1002 rc_window.right > 32768 || rc_window.bottom > 32768) return;
1003
1004 CopyRect(&rc, &rc_client);
1005 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
1006 FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
1007
1008 ok(EqualRect(&rc, &rc_window),
1009 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1010 style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
1011 rc.left, rc.top, rc.right, rc.bottom);
1012
1013
1014 CopyRect(&rc, &rc_window);
1015 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1016 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1017 ok(EqualRect(&rc, &rc_client),
1018 "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1019 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
1020 rc.left, rc.top, rc.right, rc.bottom);
1021
1022 /* NULL rectangle shouldn't crash */
1023 ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0);
1024 ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
1025
1026 /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
1027 if (is_win9x)
1028 return;
1029
1030 /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
1031 SetRect(&rc_client, 0, 0, 250, 150);
1032 CopyRect(&rc_window, &rc_client);
1033 MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
1034 FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
1035
1036 CopyRect(&rc, &rc_window);
1037 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
1038 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
1039 ok(EqualRect(&rc, &rc_client),
1040 "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
1041 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
1042 rc.left, rc.top, rc.right, rc.bottom);
1043 }
1044
1045 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
1046 {
1047 static const char *CBT_code_name[10] = {
1048 "HCBT_MOVESIZE",
1049 "HCBT_MINMAX",
1050 "HCBT_QS",
1051 "HCBT_CREATEWND",
1052 "HCBT_DESTROYWND",
1053 "HCBT_ACTIVATE",
1054 "HCBT_CLICKSKIPPED",
1055 "HCBT_KEYSKIPPED",
1056 "HCBT_SYSCOMMAND",
1057 "HCBT_SETFOCUS" };
1058 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
1059 HWND hwnd = (HWND)wParam;
1060
1061 switch (nCode)
1062 {
1063 case HCBT_CREATEWND:
1064 {
1065 static const RECT rc_null;
1066 RECT rc;
1067 LONG style;
1068 CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1069 ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1070
1071 if (pGetWindowInfo)
1072 {
1073 WINDOWINFO info;
1074 info.cbSize = sizeof(WINDOWINFO);
1075 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1076 verify_window_info(code_name, hwnd, &info);
1077 }
1078
1079 /* WS_VISIBLE should be turned off yet */
1080 style = createwnd->lpcs->style & ~WS_VISIBLE;
1081 ok(style == GetWindowLongA(hwnd, GWL_STYLE),
1082 "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1083 GetWindowLongA(hwnd, GWL_STYLE), style);
1084
1085 if (0)
1086 {
1087 /* Uncomment this once the test succeeds in all cases */
1088 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1089 {
1090 ok(GetParent(hwnd) == hwndMessage,
1091 "wrong result from GetParent %p: message window %p\n",
1092 GetParent(hwnd), hwndMessage);
1093 }
1094 else
1095 ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1096
1097 ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1098 }
1099 if (0)
1100 {
1101 /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1102 * Win9x still has them set to 0.
1103 */
1104 ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1105 ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1106 }
1107 ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1108 ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1109
1110 if (0)
1111 {
1112 /* Uncomment this once the test succeeds in all cases */
1113 if (pGetAncestor)
1114 {
1115 ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1116 ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1117 "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1118
1119 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1120 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1121 "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1122 else
1123 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1124 "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1125 }
1126
1127 ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1128 ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1129 ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1130 ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1131 }
1132 break;
1133 }
1134 case HCBT_MOVESIZE:
1135 case HCBT_MINMAX:
1136 case HCBT_ACTIVATE:
1137 if (pGetWindowInfo && IsWindow(hwnd))
1138 {
1139 WINDOWINFO info;
1140
1141 /* Win98 actually does check the info.cbSize and doesn't allow
1142 * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1143 * WinXP do not check it at all.
1144 */
1145 info.cbSize = sizeof(WINDOWINFO);
1146 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1147 verify_window_info(code_name, hwnd, &info);
1148 }
1149 break;
1150 /* window state is undefined */
1151 case HCBT_SETFOCUS:
1152 case HCBT_DESTROYWND:
1153 break;
1154 default:
1155 break;
1156 }
1157
1158 return CallNextHookEx(hhook, nCode, wParam, lParam);
1159 }
1160
1161 static void test_shell_window(void)
1162 {
1163 BOOL ret;
1164 DWORD error;
1165 HMODULE hinst, hUser32;
1166 BOOL (WINAPI*SetShellWindow)(HWND);
1167 HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1168 HWND shellWindow, nextWnd;
1169
1170 if (is_win9x)
1171 {
1172 win_skip("Skipping shell window test on Win9x\n");
1173 return;
1174 }
1175
1176 shellWindow = GetShellWindow();
1177 hinst = GetModuleHandleA(NULL);
1178 hUser32 = GetModuleHandleA("user32");
1179
1180 SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1181
1182 trace("previous shell window: %p\n", shellWindow);
1183
1184 if (shellWindow) {
1185 DWORD pid;
1186 HANDLE hProcess;
1187
1188 GetWindowThreadProcessId(shellWindow, &pid);
1189 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
1190 if (!hProcess)
1191 {
1192 skip( "cannot get access to shell process\n" );
1193 return;
1194 }
1195
1196 SetLastError(0xdeadbeef);
1197 ret = DestroyWindow(shellWindow);
1198 error = GetLastError();
1199
1200 ok(!ret, "DestroyWindow(shellWindow)\n");
1201 /* passes on Win XP, but not on Win98 */
1202 ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1203 "got %u after DestroyWindow(shellWindow)\n", error);
1204
1205 /* close old shell instance */
1206 ret = TerminateProcess(hProcess, 0);
1207 ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1208 WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
1209 CloseHandle(hProcess);
1210 }
1211
1212 hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1213 trace("created window 1: %p\n", hwnd1);
1214
1215 ret = SetShellWindow(hwnd1);
1216 ok(ret, "first call to SetShellWindow(hwnd1)\n");
1217 shellWindow = GetShellWindow();
1218 ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1219
1220 ret = SetShellWindow(hwnd1);
1221 ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1222
1223 ret = SetShellWindow(0);
1224 error = GetLastError();
1225 /* passes on Win XP, but not on Win98
1226 ok(!ret, "reset shell window by SetShellWindow(0)\n");
1227 ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1228
1229 ret = SetShellWindow(hwnd1);
1230 /* passes on Win XP, but not on Win98
1231 ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1232
1233 SetWindowLongA(hwnd1, GWL_EXSTYLE, GetWindowLongA(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
1234 ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0;
1235 ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1236
1237 ret = DestroyWindow(hwnd1);
1238 ok(ret, "DestroyWindow(hwnd1)\n");
1239
1240 hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1241 trace("created window 2: %p\n", hwnd2);
1242 ret = SetShellWindow(hwnd2);
1243 ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1244
1245 hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1246 trace("created window 3: %p\n", hwnd3);
1247
1248 hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1249 trace("created window 4: %p\n", hwnd4);
1250
1251 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1252 ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1253
1254 ret = SetShellWindow(hwnd4);
1255 ok(ret, "SetShellWindow(hwnd4)\n");
1256 shellWindow = GetShellWindow();
1257 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1258
1259 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1260 ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1261
1262 ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1263 ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1264
1265 ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1266 ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1267
1268 ret = SetShellWindow(hwnd3);
1269 ok(!ret, "SetShellWindow(hwnd3)\n");
1270 shellWindow = GetShellWindow();
1271 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1272
1273 hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1274 trace("created window 5: %p\n", hwnd5);
1275 ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1276 ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1277
1278 todo_wine
1279 {
1280 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1281 ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1282 }
1283
1284 /* destroy test windows */
1285 DestroyWindow(hwnd2);
1286 DestroyWindow(hwnd3);
1287 DestroyWindow(hwnd4);
1288 DestroyWindow(hwnd5);
1289 }
1290
1291 /************** MDI test ****************/
1292
1293 static char mdi_lParam_test_message[] = "just a test string";
1294
1295 static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id)
1296 {
1297 MDICREATESTRUCTA mdi_cs;
1298 HWND mdi_child, hwnd, exp_hwnd;
1299 INT_PTR id;
1300 static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1301 static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1302 BOOL isWin9x = FALSE;
1303
1304 mdi_cs.szClass = "MDI_child_Class_1";
1305 mdi_cs.szTitle = "MDI child";
1306 mdi_cs.hOwner = GetModuleHandleA(NULL);
1307 mdi_cs.x = CW_USEDEFAULT;
1308 mdi_cs.y = CW_USEDEFAULT;
1309 mdi_cs.cx = CW_USEDEFAULT;
1310 mdi_cs.cy = CW_USEDEFAULT;
1311 mdi_cs.style = 0;
1312 mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
1313 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1314 ok(mdi_child != 0, "MDI child creation failed\n");
1315 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1316 ok(id == first_id, "wrong child id %ld\n", id);
1317 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1318 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1319 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1320 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1321 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1322
1323 mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1324 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1325 ok(mdi_child != 0, "MDI child creation failed\n");
1326 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1327 ok(id == first_id, "wrong child id %ld\n", id);
1328 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1329 todo_wine
1330 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1331 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1332 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1333
1334 mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1335 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1336 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1337 {
1338 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1339 }
1340 else
1341 {
1342 ok(mdi_child != 0, "MDI child creation failed\n");
1343 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1344 ok(id == first_id, "wrong child id %ld\n", id);
1345 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1346 todo_wine
1347 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1348 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1349 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1350 }
1351
1352 /* test MDICREATESTRUCT A<->W mapping */
1353 /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1354 mdi_cs.style = 0;
1355 mdi_cs.szClass = (LPCSTR)classW;
1356 mdi_cs.szTitle = (LPCSTR)titleW;
1357 SetLastError(0xdeadbeef);
1358 mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1359 if (!mdi_child)
1360 {
1361 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1362 isWin9x = TRUE;
1363 else
1364 ok(mdi_child != 0, "MDI child creation failed\n");
1365 }
1366 else
1367 {
1368 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1369 ok(id == first_id, "wrong child id %ld\n", id);
1370 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1371 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1372 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1373 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1374 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1375 }
1376
1377 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1378 0,
1379 CW_USEDEFAULT, CW_USEDEFAULT,
1380 CW_USEDEFAULT, CW_USEDEFAULT,
1381 mdi_client, GetModuleHandleA(NULL),
1382 (LPARAM)mdi_lParam_test_message);
1383 ok(mdi_child != 0, "MDI child creation failed\n");
1384 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1385 ok(id == first_id, "wrong child id %ld\n", id);
1386 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1387 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1388 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1389 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1390 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1391
1392 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1393 0x7fffffff, /* without WS_POPUP */
1394 CW_USEDEFAULT, CW_USEDEFAULT,
1395 CW_USEDEFAULT, CW_USEDEFAULT,
1396 mdi_client, GetModuleHandleA(NULL),
1397 (LPARAM)mdi_lParam_test_message);
1398 ok(mdi_child != 0, "MDI child creation failed\n");
1399 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1400 ok(id == first_id, "wrong child id %ld\n", id);
1401 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1402 todo_wine
1403 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1404 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1405 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1406
1407 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1408 0xffffffff, /* with WS_POPUP */
1409 CW_USEDEFAULT, CW_USEDEFAULT,
1410 CW_USEDEFAULT, CW_USEDEFAULT,
1411 mdi_client, GetModuleHandleA(NULL),
1412 (LPARAM)mdi_lParam_test_message);
1413 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1414 {
1415 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1416 }
1417 else
1418 {
1419 ok(mdi_child != 0, "MDI child creation failed\n");
1420 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1421 ok(id == first_id, "wrong child id %ld\n", id);
1422 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1423 todo_wine
1424 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1425 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1426 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1427 }
1428
1429 /* test MDICREATESTRUCT A<->W mapping */
1430 SetLastError(0xdeadbeef);
1431 mdi_child = CreateMDIWindowW(classW, titleW,
1432 0,
1433 CW_USEDEFAULT, CW_USEDEFAULT,
1434 CW_USEDEFAULT, CW_USEDEFAULT,
1435 mdi_client, GetModuleHandleA(NULL),
1436 (LPARAM)mdi_lParam_test_message);
1437 if (!mdi_child)
1438 {
1439 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1440 isWin9x = TRUE;
1441 else
1442 ok(mdi_child != 0, "MDI child creation failed\n");
1443 }
1444 else
1445 {
1446 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1447 ok(id == first_id, "wrong child id %ld\n", id);
1448 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1449 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1450 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1451 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1452 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1453 }
1454
1455 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1456 0,
1457 CW_USEDEFAULT, CW_USEDEFAULT,
1458 CW_USEDEFAULT, CW_USEDEFAULT,
1459 mdi_client, 0, GetModuleHandleA(NULL),
1460 mdi_lParam_test_message);
1461 ok(mdi_child != 0, "MDI child creation failed\n");
1462 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1463 ok(id == first_id, "wrong child id %ld\n", id);
1464 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1465 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1466 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1467 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1468 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1469
1470 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1471 0x7fffffff, /* without WS_POPUP */
1472 CW_USEDEFAULT, CW_USEDEFAULT,
1473 CW_USEDEFAULT, CW_USEDEFAULT,
1474 mdi_client, 0, GetModuleHandleA(NULL),
1475 mdi_lParam_test_message);
1476 ok(mdi_child != 0, "MDI child creation failed\n");
1477 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1478 ok(id == first_id, "wrong child id %ld\n", id);
1479 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1480 todo_wine
1481 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1482 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1483 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1484
1485 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1486 0xffffffff, /* with WS_POPUP */
1487 CW_USEDEFAULT, CW_USEDEFAULT,
1488 CW_USEDEFAULT, CW_USEDEFAULT,
1489 mdi_client, 0, GetModuleHandleA(NULL),
1490 mdi_lParam_test_message);
1491 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1492 {
1493 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1494 }
1495 else
1496 {
1497 ok(mdi_child != 0, "MDI child creation failed\n");
1498 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1499 ok(id == first_id, "wrong child id %ld\n", id);
1500 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1501 todo_wine
1502 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1503 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1504 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1505 }
1506
1507 /* test MDICREATESTRUCT A<->W mapping */
1508 SetLastError(0xdeadbeef);
1509 mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
1510 0,
1511 CW_USEDEFAULT, CW_USEDEFAULT,
1512 CW_USEDEFAULT, CW_USEDEFAULT,
1513 mdi_client, 0, GetModuleHandleA(NULL),
1514 mdi_lParam_test_message);
1515 if (!mdi_child)
1516 {
1517 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1518 isWin9x = TRUE;
1519 else
1520 ok(mdi_child != 0, "MDI child creation failed\n");
1521 }
1522 else
1523 {
1524 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1525 ok(id == first_id, "wrong child id %ld\n", id);
1526 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1527 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0;
1528 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd);
1529 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1530 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1531 }
1532
1533 /* This test fails on Win9x */
1534 if (!isWin9x)
1535 {
1536 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1537 WS_CHILD,
1538 CW_USEDEFAULT, CW_USEDEFAULT,
1539 CW_USEDEFAULT, CW_USEDEFAULT,
1540 parent, 0, GetModuleHandleA(NULL),
1541 mdi_lParam_test_message);
1542 ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1543 }
1544
1545 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1546 WS_CHILD, /* without WS_POPUP */
1547 CW_USEDEFAULT, CW_USEDEFAULT,
1548 CW_USEDEFAULT, CW_USEDEFAULT,
1549 mdi_client, 0, GetModuleHandleA(NULL),
1550 mdi_lParam_test_message);
1551 ok(mdi_child != 0, "MDI child creation failed\n");
1552 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1553 ok(id == 0, "wrong child id %ld\n", id);
1554 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1555 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1556 DestroyWindow(mdi_child);
1557
1558 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1559 WS_CHILD | WS_POPUP, /* with WS_POPUP */
1560 CW_USEDEFAULT, CW_USEDEFAULT,
1561 CW_USEDEFAULT, CW_USEDEFAULT,
1562 mdi_client, 0, GetModuleHandleA(NULL),
1563 mdi_lParam_test_message);
1564 ok(mdi_child != 0, "MDI child creation failed\n");
1565 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1566 ok(id == 0, "wrong child id %ld\n", id);
1567 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1568 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1569 DestroyWindow(mdi_child);
1570
1571 /* maximized child */
1572 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1573 WS_CHILD | WS_MAXIMIZE,
1574 CW_USEDEFAULT, CW_USEDEFAULT,
1575 CW_USEDEFAULT, CW_USEDEFAULT,
1576 mdi_client, 0, GetModuleHandleA(NULL),
1577 mdi_lParam_test_message);
1578 ok(mdi_child != 0, "MDI child creation failed\n");
1579 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1580 ok(id == 0, "wrong child id %ld\n", id);
1581 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1582 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1583 DestroyWindow(mdi_child);
1584
1585 trace("Creating maximized child with a caption\n");
1586 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1587 WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
1588 CW_USEDEFAULT, CW_USEDEFAULT,
1589 CW_USEDEFAULT, CW_USEDEFAULT,
1590 mdi_client, 0, GetModuleHandleA(NULL),
1591 mdi_lParam_test_message);
1592 ok(mdi_child != 0, "MDI child creation failed\n");
1593 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1594 ok(id == 0, "wrong child id %ld\n", id);
1595 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1596 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1597 DestroyWindow(mdi_child);
1598
1599 trace("Creating maximized child with a caption and a thick frame\n");
1600 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1601 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
1602 CW_USEDEFAULT, CW_USEDEFAULT,
1603 CW_USEDEFAULT, CW_USEDEFAULT,
1604 mdi_client, 0, GetModuleHandleA(NULL),
1605 mdi_lParam_test_message);
1606 ok(mdi_child != 0, "MDI child creation failed\n");
1607 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1608 ok(id == 0, "wrong child id %ld\n", id);
1609 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1610 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd);
1611 DestroyWindow(mdi_child);
1612 }
1613
1614 static void test_MDI_child_stack(HWND mdi_client)
1615 {
1616 HWND child_1, child_2, child_3, child_4;
1617 HWND stack[4];
1618 MDICREATESTRUCTA cs;
1619
1620 cs.szClass = "MDI_child_Class_1";
1621 cs.szTitle = "MDI child";
1622 cs.hOwner = GetModuleHandleA(0);
1623 cs.x = CW_USEDEFAULT;
1624 cs.y = CW_USEDEFAULT;
1625 cs.cx = CW_USEDEFAULT;
1626 cs.cy = CW_USEDEFAULT;
1627 cs.style = 0;
1628 cs.lParam = (LPARAM)mdi_lParam_test_message;
1629
1630 child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1631 ok(child_1 != 0, "expected child_1 to be non NULL\n");
1632 child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1633 ok(child_2 != 0, "expected child_2 to be non NULL\n");
1634 child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1635 ok(child_3 != 0, "expected child_3 to be non NULL\n");
1636 child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs);
1637 ok(child_4 != 0, "expected child_4 to be non NULL\n");
1638
1639 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1640 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1641 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1642 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1643 trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]);
1644 ok(stack[0] == child_4 && stack[1] == child_3 &&
1645 stack[2] == child_2 && stack[3] == child_1,
1646 "Unexpected initial order, should be: %p->%p->%p->%p\n",
1647 child_4, child_3, child_2, child_1);
1648
1649 trace("Activate child next to %p\n", child_3);
1650 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0);
1651
1652 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1653 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1654 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1655 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1656 ok(stack[0] == child_2 && stack[1] == child_4 &&
1657 stack[2] == child_1 && stack[3] == child_3,
1658 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1659 child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1660
1661 trace("Activate child previous to %p\n", child_1);
1662 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1);
1663
1664 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0);
1665 stack[1] = GetWindow(stack[0], GW_HWNDNEXT);
1666 stack[2] = GetWindow(stack[1], GW_HWNDNEXT);
1667 stack[3] = GetWindow(stack[2], GW_HWNDNEXT);
1668 ok(stack[0] == child_4 && stack[1] == child_2 &&
1669 stack[2] == child_1 && stack[3] == child_3,
1670 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n",
1671 child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]);
1672
1673 DestroyWindow(child_1);
1674 DestroyWindow(child_2);
1675 DestroyWindow(child_3);
1676 DestroyWindow(child_4);
1677 }
1678
1679 /**********************************************************************
1680 * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1681 *
1682 * Note: The rule here is that client rect of the maximized MDI child
1683 * is equal to the client rect of the MDI client window.
1684 */
1685 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
1686 {
1687 RECT rect;
1688
1689 GetClientRect( client, &rect );
1690 AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
1691 0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
1692
1693 rect.right -= rect.left;
1694 rect.bottom -= rect.top;
1695 lpMinMax->ptMaxSize.x = rect.right;
1696 lpMinMax->ptMaxSize.y = rect.bottom;
1697
1698 lpMinMax->ptMaxPosition.x = rect.left;
1699 lpMinMax->ptMaxPosition.y = rect.top;
1700
1701 trace("max rect (%d,%d - %d, %d)\n",
1702 rect.left, rect.top, rect.right, rect.bottom);
1703 }
1704
1705 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1706 {
1707 switch (msg)
1708 {
1709 case WM_NCCREATE:
1710 case WM_CREATE:
1711 {
1712 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1713 MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1714
1715 ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1716 ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1717
1718 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1719 ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1720 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1721 ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1722 ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1723
1724 /* MDICREATESTRUCT should have original values */
1725 ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
1726 "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1727 ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1728 ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1729 ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1730 ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1731
1732 /* CREATESTRUCT should have fixed values */
1733 ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1734 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1735
1736 /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1737 ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1738 ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1739
1740 ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1741
1742 if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1743 {
1744 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1745 ok(cs->style == style,
1746 "cs->style does not match (%08x)\n", cs->style);
1747 }
1748 else
1749 {
1750 LONG style = mdi_cs->style;
1751 style &= ~WS_POPUP;
1752 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1753 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1754 ok(cs->style == style,
1755 "cs->style does not match (%08x)\n", cs->style);
1756 }
1757 break;
1758 }
1759
1760 case WM_GETMINMAXINFO:
1761 {
1762 HWND client = GetParent(hwnd);
1763 RECT rc;
1764 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1765 MINMAXINFO my_minmax;
1766 LONG style, exstyle;
1767
1768 style = GetWindowLongA(hwnd, GWL_STYLE);
1769 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1770
1771 GetClientRect(client, &rc);
1772
1773 GetClientRect(client, &rc);
1774 if ((style & WS_CAPTION) == WS_CAPTION)
1775 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1776 AdjustWindowRectEx(&rc, style, 0, exstyle);
1777 trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1778 dump_minmax_info( minmax );
1779
1780 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1781 minmax->ptMaxSize.x, rc.right - rc.left);
1782 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1783 minmax->ptMaxSize.y, rc.bottom - rc.top);
1784
1785 DefMDIChildProcA(hwnd, msg, wparam, lparam);
1786
1787 trace("DefMDIChildProc returned:\n");
1788 dump_minmax_info( minmax );
1789
1790 MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1791 ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1792 minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1793 ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1794 minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1795
1796 return 1;
1797 }
1798
1799 case WM_MDIACTIVATE:
1800 {
1801 HWND active, client = GetParent(hwnd);
1802 /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1803 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1804 if (hwnd == (HWND)lparam) /* if we are being activated */
1805 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1806 else
1807 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1808 break;
1809 }
1810 }
1811 return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1812 }
1813
1814 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1815 {
1816 switch (msg)
1817 {
1818 case WM_NCCREATE:
1819 case WM_CREATE:
1820 {
1821 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1822
1823 trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1824 cs->x, cs->y, cs->cx, cs->cy);
1825
1826 ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1827 ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1828
1829 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1830 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1831
1832 /* CREATESTRUCT should have fixed values */
1833 /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1834 while NT does. */
1835 /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1836 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1837
1838 /* cx/cy == CW_USEDEFAULT are translated to 0 */
1839 /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1840 while Win95, Win2k, WinXP do. */
1841 /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1842 ok(cs->cy == 0, "%d != 0\n", cs->cy);
1843 break;
1844 }
1845
1846 case WM_GETMINMAXINFO:
1847 {
1848 HWND parent = GetParent(hwnd);
1849 RECT rc;
1850 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1851 LONG style, exstyle;
1852
1853 style = GetWindowLongA(hwnd, GWL_STYLE);
1854 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1855
1856 GetClientRect(parent, &rc);
1857 trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1858
1859 GetClientRect(parent, &rc);
1860 if ((style & WS_CAPTION) == WS_CAPTION)
1861 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1862 AdjustWindowRectEx(&rc, style, 0, exstyle);
1863 dump_minmax_info( minmax );
1864
1865 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1866 minmax->ptMaxSize.x, rc.right - rc.left);
1867 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1868 minmax->ptMaxSize.y, rc.bottom - rc.top);
1869 break;
1870 }
1871
1872 case WM_WINDOWPOSCHANGED:
1873 {
1874 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1875 RECT rc1, rc2;
1876
1877 GetWindowRect(hwnd, &rc1);
1878 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1879 /* note: winpos coordinates are relative to parent */
1880 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1881 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) pos=(%d,%d)-(%d,%d)\n",
1882 rc1.left, rc1.top, rc1.right, rc1.bottom,
1883 rc2.left, rc2.top, rc2.right, rc2.bottom);
1884 GetWindowRect(hwnd, &rc1);
1885 GetClientRect(hwnd, &rc2);
1886 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1887 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1888 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n",
1889 rc1.left, rc1.top, rc1.right, rc1.bottom,
1890 rc2.left, rc2.top, rc2.right, rc2.bottom);
1891 }
1892 /* fall through */
1893 case WM_WINDOWPOSCHANGING:
1894 {
1895 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1896 WINDOWPOS my_winpos = *winpos;
1897
1898 trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1899 (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
1900 winpos->hwnd, winpos->hwndInsertAfter,
1901 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1902
1903 DefWindowProcA(hwnd, msg, wparam, lparam);
1904
1905 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1906 "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1907 winpos->hwnd, winpos->hwndInsertAfter,
1908 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1909
1910 return 1;
1911 }
1912 }
1913 return DefWindowProcA(hwnd, msg, wparam, lparam);
1914 }
1915
1916 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1917 {
1918 static HWND mdi_client;
1919
1920 switch (msg)
1921 {
1922 case WM_CREATE:
1923 return 1;
1924
1925 case WM_WINDOWPOSCHANGED:
1926 {
1927 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1928 RECT rc1, rc2;
1929
1930 GetWindowRect(hwnd, &rc1);
1931 trace("window: (%d,%d)-(%d,%d)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
1932 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1933 /* note: winpos coordinates are relative to parent */
1934 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1935 trace("pos: (%d,%d)-(%d,%d)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
1936 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1937
1938 GetWindowRect(hwnd, &rc1);
1939 GetClientRect(hwnd, &rc2);
1940 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1941 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1942 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1943 }
1944 /* fall through */
1945 case WM_WINDOWPOSCHANGING:
1946 {
1947 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1948 WINDOWPOS my_winpos = *winpos;
1949
1950 trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1951 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1952 winpos->hwnd, winpos->hwndInsertAfter,
1953 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1954
1955 DefWindowProcA(hwnd, msg, wparam, lparam);
1956
1957 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1958 winpos->hwnd, winpos->hwndInsertAfter,
1959 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1960
1961 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1962 "DefWindowProc should not change WINDOWPOS values\n");
1963
1964 return 1;
1965 }
1966
1967 case WM_CLOSE:
1968 PostQuitMessage(0);
1969 break;
1970 }
1971 return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
1972 }
1973
1974 static BOOL mdi_RegisterWindowClasses(void)
1975 {
1976 WNDCLASSA cls;
1977
1978 cls.style = 0;
1979 cls.lpfnWndProc = mdi_main_wnd_procA;
1980 cls.cbClsExtra = 0;
1981 cls.cbWndExtra = 0;
1982 cls.hInstance = GetModuleHandleA(0);
1983 cls.hIcon = 0;
1984 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
1985 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1986 cls.lpszMenuName = NULL;
1987 cls.lpszClassName = "MDI_parent_Class";
1988 if(!RegisterClassA(&cls)) return FALSE;
1989
1990 cls.lpfnWndProc = mdi_child_wnd_proc_1;
1991 cls.lpszClassName = "MDI_child_Class_1";
1992 if(!RegisterClassA(&cls)) return FALSE;
1993
1994 cls.lpfnWndProc = mdi_child_wnd_proc_2;
1995 cls.lpszClassName = "MDI_child_Class_2";
1996 if(!RegisterClassA(&cls)) return FALSE;
1997
1998 return TRUE;
1999 }
2000
2001 static void test_mdi(void)
2002 {
2003 HWND mdi_hwndMain, mdi_client;
2004 CLIENTCREATESTRUCT client_cs;
2005 RECT rc;
2006 /*MSG msg;*/
2007
2008 if (!mdi_RegisterWindowClasses()) assert(0);
2009
2010 mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
2011 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
2012 WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
2013 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
2014 GetDesktopWindow(), 0,
2015 GetModuleHandleA(NULL), NULL);
2016 assert(mdi_hwndMain);
2017
2018 GetClientRect(mdi_hwndMain, &rc);
2019
2020 client_cs.hWindowMenu = 0;
2021 client_cs.idFirstChild = 1;
2022
2023 /* MDIClient without MDIS_ALLCHILDSTYLES */
2024 mdi_client = CreateWindowExA(0, "mdiclient",
2025 NULL,
2026 WS_CHILD /*| WS_VISIBLE*/,
2027 /* tests depend on a not zero MDIClient size */
2028 0, 0, rc.right, rc.bottom,
2029 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2030 &client_cs);
2031 assert(mdi_client);
2032 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2033 DestroyWindow(mdi_client);
2034
2035 /* MDIClient with MDIS_ALLCHILDSTYLES */
2036 mdi_client = CreateWindowExA(0, "mdiclient",
2037 NULL,
2038 WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
2039 /* tests depend on a not zero MDIClient size */
2040 0, 0, rc.right, rc.bottom,
2041 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2042 &client_cs);
2043 assert(mdi_client);
2044 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild);
2045 DestroyWindow(mdi_client);
2046
2047 /* Test child window stack management */
2048 mdi_client = CreateWindowExA(0, "mdiclient",
2049 NULL,
2050 WS_CHILD,
2051 0, 0, rc.right, rc.bottom,
2052 mdi_hwndMain, 0, GetModuleHandleA(NULL),
2053 &client_cs);
2054 assert(mdi_client);
2055 test_MDI_child_stack(mdi_client);
2056 DestroyWindow(mdi_client);
2057 /*
2058 while(GetMessage(&msg, 0, 0, 0))
2059 {
2060 TranslateMessage(&msg);
2061 DispatchMessage(&msg);
2062 }
2063 */
2064 DestroyWindow(mdi_hwndMain);
2065 }
2066
2067 static void test_icons(void)
2068 {
2069 WNDCLASSEXA cls;
2070 HWND hwnd;
2071 HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION);
2072 HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
2073 HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
2074 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
2075 HICON res;
2076
2077 cls.cbSize = sizeof(cls);
2078 cls.style = 0;
2079 cls.lpfnWndProc = DefWindowProcA;
2080 cls.cbClsExtra = 0;
2081 cls.cbWndExtra = 0;
2082 cls.hInstance = 0;
2083 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND);
2084 cls.hIconSm = small_icon;
2085 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW);
2086 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
2087 cls.lpszMenuName = NULL;
2088 cls.lpszClassName = "IconWindowClass";
2089
2090 RegisterClassExA(&cls);
2091
2092 hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
2093 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
2094 assert( hwnd );
2095
2096 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2097 ok( res == 0, "wrong big icon %p/0\n", res );
2098 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
2099 ok( res == 0, "wrong previous big icon %p/0\n", res );
2100 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2101 ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
2102 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
2103 ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
2104 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2105 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2106
2107 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2108 ok( res == 0, "wrong small icon %p/0\n", res );
2109 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2110 ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
2111 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
2112 ok( res == 0, "wrong previous small icon %p/0\n", res );
2113 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2114 ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
2115 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2116 ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
2117 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
2118 ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
2119 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
2120 ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
2121 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
2122 ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
2123
2124 /* make sure the big icon hasn't changed */
2125 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
2126 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
2127
2128 DestroyWindow( hwnd );
2129 }
2130
2131 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2132 {
2133 if (msg == WM_NCCALCSIZE)
2134 {
2135 RECT *rect = (RECT *)lparam;
2136 /* first time around increase the rectangle, next time decrease it */
2137 if (rect->left == 100) InflateRect( rect, 10, 10 );
2138 else InflateRect( rect, -10, -10 );
2139 return 0;
2140 }
2141 return DefWindowProcA( hwnd, msg, wparam, lparam );
2142 }
2143
2144 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
2145 {
2146 RECT orig_win_rc, rect;
2147 LONG_PTR old_proc;
2148 HWND hwnd_grandchild, hwnd_child, hwnd_child2;
2149 HWND hwnd_desktop;
2150 RECT rc1, rc2;
2151 BOOL ret;
2152
2153 SetRect(&rect, 111, 222, 333, 444);
2154 ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
2155 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2156 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2157
2158 SetRect(&rect, 111, 222, 333, 444);
2159 ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
2160 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
2161 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2162
2163 GetWindowRect(hwnd, &orig_win_rc);
2164
2165 old_proc = SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
2166 ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2167 ok(ret, "Got %d\n", ret);
2168 GetWindowRect( hwnd, &rect );
2169 ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
2170 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2171 GetClientRect( hwnd, &rect );
2172 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2173 ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2174 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2175
2176 ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2177 ok(ret, "Got %d\n", ret);
2178 GetWindowRect( hwnd, &rect );
2179 ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2180 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2181 GetClientRect( hwnd, &rect );
2182 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2183 ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2184 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2185
2186 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2187 orig_win_rc.right, orig_win_rc.bottom, 0);
2188 ok(ret, "Got %d\n", ret);
2189 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, old_proc );
2190
2191 /* Win9x truncates coordinates to 16-bit irrespectively */
2192 if (!is_win9x)
2193 {
2194 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2195 ok(ret, "Got %d\n", ret);
2196 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2197 ok(ret, "Got %d\n", ret);
2198
2199 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2200 ok(ret, "Got %d\n", ret);
2201 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2202 ok(ret, "Got %d\n", ret);
2203 }
2204
2205 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2206 orig_win_rc.right, orig_win_rc.bottom, 0);
2207 ok(ret, "Got %d\n", ret);
2208
2209 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2210 ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2211 ok(ret, "Got %d\n", ret);
2212 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2213 ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2214 ok(ret, "Got %d\n", ret);
2215 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2216 ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2217 ok(ret, "Got %d\n", ret);
2218 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2219
2220 hwnd_desktop = GetDesktopWindow();
2221 ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2222 hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2223 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2224 hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2225 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2226 hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2227 ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2228
2229 ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2230 ok(ret, "Got %d\n", ret);
2231 check_active_state(hwnd, hwnd, hwnd);
2232
2233 ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2234 ok(ret, "Got %d\n", ret);
2235 check_active_state(hwnd2, hwnd2, hwnd2);
2236
2237 /* Returns TRUE also for windows that are not siblings */
2238 ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2239 ok(ret, "Got %d\n", ret);
2240 check_active_state(hwnd2, hwnd2, hwnd2);
2241
2242 ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2243 ok(ret, "Got %d\n", ret);
2244 check_active_state(hwnd2, hwnd2, hwnd2);
2245
2246 /* Does not seem to do anything even without passing flags, still returns TRUE */
2247 GetWindowRect(hwnd_child, &rc1);
2248 ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2249 ok(ret, "Got %d\n", ret);
2250 GetWindowRect(hwnd_child, &rc2);
2251 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2252 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2253 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2254 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2255 check_active_state(hwnd2, hwnd2, hwnd2);
2256
2257 /* Same thing the other way around. */
2258 GetWindowRect(hwnd2, &rc1);
2259 ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2260 ok(ret, "Got %d\n", ret);
2261 GetWindowRect(hwnd2, &rc2);
2262 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2263 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2264 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2265 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2266 check_active_state(hwnd2, hwnd2, hwnd2);
2267
2268 /* .. and with these windows. */
2269 GetWindowRect(hwnd_grandchild, &rc1);
2270 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2271 ok(ret, "Got %d\n", ret);
2272 GetWindowRect(hwnd_grandchild, &rc2);
2273 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2274 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2275 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2276 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2277 check_active_state(hwnd2, hwnd2, hwnd2);
2278
2279 /* Add SWP_NOZORDER and it will be properly resized. */
2280 GetWindowRect(hwnd_grandchild, &rc1);
2281 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2282 ok(ret, "Got %d\n", ret);
2283 GetWindowRect(hwnd_grandchild, &rc2);
2284 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2285 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2286 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2287 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2288 check_active_state(hwnd2, hwnd2, hwnd2);
2289
2290 /* Given a sibling window, the window is properly resized. */
2291 GetWindowRect(hwnd_child, &rc1);
2292 ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2293 ok(ret, "Got %d\n", ret);
2294 GetWindowRect(hwnd_child, &rc2);
2295 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2296 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2297 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2298 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2299 check_active_state(hwnd2, hwnd2, hwnd2);
2300
2301 /* Involving the desktop window changes things. */
2302 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2303 ok(!ret, "Got %d\n", ret);
2304 check_active_state(hwnd2, hwnd2, hwnd2);
2305
2306 GetWindowRect(hwnd_child, &rc1);
2307 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2308 ok(!ret, "Got %d\n", ret);
2309 GetWindowRect(hwnd_child, &rc2);
2310 ok(rc1.top == rc2.top && rc1.left == rc2.left &&
2311 rc1.bottom == rc2.bottom && rc1.right == rc2.right,
2312 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2313 rc1.top, rc1.left, rc1.bottom, rc1.right, rc2.top, rc2.left, rc2.bottom, rc2.right);
2314 check_active_state(hwnd2, hwnd2, hwnd2);
2315
2316 ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2317 ok(!ret, "Got %d\n", ret);
2318 check_active_state(hwnd2, hwnd2, hwnd2);
2319
2320 ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2321 ok(!ret, "Got %d\n", ret);
2322 check_active_state(hwnd2, hwnd2, hwnd2);
2323
2324 ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2325 ok(!ret, "Got %d\n", ret);
2326 check_active_state(hwnd2, hwnd2, hwnd2);
2327
2328 DestroyWindow(hwnd_grandchild);
2329 DestroyWindow(hwnd_child);
2330 DestroyWindow(hwnd_child2);
2331
2332 hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2);
2333 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2334 ret = SetWindowPos(hwnd_child, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2335 ok(ret, "Got %d\n", ret);
2336 flush_events( TRUE );
2337 todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
2338 DestroyWindow(hwnd_child);
2339 }
2340
2341 static void test_SetMenu(HWND parent)
2342 {
2343 HWND child;
2344 HMENU hMenu, ret;
2345 BOOL retok;
2346 DWORD style;
2347
2348 hMenu = CreateMenu();
2349 assert(hMenu);
2350
2351 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2352 if (0)
2353 {
2354 /* fails on (at least) Wine, NT4, XP SP2 */
2355 test_nonclient_area(parent);
2356 }
2357 ret = GetMenu(parent);
2358 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2359 /* test whether we can destroy a menu assigned to a window */
2360 retok = DestroyMenu(hMenu);
2361 ok( retok, "DestroyMenu error %d\n", GetLastError());
2362 retok = IsMenu(hMenu);
2363 ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2364 ret = GetMenu(parent);
2365 /* This test fails on Win9x */
2366 if (!is_win9x)
2367 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2368 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2369 test_nonclient_area(parent);
2370
2371 hMenu = CreateMenu();
2372 assert(hMenu);
2373
2374 /* parent */
2375 ret = GetMenu(parent);
2376 ok(ret == 0, "unexpected menu id %p\n", ret);
2377
2378 ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2379 test_nonclient_area(parent);
2380 ret = GetMenu(parent);
2381 ok(ret == 0, "unexpected menu id %p\n", ret);
2382
2383 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2384 if (0)
2385 {
2386 /* fails on (at least) Wine, NT4, XP SP2 */
2387 test_nonclient_area(parent);
2388 }
2389 ret = GetMenu(parent);
2390 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2391
2392 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2393 test_nonclient_area(parent);
2394 ret = GetMenu(parent);
2395 ok(ret == 0, "unexpected menu id %p\n", ret);
2396
2397 /* child */
2398 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2399 assert(child);
2400
2401 ret = GetMenu(child);
2402 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2403
2404 ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2405 test_nonclient_area(child);
2406 ret = GetMenu(child);
2407 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2408
2409 ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2410 test_nonclient_area(child);
2411 ret = GetMenu(child);
2412 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2413
2414 ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2415 test_nonclient_area(child);
2416 ret = GetMenu(child);
2417 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2418
2419 style = GetWindowLongA(child, GWL_STYLE);
2420 SetWindowLongA(child, GWL_STYLE, style | WS_POPUP);
2421 ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2422 ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2423 SetWindowLongA(child, GWL_STYLE, style);
2424
2425 SetWindowLongA(child, GWL_STYLE, style | WS_OVERLAPPED);
2426 ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n");
2427 SetWindowLongA(child, GWL_STYLE, style);
2428
2429 DestroyWindow(child);
2430 DestroyMenu(hMenu);
2431 }
2432
2433 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2434 {
2435 HWND child[5], hwnd;
2436 INT_PTR i;
2437
2438 assert(total <= 5);
2439
2440 hwnd = GetWindow(parent, GW_CHILD);
2441 ok(!hwnd, "have to start without children to perform the test\n");
2442
2443 for (i = 0; i < total; i++)
2444 {
2445 if (style[i] & DS_CONTROL)
2446 {
2447 child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2448 0,0,0,0, parent, (HMENU)i, 0, NULL);
2449 if (style[i] & WS_VISIBLE)
2450 ShowWindow(child[i], SW_SHOW);
2451
2452 SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
2453 }
2454 else
2455 child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2456 parent, (HMENU)i, 0, NULL);
2457 trace("child[%ld] = %p\n", i, child[i]);
2458 ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2459 }
2460
2461 hwnd = GetWindow(parent, GW_CHILD);
2462 ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2463 ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2464 ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2465
2466 for (i = 0; i < total; i++)
2467 {
2468 trace("hwnd[%ld] = %p\n", i, hwnd);
2469 ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2470
2471 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
2472 }
2473
2474 for (i = 0; i < total; i++)
2475 ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2476 }
2477
2478 static void test_children_zorder(HWND parent)
2479 {
2480 const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2481 WS_CHILD };
2482 const int simple_order[5] = { 0, 1, 2, 3, 4 };
2483
2484 const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2485 WS_CHILD | WS_VISIBLE, WS_CHILD,
2486 WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
2487 const int complex_order_1[1] = { 0 };
2488 const int complex_order_2[2] = { 1, 0 };
2489 const int complex_order_3[3] = { 1, 0, 2 };
2490 const int complex_order_4[4] = { 1, 0, 2, 3 };
2491 const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2492 const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2493 WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
2494 WS_CHILD | WS_VISIBLE };
2495 const int complex_order_6[3] = { 0, 1, 2 };
2496
2497 /* simple WS_CHILD */
2498 test_window_tree(parent, simple_style, simple_order, 5);
2499
2500 /* complex children styles */
2501 test_window_tree(parent, complex_style, complex_order_1, 1);
2502 test_window_tree(parent, complex_style, complex_order_2, 2);
2503 test_window_tree(parent, complex_style, complex_order_3, 3);
2504 test_window_tree(parent, complex_style, complex_order_4, 4);
2505 test_window_tree(parent, complex_style, complex_order_5, 5);
2506
2507 /* another set of complex children styles */
2508 test_window_tree(parent, complex_style_6, complex_order_6, 3);
2509 }
2510
2511 #define check_z_order(hwnd, next, prev, owner, topmost) \
2512 check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2513 __FILE__, __LINE__)
2514
2515 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2516 BOOL topmost, const char *file, int line)
2517 {
2518 HWND test;
2519 DWORD ex_style;
2520
2521 test = GetWindow(hwnd, GW_HWNDNEXT);
2522 /* skip foreign windows */
2523 while (test && test != next &&
2524 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2525 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2526 GetWindow(test, GW_OWNER) == next))
2527 {
2528 /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2529 test = GetWindow(test, GW_HWNDNEXT);
2530 }
2531 ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2532
2533 test = GetWindow(hwnd, GW_HWNDPREV);
2534 /* skip foreign windows */
2535 while (test && test != prev &&
2536 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2537 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) ||
2538 GetWindow(test, GW_OWNER) == hwnd))
2539 {
2540 /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2541 test = GetWindow(test, GW_HWNDPREV);
2542 }
2543 ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2544
2545 test = GetWindow(hwnd, GW_OWNER);
2546 ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2547
2548 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE);
2549 ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2550 hwnd, topmost ? "" : "NOT ");
2551 }
2552
2553 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2554 {
2555 HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2556
2557 trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2558
2559 SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2560
2561 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2562 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2563
2564 hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window",
2565 WS_OVERLAPPED | WS_CAPTION,
2566 100, 100, 100, 100,
2567 0, 0, GetModuleHandleA(NULL), NULL);
2568 trace("hwnd_F %p\n", hwnd_F);
2569 check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2570
2571 SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2572 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2573 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2574 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2575
2576 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2577 style,
2578 100, 100, 100, 100,
2579 hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2580 trace("hwnd_C %p\n", hwnd_C);
2581 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2582 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2583 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2584 check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2585
2586 hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2587 style,
2588 100, 100, 100, 100,
2589 hwnd_F, 0, GetModuleHandleA(NULL), NULL);
2590 trace("hwnd_B %p\n", hwnd_B);
2591 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2592 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2593 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2594 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2595 check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2596
2597 hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL,
2598 style,
2599 100, 100, 100, 100,
2600 0, 0, GetModuleHandleA(NULL), NULL);
2601 trace("hwnd_A %p\n", hwnd_A);
2602 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2603 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2604 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2605 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2606 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2607 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2608
2609 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);
2610
2611 /* move hwnd_F and its popups up */
2612 SetWindowPos(hwnd_F, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2613 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2614 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2615 check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2616 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2617 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2618 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2619
2620 /* move hwnd_F and its popups down */
2621 #if 0 /* enable once Wine is fixed to pass this test */
2622 SetWindowPos(hwnd_F, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2623 check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2624 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2625 check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2626 check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2627 check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2628 check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2629 #endif
2630
2631 /* make hwnd_C owned by a topmost window */
2632 DestroyWindow( hwnd_C );
2633 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL,
2634 style,
2635 100, 100, 100, 100,
2636 hwnd_A, 0, GetModuleHandleA(NULL), NULL);
2637 trace("hwnd_C %p\n", hwnd_C);
2638 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2639 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2640 check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2641 check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2642 check_z_order(hwnd_A,