2 * Unit tests for window handling
4 * Copyright 2002 Bill Medland
5 * Copyright 2002 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/test.h"
34 # define IDC_ARROWA IDC_ARROW
37 #ifndef SPI_GETDESKWALLPAPER
38 #define SPI_GETDESKWALLPAPER 0x0073
41 #define LONG_PTR INT_PTR
42 #define ULONG_PTR UINT_PTR
44 static HWND (WINAPI *pGetAncestor)(HWND,UINT);
46 static HWND hwndMain, hwndMain2;
48 /* check the values returned by the various parent/owner functions on a given window */
49 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
50 HWND gw_owner, HWND ga_root, HWND ga_root_owner )
56 res = pGetAncestor( hwnd, GA_PARENT );
57 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p", res, ga_parent );
59 res = (HWND)GetWindowLongA( hwnd, GWL_HWNDPARENT );
60 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p", res, gwl_parent );
61 res = GetParent( hwnd );
62 ok( res == get_parent, "Wrong result for GetParent %p expected %p", res, get_parent );
63 res = GetWindow( hwnd, GW_OWNER );
64 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p", res, gw_owner );
67 res = pGetAncestor( hwnd, GA_ROOT );
68 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p", res, ga_root );
69 res = pGetAncestor( hwnd, GA_ROOTOWNER );
70 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p", res, ga_root_owner );
75 static HWND create_tool_window( LONG style, HWND parent )
77 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
78 0, 0, 100, 100, parent, 0, 0, NULL );
79 ok( ret != 0, "Creation failed" );
83 /* test parent and owner values for various combinations */
84 static void test_parent_owner(void)
87 HWND test, owner, ret;
88 HWND desktop = GetDesktopWindow();
89 HWND child = create_tool_window( WS_CHILD, hwndMain );
91 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
93 /* child without parent, should fail */
94 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
95 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
96 ok( !test, "WS_CHILD without parent created" );
99 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
100 style = GetWindowLongA( desktop, GWL_STYLE );
101 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded" );
102 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded" );
103 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed" );
105 /* normal child window */
106 test = create_tool_window( WS_CHILD, hwndMain );
107 trace( "created child %p\n", test );
108 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
109 SetWindowLongA( test, GWL_STYLE, 0 );
110 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
111 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
112 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
113 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
114 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
115 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
116 DestroyWindow( test );
118 /* child of desktop */
119 test = create_tool_window( WS_CHILD, desktop );
120 trace( "created child of desktop %p\n", test );
121 check_parents( test, desktop, 0, desktop, 0, test, desktop );
122 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
123 check_parents( test, desktop, 0, 0, 0, test, test );
124 SetWindowLongA( test, GWL_STYLE, 0 );
125 check_parents( test, desktop, 0, 0, 0, test, test );
126 DestroyWindow( test );
129 test = create_tool_window( WS_CHILD, child );
130 trace( "created child of child %p\n", test );
131 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
132 SetWindowLongA( test, GWL_STYLE, 0 );
133 check_parents( test, child, child, 0, 0, hwndMain, test );
134 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
135 check_parents( test, child, child, 0, 0, hwndMain, test );
136 DestroyWindow( test );
138 /* not owned top-level window */
139 test = create_tool_window( 0, 0 );
140 trace( "created top-level %p\n", test );
141 check_parents( test, desktop, 0, 0, 0, test, test );
142 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
143 check_parents( test, desktop, 0, 0, 0, test, test );
144 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
145 check_parents( test, desktop, 0, desktop, 0, test, desktop );
146 DestroyWindow( test );
148 /* owned top-level window */
149 test = create_tool_window( 0, hwndMain );
150 trace( "created owned top-level %p\n", test );
151 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
152 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
153 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
154 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
155 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
156 DestroyWindow( test );
158 /* not owned popup */
159 test = create_tool_window( WS_POPUP, 0 );
160 trace( "created popup %p\n", test );
161 check_parents( test, desktop, 0, 0, 0, test, test );
162 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
163 check_parents( test, desktop, 0, desktop, 0, test, desktop );
164 SetWindowLongA( test, GWL_STYLE, 0 );
165 check_parents( test, desktop, 0, 0, 0, test, test );
166 DestroyWindow( test );
169 test = create_tool_window( WS_POPUP, hwndMain );
170 trace( "created owned popup %p\n", test );
171 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
172 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
173 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
174 SetWindowLongA( test, GWL_STYLE, 0 );
175 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
176 DestroyWindow( test );
178 /* top-level window owned by child (same as owned by top-level) */
179 test = create_tool_window( 0, child );
180 trace( "created top-level owned by child %p\n", test );
181 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
182 DestroyWindow( test );
184 /* popup owned by desktop (same as not owned) */
185 test = create_tool_window( WS_POPUP, desktop );
186 trace( "created popup owned by desktop %p\n", test );
187 check_parents( test, desktop, 0, 0, 0, test, test );
188 DestroyWindow( test );
190 /* popup owned by child (same as owned by top-level) */
191 test = create_tool_window( WS_POPUP, child );
192 trace( "created popup owned by child %p\n", test );
193 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
194 DestroyWindow( test );
196 /* not owned popup with WS_CHILD (same as WS_POPUP only) */
197 test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
198 trace( "created WS_CHILD popup %p\n", test );
199 check_parents( test, desktop, 0, 0, 0, test, test );
200 DestroyWindow( test );
202 /* owned popup with WS_CHILD (same as WS_POPUP only) */
203 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
204 trace( "created owned WS_CHILD popup %p\n", test );
205 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
206 DestroyWindow( test );
208 /******************** parent changes *************************/
209 trace( "testing parent changes\n" );
212 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
213 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
214 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop" );
215 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
216 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop" );
217 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
219 /* normal child window */
220 test = create_tool_window( WS_CHILD, hwndMain );
221 trace( "created child %p\n", test );
223 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
224 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain );
225 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
227 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
228 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
229 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
231 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)desktop );
232 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
233 check_parents( test, desktop, 0, desktop, 0, test, desktop );
235 /* window is now child of desktop so GWL_HWNDPARENT changes owner from now on */
236 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
237 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
238 check_parents( test, desktop, child, desktop, child, test, desktop );
240 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
241 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
242 check_parents( test, desktop, 0, desktop, 0, test, desktop );
243 DestroyWindow( test );
245 /* not owned top-level window */
246 test = create_tool_window( 0, 0 );
247 trace( "created top-level %p\n", test );
249 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
250 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
251 check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
253 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
254 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
255 check_parents( test, desktop, child, 0, child, test, test );
257 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
258 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
259 check_parents( test, desktop, 0, 0, 0, test, test );
260 DestroyWindow( test );
262 /* not owned popup */
263 test = create_tool_window( WS_POPUP, 0 );
264 trace( "created popup %p\n", test );
266 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)hwndMain2 );
267 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
268 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
270 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (LONG_PTR)child );
271 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p", ret, hwndMain2 );
272 check_parents( test, desktop, child, child, child, test, hwndMain );
274 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, 0 );
275 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
276 check_parents( test, desktop, 0, 0, 0, test, test );
277 DestroyWindow( test );
279 /* normal child window */
280 test = create_tool_window( WS_CHILD, hwndMain );
281 trace( "created child %p\n", test );
283 ret = SetParent( test, desktop );
284 ok( ret == hwndMain, "SetParent return value %p expected %p", ret, hwndMain );
285 check_parents( test, desktop, 0, desktop, 0, test, desktop );
287 ret = SetParent( test, child );
288 ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
289 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
291 ret = SetParent( test, hwndMain2 );
292 ok( ret == child, "SetParent return value %p expected %p", ret, child );
293 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
294 DestroyWindow( test );
296 /* not owned top-level window */
297 test = create_tool_window( 0, 0 );
298 trace( "created top-level %p\n", test );
300 ret = SetParent( test, child );
301 ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
302 check_parents( test, child, child, 0, 0, hwndMain, test );
303 DestroyWindow( test );
306 test = create_tool_window( WS_POPUP, hwndMain2 );
307 trace( "created owned popup %p\n", test );
309 ret = SetParent( test, child );
310 ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
311 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
313 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)hwndMain );
314 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p", ret, child );
315 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
316 DestroyWindow( test );
318 /**************** test owner destruction *******************/
320 /* owned child popup */
321 owner = create_tool_window( 0, 0 );
322 test = create_tool_window( WS_POPUP, owner );
323 trace( "created owner %p and popup %p\n", owner, test );
324 ret = SetParent( test, child );
325 ok( ret == desktop, "SetParent return value %p expected %p", ret, desktop );
326 check_parents( test, child, child, owner, owner, hwndMain, owner );
327 /* window is now child of 'child' but owned by 'owner' */
328 DestroyWindow( owner );
329 ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
330 check_parents( test, child, child, owner, owner, hwndMain, owner );
331 ok( !IsWindow(owner), "Owner %p not destroyed", owner );
334 /* owned top-level popup */
335 owner = create_tool_window( 0, 0 );
336 test = create_tool_window( WS_POPUP, owner );
337 trace( "created owner %p and popup %p\n", owner, test );
338 check_parents( test, desktop, owner, owner, owner, test, owner );
339 DestroyWindow( owner );
340 ok( !IsWindow(test), "Window %p not destroyed by owner destruction", test );
342 /* top-level popup owned by child */
343 owner = create_tool_window( WS_CHILD, hwndMain2 );
344 test = create_tool_window( WS_POPUP, 0 );
345 trace( "created owner %p and popup %p\n", owner, test );
346 ret = (HWND)SetWindowLongA( test, GWL_HWNDPARENT, (ULONG_PTR)owner );
347 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0", ret );
348 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
349 DestroyWindow( owner );
350 ok( IsWindow(test), "Window %p destroyed by owner destruction", test );
351 ok( !IsWindow(owner), "Owner %p not destroyed", owner );
352 check_parents( test, desktop, owner, owner, owner, test, owner );
356 DestroyWindow(child);
360 static BOOL RegisterWindowClasses(void)
365 cls.lpfnWndProc = DefWindowProcA;
368 cls.hInstance = GetModuleHandleA(0);
370 cls.hCursor = LoadCursorA(0, IDC_ARROWA);
371 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
372 cls.lpszMenuName = NULL;
373 cls.lpszClassName = "MainWindowClass";
375 if(!RegisterClassA(&cls)) return FALSE;
378 cls.lpfnWndProc = DefWindowProcA;
381 cls.hInstance = GetModuleHandleA(0);
383 cls.hCursor = LoadCursorA(0, IDC_ARROWA);
384 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
385 cls.lpszMenuName = NULL;
386 cls.lpszClassName = "ToolWindowClass";
388 if(!RegisterClassA(&cls)) return FALSE;
396 pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" );
398 if (!RegisterWindowClasses()) assert(0);
400 hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
401 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
402 WS_MAXIMIZEBOX | WS_POPUP,
405 hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
406 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
407 WS_MAXIMIZEBOX | WS_POPUP,