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