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 *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
53 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
54
55 static BOOL test_lbuttondown_flag;
56 static HWND hwndMessage;
57 static HWND hwndMain, hwndMain2;
58 static HHOOK hhook;
59
60 static const char* szAWRClass = "Winsize";
61 static HMENU hmenu;
62 static DWORD our_pid;
63
64 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
65
66 static void dump_minmax_info( const MINMAXINFO *minmax )
67 {
68 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
69 minmax->ptReserved.x, minmax->ptReserved.y,
70 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
71 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
72 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
73 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
74 }
75
76 /* try to make sure pending X events have been processed before continuing */
77 static void flush_events( BOOL remove_messages )
78 {
79 MSG msg;
80 int diff = 200;
81 int min_timeout = 50;
82 DWORD time = GetTickCount() + diff;
83
84 while (diff > 0)
85 {
86 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
87 if (remove_messages)
88 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
89 diff = time - GetTickCount();
90 min_timeout = 10;
91 }
92 }
93
94 /* check the values returned by the various parent/owner functions on a given window */
95 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
96 HWND gw_owner, HWND ga_root, HWND ga_root_owner )
97 {
98 HWND res;
99
100 if (pGetAncestor)
101 {
102 res = pGetAncestor( hwnd, GA_PARENT );
103 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
104 }
105 res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
106 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
107 res = GetParent( hwnd );
108 ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
109 res = GetWindow( hwnd, GW_OWNER );
110 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
111 if (pGetAncestor)
112 {
113 res = pGetAncestor( hwnd, GA_ROOT );
114 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
115 res = pGetAncestor( hwnd, GA_ROOTOWNER );
116 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
117 }
118 }
119
120 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
121 {
122 (*(LPINT)lParam)++;
123 trace("EnumChildProc on %p\n", hwndChild);
124 if (*(LPINT)lParam > 1) return FALSE;
125 return TRUE;
126 }
127
128 /* will search for the given window */
129 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam)
130 {
131 trace("EnumChildProc1 on %p\n", hwndChild);
132 if ((HWND)lParam == hwndChild) return FALSE;
133 return TRUE;
134 }
135
136 static HWND create_tool_window( LONG style, HWND parent )
137 {
138 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
139 0, 0, 100, 100, parent, 0, 0, NULL );
140 ok( ret != 0, "Creation failed\n" );
141 return ret;
142 }
143
144 /* test parent and owner values for various combinations */
145 static void test_parent_owner(void)
146 {
147 LONG style;
148 HWND test, owner, ret;
149 HWND desktop = GetDesktopWindow();
150 HWND child = create_tool_window( WS_CHILD, hwndMain );
151 INT numChildren;
152
153 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
154
155 /* child without parent, should fail */
156 SetLastError(0xdeadbeef);
157 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
158 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
159 ok( GetLastError() == ERROR_TLW_WITH_WSCHILD, "CreateWindowExA should call SetLastError\n" );
160 ok( !test, "WS_CHILD without parent created\n" );
161
162 /* desktop window */
163 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
164 style = GetWindowLongA( desktop, GWL_STYLE );
165 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
166 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
167 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
168
169 /* normal child window */
170 test = create_tool_window( WS_CHILD, hwndMain );
171 trace( "created child %p\n", test );
172 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
173 SetWindowLongA( test, GWL_STYLE, 0 );
174 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
175 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
176 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
177 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
178 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
179 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
180 DestroyWindow( test );
181
182 /* normal child window with WS_MAXIMIZE */
183 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
184 DestroyWindow( test );
185
186 /* normal child window with WS_THICKFRAME */
187 test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
188 DestroyWindow( test );
189
190 /* popup window with WS_THICKFRAME */
191 test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
192 DestroyWindow( test );
193
194 /* child of desktop */
195 test = create_tool_window( WS_CHILD, desktop );
196 trace( "created child of desktop %p\n", test );
197 check_parents( test, desktop, 0, desktop, 0, test, desktop );
198 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
199 check_parents( test, desktop, 0, 0, 0, test, test );
200 SetWindowLongA( test, GWL_STYLE, 0 );
201 check_parents( test, desktop, 0, 0, 0, test, test );
202 DestroyWindow( test );
203
204 /* child of desktop with WS_MAXIMIZE */
205 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
206 DestroyWindow( test );
207
208 /* child of desktop with WS_MINIMIZE */
209 test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
210 DestroyWindow( test );
211
212 /* child of child */
213 test = create_tool_window( WS_CHILD, child );
214 trace( "created child of child %p\n", test );
215 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
216 SetWindowLongA( test, GWL_STYLE, 0 );
217 check_parents( test, child, child, 0, 0, hwndMain, test );
218 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
219 check_parents( test, child, child, 0, 0, hwndMain, test );
220 DestroyWindow( test );
221
222 /* child of child with WS_MAXIMIZE */
223 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
224 DestroyWindow( test );
225
226 /* child of child with WS_MINIMIZE */
227 test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
228 DestroyWindow( test );
229
230 /* not owned top-level window */
231 test = create_tool_window( 0, 0 );
232 trace( "created top-level %p\n", test );
233 check_parents( test, desktop, 0, 0, 0, test, test );
234 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
235 check_parents( test, desktop, 0, 0, 0, test, test );
236 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
237 check_parents( test, desktop, 0, desktop, 0, test, desktop );
238 DestroyWindow( test );
239
240 /* not owned top-level window with WS_MAXIMIZE */
241 test = create_tool_window( WS_MAXIMIZE, 0 );
242 DestroyWindow( test );
243
244 /* owned top-level window */
245 test = create_tool_window( 0, hwndMain );
246 trace( "created owned top-level %p\n", test );
247 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
248 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
249 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
250 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
251 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
252 DestroyWindow( test );
253
254 /* owned top-level window with WS_MAXIMIZE */
255 test = create_tool_window( WS_MAXIMIZE, hwndMain );
256 DestroyWindow( test );
257
258 /* not owned popup */
259 test = create_tool_window( WS_POPUP, 0 );
260 trace( "created popup %p\n", test );
261 check_parents( test, desktop, 0, 0, 0, test, test );
262 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
263 check_parents( test, desktop, 0, desktop, 0, test, desktop );
264 SetWindowLongA( test, GWL_STYLE, 0 );
265 check_parents( test, desktop, 0, 0, 0, test, test );
266 DestroyWindow( test );
267
268 /* not owned popup with WS_MAXIMIZE */
269 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
270 DestroyWindow( test );
271
272 /* owned popup */
273 test = create_tool_window( WS_POPUP, hwndMain );
274 trace( "created owned popup %p\n", test );
275 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
276 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
277 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
278 SetWindowLongA( test, GWL_STYLE, 0 );
279 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
280 DestroyWindow( test );
281
282 /* owned popup with WS_MAXIMIZE */
283 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
284 DestroyWindow( test );
285
286 /* top-level window owned by child (same as owned by top-level) */
287 test = create_tool_window( 0, child );
288 trace( "created top-level owned by child %p\n", test );
289 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
290 DestroyWindow( test );
291
292 /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
293 test = create_tool_window( WS_MAXIMIZE, child );
294 DestroyWindow( test );
295
296 /* popup owned by desktop (same as not owned) */
297 test = create_tool_window( WS_POPUP, desktop );
298 trace( "created popup owned by desktop %p\n", test );
299 check_parents( test, desktop, 0, 0, 0, test, test );
300 DestroyWindow( test );
301
302 /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
303 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
304 DestroyWindow( test );
305
306 /* popup owned by child (same as owned by top-level) */
307 test = create_tool_window( WS_POPUP, child );
308 trace( "created popup owned by child %p\n", test );
309 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
310 DestroyWindow( test );
311
312 /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
313 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
314 DestroyWindow( test );
315
316 /* not owned popup with WS_CHILD (same as WS_POPUP only) */
317 test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
318 trace( "created WS_CHILD popup %p\n", test );
319 check_parents( test, desktop, 0, 0, 0, test, test );
320 DestroyWindow( test );
321
322 /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
323 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
324 DestroyWindow( test );
325
326 /* owned popup with WS_CHILD (same as WS_POPUP only) */
327 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
328 trace( "created owned WS_CHILD popup %p\n", test );
329 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
330 DestroyWindow( test );
331
332 /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
333 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
334 DestroyWindow( test );
335
336 /******************** parent changes *************************/
337 trace( "testing parent changes\n" );
338
339 /* desktop window */
340 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
341 if (0)
342 {
343 /* this test succeeds on NT but crashes on win9x systems */
344 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
345 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
346 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
347 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
348 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
349 }
350 /* normal child window */
351 test = create_tool_window( WS_CHILD, hwndMain );
352 trace( "created child %p\n", test );
353
354 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
355 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
356 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
357
358 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
359 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
360 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
361
362 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
363 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
364 check_parents( test, desktop, 0, desktop, 0, test, desktop );
365
366 /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
367 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
368 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
369 check_parents( test, desktop, child, desktop, child, test, desktop );
370
371 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
372 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
373 check_parents( test, desktop, 0, desktop, 0, test, desktop );
374 DestroyWindow( test );
375
376 /* not owned top-level window */
377 test = create_tool_window( 0, 0 );
378 trace( "created top-level %p\n", test );
379
380 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
381 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
382 check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
383
384 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
385 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
386 check_parents( test, desktop, child, 0, child, test, test );
387
388 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
389 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
390 check_parents( test, desktop, 0, 0, 0, test, test );
391 DestroyWindow( test );
392
393 /* not owned popup */
394 test = create_tool_window( WS_POPUP, 0 );
395 trace( "created popup %p\n", test );
396
397 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
398 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
399 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
400
401 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
402 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
403 check_parents( test, desktop, child, child, child, test, hwndMain );
404
405 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
406 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
407 check_parents( test, desktop, 0, 0, 0, test, test );
408 DestroyWindow( test );
409
410 /* normal child window */
411 test = create_tool_window( WS_CHILD, hwndMain );
412 trace( "created child %p\n", test );
413
414 ret = SetParent( test, desktop );
415 ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
416 check_parents( test, desktop, 0, desktop, 0, test, desktop );
417
418 ret = SetParent( test, child );
419 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
420 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
421
422 ret = SetParent( test, hwndMain2 );
423 ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
424 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
425 DestroyWindow( test );
426
427 /* not owned top-level window */
428 test = create_tool_window( 0, 0 );
429 trace( "created top-level %p\n", test );
430
431 ret = SetParent( test, child );
432 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
433 check_parents( test, child, child, 0, 0, hwndMain, test );
434 DestroyWindow( test );
435
436 /* owned popup */
437 test = create_tool_window( WS_POPUP, hwndMain2 );
438 trace( "created owned popup %p\n", test );
439
440 ret = SetParent( test, child );
441 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
442 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
443
444 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
445 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
446 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
447 DestroyWindow( test );
448
449 /**************** test owner destruction *******************/
450
451 /* owned child popup */
452 owner = create_tool_window( 0, 0 );
453 test = create_tool_window( WS_POPUP, owner );
454 trace( "created owner %p and popup %p\n", owner, test );
455 ret = SetParent( test, child );
456 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
457 check_parents( test, child, child, owner, owner, hwndMain, owner );
458 /* window is now child of 'child' but owned by 'owner' */
459 DestroyWindow( owner );
460 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
461 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
462 * while Win95, Win2k, WinXP do.
463 */
464 /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
465 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
466 DestroyWindow(test);
467
468 /* owned top-level popup */
469 owner = create_tool_window( 0, 0 );
470 test = create_tool_window( WS_POPUP, owner );
471 trace( "created owner %p and popup %p\n", owner, test );
472 check_parents( test, desktop, owner, owner, owner, test, owner );
473 DestroyWindow( owner );
474 ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
475
476 /* top-level popup owned by child */
477 owner = create_tool_window( WS_CHILD, hwndMain2 );
478 test = create_tool_window( WS_POPUP, 0 );
479 trace( "created owner %p and popup %p\n", owner, test );
480 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
481 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
482 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
483 DestroyWindow( owner );
484 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
485 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
486 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
487 * while Win95, Win2k, WinXP do.
488 */
489 /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
490 DestroyWindow(test);
491
492 /* final cleanup */
493 DestroyWindow(child);
494
495
496 owner = create_tool_window( WS_OVERLAPPED, 0 );
497 test = create_tool_window( WS_POPUP, desktop );
498
499 ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
500 numChildren = 0;
501 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
502 "EnumChildWindows should have returned FALSE\n" );
503 ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
504
505 SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
506 ret = SetParent( test, owner );
507 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
508
509 numChildren = 0;
510 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
511 "EnumChildWindows should have returned TRUE\n" );
512 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
513
514 child = create_tool_window( WS_CHILD, owner );
515 numChildren = 0;
516 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
517 "EnumChildWindows should have returned FALSE\n" );
518 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
519 DestroyWindow( child );
520
521 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
522 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
523 numChildren = 0;
524 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
525 "EnumChildWindows should have returned TRUE\n" );
526 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
527
528 ret = SetParent( child, owner );
529 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
530 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
531 numChildren = 0;
532 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
533 "EnumChildWindows should have returned FALSE\n" );
534 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
535
536 ret = SetParent( child, NULL );
537 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
538 ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
539 numChildren = 0;
540 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
541 "EnumChildWindows should have returned TRUE\n" );
542 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
543
544 /* even GW_OWNER == owner it's still a desktop's child */
545 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
546 "EnumChildWindows should have found %p and returned FALSE\n", child );
547
548 DestroyWindow( child );
549 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
550
551 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
552 "EnumChildWindows should have found %p and returned FALSE\n", child );
553
554 DestroyWindow( child );
555 DestroyWindow( test );
556 DestroyWindow( owner );
557 }
558
559
560 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
561 {
562 switch (msg)
563 {
564 case WM_GETMINMAXINFO:
565 {
566 MINMAXINFO* minmax = (MINMAXINFO *)lparam;
567
568 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
569 dump_minmax_info( minmax );
570 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
571 break;
572 }
573 case WM_WINDOWPOSCHANGING:
574 {
575 BOOL is_win9x = GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == 0;
576 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
577 trace("main: WM_WINDOWPOSCHANGING\n");
578 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
579 winpos->hwnd, winpos->hwndInsertAfter,
580 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
581 if (!(winpos->flags & SWP_NOMOVE))
582 {
583 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
584 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
585 }
586 /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
587 if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
588 {
589 ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
590 ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
591 }
592 break;
593 }
594 case WM_WINDOWPOSCHANGED:
595 {
596 RECT rc1, rc2;
597 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
598 trace("main: WM_WINDOWPOSCHANGED\n");
599 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
600 winpos->hwnd, winpos->hwndInsertAfter,
601 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
602 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
603 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
604
605 ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx);
606 ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy);
607
608 GetWindowRect(hwnd, &rc1);
609 trace("window: (%d,%d)-(%d,%d)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
610 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
611 /* note: winpos coordinates are relative to parent */
612 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
613 trace("pos: (%d,%d)-(%d,%d)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
614 if (0)
615 {
616 /* Uncomment this once the test succeeds in all cases */
617 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
618 }
619
620 GetClientRect(hwnd, &rc2);
621 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
622 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
623 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
624 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
625 break;
626 }
627 case WM_NCCREATE:
628 {
629 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
630 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
631
632 trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
633 if (got_getminmaxinfo)
634 trace("%p got WM_GETMINMAXINFO\n", hwnd);
635
636 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
637 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
638 else
639 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
640 break;
641 }
642 case WM_COMMAND:
643 if (test_lbuttondown_flag)
644 {
645 ShowWindow((HWND)wparam, SW_SHOW);
646 flush_events( FALSE );
647 }
648 break;
649 }
650
651 return DefWindowProcA(hwnd, msg, wparam, lparam);
652 }
653
654 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
655 {
656 switch (msg)
657 {
658 case WM_GETMINMAXINFO:
659 {
660 MINMAXINFO* minmax = (MINMAXINFO *)lparam;
661
662 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
663 dump_minmax_info( minmax );
664 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
665 break;
666 }
667 case WM_NCCREATE:
668 {
669 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
670 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
671
672 trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
673 if (got_getminmaxinfo)
674 trace("%p got WM_GETMINMAXINFO\n", hwnd);
675
676 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
677 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
678 else
679 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
680 break;
681 }
682 }
683
684 return DefWindowProcA(hwnd, msg, wparam, lparam);
685 }
686
687 static BOOL RegisterWindowClasses(void)