2 * Unit tests for window handling
4 * Copyright 2002 Bill Medland
5 * Copyright 2002 Alexandre Julliard
6 * Copyright 2003 Dmitry Timoshkov
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 /* To get ICON_SMALL2 with the MSVC headers */
24 #define _WIN32_WINNT 0x0501
36 #include "wine/test.h"
38 #ifndef SPI_GETDESKWALLPAPER
39 #define SPI_GETDESKWALLPAPER 0x0073
42 #define LONG_PTR INT_PTR
43 #define ULONG_PTR UINT_PTR
45 void dump_region(HRGN hrgn);
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 *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
54 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
55 static int (WINAPI *pGetWindowRgnBox)(HWND,LPRECT);
56 static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*);
57 static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout );
58 static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout );
59 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout);
60 static DWORD (WINAPI *pGetLayout)(HDC hdc);
61 static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn);
63 static BOOL test_lbuttondown_flag;
64 static HWND hwndMessage;
65 static HWND hwndMain, hwndMain2;
68 static const char* szAWRClass = "Winsize";
72 static BOOL is_win9x = FALSE;
74 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0]))
76 static void dump_minmax_info( const MINMAXINFO *minmax )
78 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n",
79 minmax->ptReserved.x, minmax->ptReserved.y,
80 minmax->ptMaxSize.x, minmax->ptMaxSize.y,
81 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y,
82 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y,
83 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y);
86 /* try to make sure pending X events have been processed before continuing */
87 static void flush_events( BOOL remove_messages )
91 int min_timeout = 100;
92 DWORD time = GetTickCount() + diff;
96 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
98 while (PeekMessage( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessage( &msg );
99 diff = time - GetTickCount();
104 /* check the values returned by the various parent/owner functions on a given window */
105 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent,
106 HWND gw_owner, HWND ga_root, HWND ga_root_owner )
112 res = pGetAncestor( hwnd, GA_PARENT );
113 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent );
115 res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT );
116 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent );
117 res = GetParent( hwnd );
118 ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent );
119 res = GetWindow( hwnd, GW_OWNER );
120 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner );
123 res = pGetAncestor( hwnd, GA_ROOT );
124 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root );
125 res = pGetAncestor( hwnd, GA_ROOTOWNER );
126 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner );
130 #define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
131 static void check_wnd_state_(const char *file, int line,
132 HWND active, HWND foreground, HWND focus, HWND capture)
134 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
135 /* only check foreground if it belongs to the current thread */
136 /* foreground can be moved to a different app pretty much at any time */
137 if (foreground && GetForegroundWindow() &&
138 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
139 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
140 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
141 ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
144 /* same as above but without capture test */
145 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
146 static void check_active_state_(const char *file, int line,
147 HWND active, HWND foreground, HWND focus)
149 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
150 /* only check foreground if it belongs to the current thread */
151 /* foreground can be moved to a different app pretty much at any time */
152 if (foreground && GetForegroundWindow() &&
153 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
154 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
155 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
158 static BOOL ignore_message( UINT message )
160 /* these are always ignored */
161 return (message >= 0xc000 ||
162 message == WM_GETICON ||
163 message == WM_GETOBJECT ||
164 message == WM_TIMECHANGE ||
165 message == WM_DEVICECHANGE);
168 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam)
171 trace("EnumChildProc on %p\n", hwndChild);
172 if (*(LPINT)lParam > 1) return FALSE;
176 /* will search for the given window */
177 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam)
179 trace("EnumChildProc1 on %p\n", hwndChild);
180 if ((HWND)lParam == hwndChild) return FALSE;
184 static HWND create_tool_window( LONG style, HWND parent )
186 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style,
187 0, 0, 100, 100, parent, 0, 0, NULL );
188 ok( ret != 0, "Creation failed\n" );
192 /* test parent and owner values for various combinations */
193 static void test_parent_owner(void)
196 HWND test, owner, ret;
197 HWND desktop = GetDesktopWindow();
198 HWND child = create_tool_window( WS_CHILD, hwndMain );
201 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child );
203 /* child without parent, should fail */
204 SetLastError(0xdeadbeef);
205 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1",
206 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL );
207 ok( !test, "WS_CHILD without parent created\n" );
208 ok( GetLastError() == ERROR_TLW_WITH_WSCHILD ||
209 broken(GetLastError() == 0xdeadbeef), /* win9x */
210 "CreateWindowExA error %u\n", GetLastError() );
213 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
214 style = GetWindowLongA( desktop, GWL_STYLE );
215 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" );
216 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" );
217 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" );
219 /* normal child window */
220 test = create_tool_window( WS_CHILD, hwndMain );
221 trace( "created child %p\n", test );
222 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain );
223 SetWindowLongA( test, GWL_STYLE, 0 );
224 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
225 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
226 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
227 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD );
228 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test );
229 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
230 DestroyWindow( test );
232 /* normal child window with WS_MAXIMIZE */
233 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain );
234 DestroyWindow( test );
236 /* normal child window with WS_THICKFRAME */
237 test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain );
238 DestroyWindow( test );
240 /* popup window with WS_THICKFRAME */
241 test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain );
242 DestroyWindow( test );
244 /* child of desktop */
245 test = create_tool_window( WS_CHILD, desktop );
246 trace( "created child of desktop %p\n", test );
247 check_parents( test, desktop, 0, desktop, 0, test, desktop );
248 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
249 check_parents( test, desktop, 0, 0, 0, test, test );
250 SetWindowLongA( test, GWL_STYLE, 0 );
251 check_parents( test, desktop, 0, 0, 0, test, test );
252 DestroyWindow( test );
254 /* child of desktop with WS_MAXIMIZE */
255 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop );
256 DestroyWindow( test );
258 /* child of desktop with WS_MINIMIZE */
259 test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop );
260 DestroyWindow( test );
263 test = create_tool_window( WS_CHILD, child );
264 trace( "created child of child %p\n", test );
265 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
266 SetWindowLongA( test, GWL_STYLE, 0 );
267 check_parents( test, child, child, 0, 0, hwndMain, test );
268 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
269 check_parents( test, child, child, 0, 0, hwndMain, test );
270 DestroyWindow( test );
272 /* child of child with WS_MAXIMIZE */
273 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child );
274 DestroyWindow( test );
276 /* child of child with WS_MINIMIZE */
277 test = create_tool_window( WS_CHILD | WS_MINIMIZE, child );
278 DestroyWindow( test );
280 /* not owned top-level window */
281 test = create_tool_window( 0, 0 );
282 trace( "created top-level %p\n", test );
283 check_parents( test, desktop, 0, 0, 0, test, test );
284 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
285 check_parents( test, desktop, 0, 0, 0, test, test );
286 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
287 check_parents( test, desktop, 0, desktop, 0, test, desktop );
288 DestroyWindow( test );
290 /* not owned top-level window with WS_MAXIMIZE */
291 test = create_tool_window( WS_MAXIMIZE, 0 );
292 DestroyWindow( test );
294 /* owned top-level window */
295 test = create_tool_window( 0, hwndMain );
296 trace( "created owned top-level %p\n", test );
297 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
298 SetWindowLongA( test, GWL_STYLE, WS_POPUP );
299 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
300 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
301 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
302 DestroyWindow( test );
304 /* owned top-level window with WS_MAXIMIZE */
305 test = create_tool_window( WS_MAXIMIZE, hwndMain );
306 DestroyWindow( test );
308 /* not owned popup */
309 test = create_tool_window( WS_POPUP, 0 );
310 trace( "created popup %p\n", test );
311 check_parents( test, desktop, 0, 0, 0, test, test );
312 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
313 check_parents( test, desktop, 0, desktop, 0, test, desktop );
314 SetWindowLongA( test, GWL_STYLE, 0 );
315 check_parents( test, desktop, 0, 0, 0, test, test );
316 DestroyWindow( test );
318 /* not owned popup with WS_MAXIMIZE */
319 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 );
320 DestroyWindow( test );
323 test = create_tool_window( WS_POPUP, hwndMain );
324 trace( "created owned popup %p\n", test );
325 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
326 SetWindowLongA( test, GWL_STYLE, WS_CHILD );
327 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop );
328 SetWindowLongA( test, GWL_STYLE, 0 );
329 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
330 DestroyWindow( test );
332 /* owned popup with WS_MAXIMIZE */
333 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain );
334 DestroyWindow( test );
336 /* top-level window owned by child (same as owned by top-level) */
337 test = create_tool_window( 0, child );
338 trace( "created top-level owned by child %p\n", test );
339 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test );
340 DestroyWindow( test );
342 /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */
343 test = create_tool_window( WS_MAXIMIZE, child );
344 DestroyWindow( test );
346 /* popup owned by desktop (same as not owned) */
347 test = create_tool_window( WS_POPUP, desktop );
348 trace( "created popup owned by desktop %p\n", test );
349 check_parents( test, desktop, 0, 0, 0, test, test );
350 DestroyWindow( test );
352 /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */
353 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop );
354 DestroyWindow( test );
356 /* popup owned by child (same as owned by top-level) */
357 test = create_tool_window( WS_POPUP, child );
358 trace( "created popup owned by child %p\n", test );
359 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
360 DestroyWindow( test );
362 /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */
363 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child );
364 DestroyWindow( test );
366 /* not owned popup with WS_CHILD (same as WS_POPUP only) */
367 test = create_tool_window( WS_POPUP | WS_CHILD, 0 );
368 trace( "created WS_CHILD popup %p\n", test );
369 check_parents( test, desktop, 0, 0, 0, test, test );
370 DestroyWindow( test );
372 /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */
373 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 );
374 DestroyWindow( test );
376 /* owned popup with WS_CHILD (same as WS_POPUP only) */
377 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain );
378 trace( "created owned WS_CHILD popup %p\n", test );
379 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain );
380 DestroyWindow( test );
382 /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */
383 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain );
384 DestroyWindow( test );
386 /******************** parent changes *************************/
387 trace( "testing parent changes\n" );
390 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
393 /* this test succeeds on NT but crashes on win9x systems */
394 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
395 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" );
396 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
397 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" );
398 check_parents( desktop, 0, 0, 0, 0, 0, 0 );
400 /* normal child window */
401 test = create_tool_window( WS_CHILD, hwndMain );
402 trace( "created child %p\n", test );
404 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
405 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain );
406 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
408 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
409 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
410 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
412 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop );
413 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
414 check_parents( test, desktop, 0, desktop, 0, test, desktop );
416 /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */
419 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test );
420 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
421 check_parents( test, desktop, 0, desktop, 0, test, desktop );
424 win_skip("Test creates circular window tree under Win9x/WinMe\n" );
426 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
427 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
428 check_parents( test, desktop, child, desktop, child, test, desktop );
430 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
431 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
432 check_parents( test, desktop, 0, desktop, 0, test, desktop );
433 DestroyWindow( test );
435 /* not owned top-level window */
436 test = create_tool_window( 0, 0 );
437 trace( "created top-level %p\n", test );
439 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
440 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
441 check_parents( test, desktop, hwndMain2, 0, hwndMain2, test, test );
443 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
444 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
445 check_parents( test, desktop, child, 0, child, test, test );
447 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
448 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
449 check_parents( test, desktop, 0, 0, 0, test, test );
450 DestroyWindow( test );
452 /* not owned popup */
453 test = create_tool_window( WS_POPUP, 0 );
454 trace( "created popup %p\n", test );
456 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 );
457 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
458 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 );
460 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child );
461 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 );
462 check_parents( test, desktop, child, child, child, test, hwndMain );
464 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 );
465 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
466 check_parents( test, desktop, 0, 0, 0, test, test );
467 DestroyWindow( test );
469 /* normal child window */
470 test = create_tool_window( WS_CHILD, hwndMain );
471 trace( "created child %p\n", test );
473 ret = SetParent( test, desktop );
474 ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain );
475 check_parents( test, desktop, 0, desktop, 0, test, desktop );
477 ret = SetParent( test, child );
478 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
479 check_parents( test, child, child, child, 0, hwndMain, hwndMain );
481 ret = SetParent( test, hwndMain2 );
482 ok( ret == child, "SetParent return value %p expected %p\n", ret, child );
483 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 );
484 DestroyWindow( test );
486 /* not owned top-level window */
487 test = create_tool_window( 0, 0 );
488 trace( "created top-level %p\n", test );
490 ret = SetParent( test, child );
491 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
492 check_parents( test, child, child, 0, 0, hwndMain, test );
496 ShowWindow( test, SW_SHOW );
497 ret = SetParent( test, test );
498 ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL );
499 ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" );
500 check_parents( test, child, child, 0, 0, hwndMain, test );
503 win_skip( "Test crashes on Win9x/WinMe\n" );
504 DestroyWindow( test );
507 test = create_tool_window( WS_POPUP, hwndMain2 );
508 trace( "created owned popup %p\n", test );
510 ret = SetParent( test, child );
511 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
512 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
514 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain );
515 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child );
516 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 );
517 DestroyWindow( test );
519 /**************** test owner destruction *******************/
521 /* owned child popup */
522 owner = create_tool_window( 0, 0 );
523 test = create_tool_window( WS_POPUP, owner );
524 trace( "created owner %p and popup %p\n", owner, test );
525 ret = SetParent( test, child );
526 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
527 check_parents( test, child, child, owner, owner, hwndMain, owner );
528 /* window is now child of 'child' but owned by 'owner' */
529 DestroyWindow( owner );
530 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
531 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
532 * while Win95, Win2k, WinXP do.
534 /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/
535 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
538 /* owned top-level popup */
539 owner = create_tool_window( 0, 0 );
540 test = create_tool_window( WS_POPUP, owner );
541 trace( "created owner %p and popup %p\n", owner, test );
542 check_parents( test, desktop, owner, owner, owner, test, owner );
543 DestroyWindow( owner );
544 ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test );
546 /* top-level popup owned by child */
547 owner = create_tool_window( WS_CHILD, hwndMain2 );
548 test = create_tool_window( WS_POPUP, 0 );
549 trace( "created owner %p and popup %p\n", owner, test );
550 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner );
551 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret );
552 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 );
553 DestroyWindow( owner );
554 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test );
555 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner );
556 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner,
557 * while Win95, Win2k, WinXP do.
559 /*check_parents( test, desktop, owner, owner, owner, test, owner );*/
563 DestroyWindow(child);
566 owner = create_tool_window( WS_OVERLAPPED, 0 );
567 test = create_tool_window( WS_POPUP, desktop );
569 ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" );
571 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
572 "EnumChildWindows should have returned FALSE\n" );
573 ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren );
575 SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD );
576 ret = SetParent( test, owner );
577 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
580 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
581 "EnumChildWindows should have returned TRUE\n" );
582 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
584 child = create_tool_window( WS_CHILD, owner );
586 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
587 "EnumChildWindows should have returned FALSE\n" );
588 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
589 DestroyWindow( child );
591 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner );
592 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
594 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
595 "EnumChildWindows should have returned TRUE\n" );
596 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
598 ret = SetParent( child, owner );
599 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
600 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop );
602 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
603 "EnumChildWindows should have returned FALSE\n" );
604 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren );
606 ret = SetParent( child, NULL );
607 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" );
608 ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner );
610 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ),
611 "EnumChildWindows should have returned TRUE\n" );
612 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren );
614 /* even GW_OWNER == owner it's still a desktop's child */
615 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
616 "EnumChildWindows should have found %p and returned FALSE\n", child );
618 DestroyWindow( child );
619 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL );
621 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ),
622 "EnumChildWindows should have found %p and returned FALSE\n", child );
624 DestroyWindow( child );
625 DestroyWindow( test );
626 DestroyWindow( owner );
629 static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam)
632 if (*(LPINT)lParam > 2) return FALSE;
635 static DWORD CALLBACK enum_thread( void *arg )
642 if (pGetGUIThreadInfo)
645 info.cbSize = sizeof(info);
646 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
647 ok( ret || broken(!ret), /* win9x */
648 "GetGUIThreadInfo failed without message queue\n" );
649 SetLastError( 0xdeadbeef );
650 info.cbSize = sizeof(info) + 1;
651 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info );
652 ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" );
653 ok( GetLastError() == ERROR_INVALID_PARAMETER ||
654 broken(GetLastError() == 0xdeadbeef), /* win9x */
655 "wrong error %u\n", GetLastError() );
658 PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */
661 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
662 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
663 ok( count == 0, "count should be 0 got %d\n", count );
665 hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP,
666 0, 0, 100, 100, 0, 0, 0, NULL );
668 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
669 ok( ret, "EnumThreadWindows should have returned TRUE\n" );
670 if (count != 2) /* Vista gives us two windows for the price of one */
672 ok( count == 1, "count should be 1 got %d\n", count );
673 hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP,
674 0, 0, 100, 100, 0, 0, 0, NULL );
678 hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP,
679 0, 0, 100, 100, 0, 0, 0, NULL );
681 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count );
682 ok( !ret, "EnumThreadWindows should have returned FALSE\n" );
683 ok( count == 3, "count should be 3 got %d\n", count );
685 if (hwnd[2]) DestroyWindow(hwnd[2]);
686 DestroyWindow(hwnd[1]);
687 DestroyWindow(hwnd[0]);
691 /* test EnumThreadWindows in a separate thread */
692 static void test_enum_thread_windows(void)
695 HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id );
696 ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" );
697 CloseHandle( handle );
700 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
704 case WM_GETMINMAXINFO:
706 MINMAXINFO* minmax = (MINMAXINFO *)lparam;
708 trace("WM_GETMINMAXINFO: hwnd %p, %08lx, %08lx\n", hwnd, wparam, lparam);
709 dump_minmax_info( minmax );
710 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
713 case WM_WINDOWPOSCHANGING:
715 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
716 trace("main: WM_WINDOWPOSCHANGING %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
717 winpos->hwnd, winpos->hwndInsertAfter,
718 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
719 if (!(winpos->flags & SWP_NOMOVE))
721 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
722 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
724 /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */
725 if (!(winpos->flags & SWP_NOSIZE) && !is_win9x)
727 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
728 winpos->cx == 32768, /* win7 doesn't truncate */
729 "bad winpos->cx %d\n", winpos->cx);
730 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
731 winpos->cy == 40000, /* win7 doesn't truncate */
732 "bad winpos->cy %d\n", winpos->cy);
736 case WM_WINDOWPOSCHANGED:
739 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
740 trace("main: WM_WINDOWPOSCHANGED %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
741 winpos->hwnd, winpos->hwndInsertAfter,
742 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
743 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x);
744 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y);
746 ok((winpos->cx >= 0 && winpos->cx <= 32767) ||
747 winpos->cx == 32768, /* win7 doesn't truncate */
748 "bad winpos->cx %d\n", winpos->cx);
749 ok((winpos->cy >= 0 && winpos->cy <= 32767) ||
750 winpos->cy == 40000, /* win7 doesn't truncate */
751 "bad winpos->cy %d\n", winpos->cy);
753 GetWindowRect(hwnd, &rc1);
754 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
755 /* note: winpos coordinates are relative to parent */
756 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
759 /* Uncomment this once the test succeeds in all cases */
760 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
761 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
763 GetClientRect(hwnd, &rc2);
764 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
765 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
766 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
767 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom );
773 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
774 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
776 trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
777 if (got_getminmaxinfo)
778 trace("%p got WM_GETMINMAXINFO\n", hwnd);
780 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
781 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
783 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
787 if (test_lbuttondown_flag)
789 ShowWindow((HWND)wparam, SW_SHOW);
790 flush_events( FALSE );
795 return DefWindowProcA(hwnd, msg, wparam, lparam);
798 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
802 case WM_GETMINMAXINFO:
804 MINMAXINFO* minmax = (MINMAXINFO *)lparam;
806 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
807 dump_minmax_info( minmax );
808 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021);
813 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021;
814 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
816 trace("WM_NCCREATE: hwnd %p, parent %p, style %08x\n", hwnd, cs->hwndParent, cs->style);
817 if (got_getminmaxinfo)
818 trace("%p got WM_GETMINMAXINFO\n", hwnd);
820 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
821 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n");
823 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n");
828 return DefWindowProcA(hwnd, msg, wparam, lparam);
831 static BOOL RegisterWindowClasses(void)
835 cls.style = CS_DBLCLKS;
836 cls.lpfnWndProc = main_window_procA;
839 cls.hInstance = GetModuleHandleA(0);
841 cls.hCursor = LoadCursorA(0, IDC_ARROW);
842 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
843 cls.lpszMenuName = NULL;
844 cls.lpszClassName = "MainWindowClass";
846 if(!RegisterClassA(&cls)) return FALSE;
849 cls.lpfnWndProc = tool_window_procA;
852 cls.hInstance = GetModuleHandleA(0);
854 cls.hCursor = LoadCursorA(0, IDC_ARROW);
855 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
856 cls.lpszMenuName = NULL;
857 cls.lpszClassName = "ToolWindowClass";
859 if(!RegisterClassA(&cls)) return FALSE;
864 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info)
866 RECT rcWindow, rcClient;
869 ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook);
871 GetWindowRect(hwnd, &rcWindow);
872 ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook);
874 GetClientRect(hwnd, &rcClient);
875 /* translate to screen coordinates */
876 MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2);
877 ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook);
879 ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE),
880 "wrong dwStyle: %08x != %08x for %p in hook %s\n",
881 info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook);
882 /* Windows reports some undocumented exstyles in WINDOWINFO, but
883 * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE).
885 ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE),
886 "wrong dwExStyle: %08x != %08x for %p in hook %s\n",
887 info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook);
888 status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0;
889 if (GetForegroundWindow())
890 ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n",
891 info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook);
893 /* win2k and XP return broken border info in GetWindowInfo most of
894 * the time, so there is no point in testing it.
898 ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left),
899 "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left);
900 border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top);
901 ok(info->cyWindowBorders == border,
902 "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border);
904 ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n",
906 ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ ||
907 info->wCreatorVersion == 0x0500 /* Vista */,
908 "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook);
911 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle)
913 AdjustWindowRectEx(rc, style, menu, exstyle);
914 /* AdjustWindowRectEx does not include scroll bars */
915 if (style & WS_VSCROLL)
917 if(exstyle & WS_EX_LEFTSCROLLBAR)
918 rc->left -= GetSystemMetrics(SM_CXVSCROLL);
920 rc->right += GetSystemMetrics(SM_CXVSCROLL);
922 if (style & WS_HSCROLL)
923 rc->bottom += GetSystemMetrics(SM_CYHSCROLL);
926 static void test_nonclient_area(HWND hwnd)
928 DWORD style, exstyle;
929 RECT rc_window, rc_client, rc;
933 style = GetWindowLongA(hwnd, GWL_STYLE);
934 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
935 menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0;
937 GetWindowRect(hwnd, &rc_window);
938 GetClientRect(hwnd, &rc_client);
940 /* avoid some cases when things go wrong */
941 if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) ||
942 rc_window.right > 32768 || rc_window.bottom > 32768) return;
944 CopyRect(&rc, &rc_client);
945 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2);
946 FixedAdjustWindowRectEx(&rc, style, menu, exstyle);
948 ok(EqualRect(&rc, &rc_window),
949 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
950 style, exstyle, menu, rc_window.left, rc_window.top, rc_window.right, rc_window.bottom,
951 rc.left, rc.top, rc.right, rc.bottom);
954 CopyRect(&rc, &rc_window);
955 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
956 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
957 ok(EqualRect(&rc, &rc_client),
958 "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
959 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
960 rc.left, rc.top, rc.right, rc.bottom);
962 /* NULL rectangle shouldn't crash */
963 ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0);
964 ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret);
966 /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */;
970 /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */
971 SetRect(&rc_client, 0, 0, 250, 150);
972 CopyRect(&rc_window, &rc_client);
973 MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2);
974 FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle);
976 CopyRect(&rc, &rc_window);
977 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc);
978 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2);
979 ok(EqualRect(&rc, &rc_client),
980 "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=(%d,%d)-(%d,%d), calc=(%d,%d)-(%d,%d)\n",
981 style, exstyle, menu, rc_client.left, rc_client.top, rc_client.right, rc_client.bottom,
982 rc.left, rc.top, rc.right, rc.bottom);
985 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam)
987 static const char *CBT_code_name[10] = {
998 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown";
999 HWND hwnd = (HWND)wParam;
1003 case HCBT_CREATEWND:
1005 static const RECT rc_null;
1008 CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam;
1009 ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n");
1014 info.cbSize = sizeof(WINDOWINFO);
1015 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1016 verify_window_info(code_name, hwnd, &info);
1019 /* WS_VISIBLE should be turned off yet */
1020 style = createwnd->lpcs->style & ~WS_VISIBLE;
1021 ok(style == GetWindowLongA(hwnd, GWL_STYLE),
1022 "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n",
1023 GetWindowLongA(hwnd, GWL_STYLE), style);
1027 /* Uncomment this once the test succeeds in all cases */
1028 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1030 ok(GetParent(hwnd) == hwndMessage,
1031 "wrong result from GetParent %p: message window %p\n",
1032 GetParent(hwnd), hwndMessage);
1035 ok(!GetParent(hwnd), "GetParent should return 0 at this point\n");
1037 ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n");
1041 /* while NT assigns GW_HWNDFIRST/LAST some values at this point,
1042 * Win9x still has them set to 0.
1044 ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n");
1045 ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n");
1047 ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n");
1048 ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n");
1052 /* Uncomment this once the test succeeds in all cases */
1055 ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n");
1056 ok(pGetAncestor(hwnd, GA_ROOT) == hwnd,
1057 "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd);
1059 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
1060 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage,
1061 "GA_ROOTOWNER should be set to hwndMessage at this point\n");
1063 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd,
1064 "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd);
1067 ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n");
1068 ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n");
1069 ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n");
1070 ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n");
1077 if (pGetWindowInfo && IsWindow(hwnd))
1081 /* Win98 actually does check the info.cbSize and doesn't allow
1082 * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k,
1083 * WinXP do not check it at all.
1085 info.cbSize = sizeof(WINDOWINFO);
1086 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n");
1087 verify_window_info(code_name, hwnd, &info);
1090 /* window state is undefined */
1092 case HCBT_DESTROYWND:
1098 return CallNextHookEx(hhook, nCode, wParam, lParam);
1101 static void test_shell_window(void)
1105 HMODULE hinst, hUser32;
1106 BOOL (WINAPI*SetShellWindow)(HWND);
1107 HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5;
1108 HWND shellWindow, nextWnd;
1112 win_skip("Skipping shell window test on Win9x\n");
1116 shellWindow = GetShellWindow();
1117 hinst = GetModuleHandle(0);
1118 hUser32 = GetModuleHandleA("user32");
1120 SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow");
1122 trace("previous shell window: %p\n", shellWindow);
1128 GetWindowThreadProcessId(shellWindow, &pid);
1129 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
1132 skip( "cannot get access to shell process\n" );
1136 SetLastError(0xdeadbeef);
1137 ret = DestroyWindow(shellWindow);
1138 error = GetLastError();
1140 ok(!ret, "DestroyWindow(shellWindow)\n");
1141 /* passes on Win XP, but not on Win98 */
1142 ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef,
1143 "got %u after DestroyWindow(shellWindow)\n", error);
1145 /* close old shell instance */
1146 ret = TerminateProcess(hProcess, 0);
1147 ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError());
1148 WaitForSingleObject(hProcess, INFINITE); /* wait for termination */
1149 CloseHandle(hProcess);
1152 hwnd1 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0);
1153 trace("created window 1: %p\n", hwnd1);
1155 ret = SetShellWindow(hwnd1);
1156 ok(ret, "first call to SetShellWindow(hwnd1)\n");
1157 shellWindow = GetShellWindow();
1158 ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow);
1160 ret = SetShellWindow(hwnd1);
1161 ok(!ret, "second call to SetShellWindow(hwnd1)\n");
1163 ret = SetShellWindow(0);
1164 error = GetLastError();
1165 /* passes on Win XP, but not on Win98
1166 ok(!ret, "reset shell window by SetShellWindow(0)\n");
1167 ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */
1169 ret = SetShellWindow(hwnd1);
1170 /* passes on Win XP, but not on Win98
1171 ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */
1173 SetWindowLong(hwnd1, GWL_EXSTYLE, GetWindowLong(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST);
1174 ret = GetWindowLong(hwnd1,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE;
1175 ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n");
1177 ret = DestroyWindow(hwnd1);
1178 ok(ret, "DestroyWindow(hwnd1)\n");
1180 hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0);
1181 trace("created window 2: %p\n", hwnd2);
1182 ret = SetShellWindow(hwnd2);
1183 ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n");
1185 hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0);
1186 trace("created window 3: %p\n", hwnd3);
1188 hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0);
1189 trace("created window 4: %p\n", hwnd4);
1191 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1192 ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd);
1194 ret = SetShellWindow(hwnd4);
1195 ok(ret, "SetShellWindow(hwnd4)\n");
1196 shellWindow = GetShellWindow();
1197 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1199 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1200 ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd);
1202 ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1203 ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n");
1205 ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1206 ok(ret, "SetWindowPos(hwnd4, hwnd3\n");
1208 ret = SetShellWindow(hwnd3);
1209 ok(!ret, "SetShellWindow(hwnd3)\n");
1210 shellWindow = GetShellWindow();
1211 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow);
1213 hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0);
1214 trace("created window 5: %p\n", hwnd5);
1215 ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
1216 ok(ret, "SetWindowPos(hwnd4, hwnd5)\n");
1220 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT);
1221 ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd);
1224 /* destroy test windows */
1225 DestroyWindow(hwnd2);
1226 DestroyWindow(hwnd3);
1227 DestroyWindow(hwnd4);
1228 DestroyWindow(hwnd5);
1231 /************** MDI test ****************/
1233 static char mdi_lParam_test_message[] = "just a test string";
1235 static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id)
1237 MDICREATESTRUCTA mdi_cs;
1240 static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0};
1241 static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0};
1242 BOOL isWin9x = FALSE;
1244 mdi_cs.szClass = "MDI_child_Class_1";
1245 mdi_cs.szTitle = "MDI child";
1246 mdi_cs.hOwner = GetModuleHandle(0);
1247 mdi_cs.x = CW_USEDEFAULT;
1248 mdi_cs.y = CW_USEDEFAULT;
1249 mdi_cs.cx = CW_USEDEFAULT;
1250 mdi_cs.cy = CW_USEDEFAULT;
1252 mdi_cs.lParam = (LPARAM)mdi_lParam_test_message;
1253 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1254 ok(mdi_child != 0, "MDI child creation failed\n");
1255 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1256 ok(id == first_id, "wrong child id %ld\n", id);
1257 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1258 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1260 mdi_cs.style = 0x7fffffff; /* without WS_POPUP */
1261 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1262 ok(mdi_child != 0, "MDI child creation failed\n");
1263 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1264 ok(id == first_id, "wrong child id %ld\n", id);
1265 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1266 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1268 mdi_cs.style = 0xffffffff; /* with WS_POPUP */
1269 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1270 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1272 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1276 ok(mdi_child != 0, "MDI child creation failed\n");
1277 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1278 ok(id == first_id, "wrong child id %ld\n", id);
1279 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1280 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1283 /* test MDICREATESTRUCT A<->W mapping */
1284 /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */
1286 mdi_cs.szClass = (LPCSTR)classW;
1287 mdi_cs.szTitle = (LPCSTR)titleW;
1288 SetLastError(0xdeadbeef);
1289 mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs);
1292 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1295 ok(mdi_child != 0, "MDI child creation failed\n");
1299 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1300 ok(id == first_id, "wrong child id %ld\n", id);
1301 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1302 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1305 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1307 CW_USEDEFAULT, CW_USEDEFAULT,
1308 CW_USEDEFAULT, CW_USEDEFAULT,
1309 mdi_client, GetModuleHandle(0),
1310 (LPARAM)mdi_lParam_test_message);
1311 ok(mdi_child != 0, "MDI child creation failed\n");
1312 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1313 ok(id == first_id, "wrong child id %ld\n", id);
1314 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1315 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1317 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1318 0x7fffffff, /* without WS_POPUP */
1319 CW_USEDEFAULT, CW_USEDEFAULT,
1320 CW_USEDEFAULT, CW_USEDEFAULT,
1321 mdi_client, GetModuleHandle(0),
1322 (LPARAM)mdi_lParam_test_message);
1323 ok(mdi_child != 0, "MDI child creation failed\n");
1324 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1325 ok(id == first_id, "wrong child id %ld\n", id);
1326 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1327 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1329 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child",
1330 0xffffffff, /* with WS_POPUP */
1331 CW_USEDEFAULT, CW_USEDEFAULT,
1332 CW_USEDEFAULT, CW_USEDEFAULT,
1333 mdi_client, GetModuleHandle(0),
1334 (LPARAM)mdi_lParam_test_message);
1335 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1337 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1341 ok(mdi_child != 0, "MDI child creation failed\n");
1342 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1343 ok(id == first_id, "wrong child id %ld\n", id);
1344 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1345 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1348 /* test MDICREATESTRUCT A<->W mapping */
1349 SetLastError(0xdeadbeef);
1350 mdi_child = CreateMDIWindowW(classW, titleW,
1352 CW_USEDEFAULT, CW_USEDEFAULT,
1353 CW_USEDEFAULT, CW_USEDEFAULT,
1354 mdi_client, GetModuleHandle(0),
1355 (LPARAM)mdi_lParam_test_message);
1358 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1361 ok(mdi_child != 0, "MDI child creation failed\n");
1365 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1366 ok(id == first_id, "wrong child id %ld\n", id);
1367 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1368 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1371 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1373 CW_USEDEFAULT, CW_USEDEFAULT,
1374 CW_USEDEFAULT, CW_USEDEFAULT,
1375 mdi_client, 0, GetModuleHandle(0),
1376 mdi_lParam_test_message);
1377 ok(mdi_child != 0, "MDI child creation failed\n");
1378 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1379 ok(id == first_id, "wrong child id %ld\n", id);
1380 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1381 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1383 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1384 0x7fffffff, /* without WS_POPUP */
1385 CW_USEDEFAULT, CW_USEDEFAULT,
1386 CW_USEDEFAULT, CW_USEDEFAULT,
1387 mdi_client, 0, GetModuleHandle(0),
1388 mdi_lParam_test_message);
1389 ok(mdi_child != 0, "MDI child creation failed\n");
1390 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1391 ok(id == first_id, "wrong child id %ld\n", id);
1392 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1393 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1395 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child",
1396 0xffffffff, /* with WS_POPUP */
1397 CW_USEDEFAULT, CW_USEDEFAULT,
1398 CW_USEDEFAULT, CW_USEDEFAULT,
1399 mdi_client, 0, GetModuleHandle(0),
1400 mdi_lParam_test_message);
1401 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1403 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n");
1407 ok(mdi_child != 0, "MDI child creation failed\n");
1408 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1409 ok(id == first_id, "wrong child id %ld\n", id);
1410 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1411 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1414 /* test MDICREATESTRUCT A<->W mapping */
1415 SetLastError(0xdeadbeef);
1416 mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW,
1418 CW_USEDEFAULT, CW_USEDEFAULT,
1419 CW_USEDEFAULT, CW_USEDEFAULT,
1420 mdi_client, 0, GetModuleHandle(0),
1421 mdi_lParam_test_message);
1424 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1427 ok(mdi_child != 0, "MDI child creation failed\n");
1431 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1432 ok(id == first_id, "wrong child id %ld\n", id);
1433 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0);
1434 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n");
1437 /* This test fails on Win9x */
1440 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child",
1442 CW_USEDEFAULT, CW_USEDEFAULT,
1443 CW_USEDEFAULT, CW_USEDEFAULT,
1444 parent, 0, GetModuleHandle(0),
1445 mdi_lParam_test_message);
1446 ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n");
1449 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1450 WS_CHILD, /* without WS_POPUP */
1451 CW_USEDEFAULT, CW_USEDEFAULT,
1452 CW_USEDEFAULT, CW_USEDEFAULT,
1453 mdi_client, 0, GetModuleHandle(0),
1454 mdi_lParam_test_message);
1455 ok(mdi_child != 0, "MDI child creation failed\n");
1456 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1457 ok(id == 0, "wrong child id %ld\n", id);
1458 DestroyWindow(mdi_child);
1460 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1461 WS_CHILD | WS_POPUP, /* with WS_POPUP */
1462 CW_USEDEFAULT, CW_USEDEFAULT,
1463 CW_USEDEFAULT, CW_USEDEFAULT,
1464 mdi_client, 0, GetModuleHandle(0),
1465 mdi_lParam_test_message);
1466 ok(mdi_child != 0, "MDI child creation failed\n");
1467 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1468 ok(id == 0, "wrong child id %ld\n", id);
1469 DestroyWindow(mdi_child);
1471 /* maximized child */
1472 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1473 WS_CHILD | WS_MAXIMIZE,
1474 CW_USEDEFAULT, CW_USEDEFAULT,
1475 CW_USEDEFAULT, CW_USEDEFAULT,
1476 mdi_client, 0, GetModuleHandle(0),
1477 mdi_lParam_test_message);
1478 ok(mdi_child != 0, "MDI child creation failed\n");
1479 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1480 ok(id == 0, "wrong child id %ld\n", id);
1481 DestroyWindow(mdi_child);
1483 trace("Creating maximized child with a caption\n");
1484 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1485 WS_CHILD | WS_MAXIMIZE | WS_CAPTION,
1486 CW_USEDEFAULT, CW_USEDEFAULT,
1487 CW_USEDEFAULT, CW_USEDEFAULT,
1488 mdi_client, 0, GetModuleHandle(0),
1489 mdi_lParam_test_message);
1490 ok(mdi_child != 0, "MDI child creation failed\n");
1491 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1492 ok(id == 0, "wrong child id %ld\n", id);
1493 DestroyWindow(mdi_child);
1495 trace("Creating maximized child with a caption and a thick frame\n");
1496 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child",
1497 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME,
1498 CW_USEDEFAULT, CW_USEDEFAULT,
1499 CW_USEDEFAULT, CW_USEDEFAULT,
1500 mdi_client, 0, GetModuleHandle(0),
1501 mdi_lParam_test_message);
1502 ok(mdi_child != 0, "MDI child creation failed\n");
1503 id = GetWindowLongPtrA(mdi_child, GWLP_ID);
1504 ok(id == 0, "wrong child id %ld\n", id);
1505 DestroyWindow(mdi_child);
1508 /**********************************************************************
1509 * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c)
1511 * Note: The rule here is that client rect of the maximized MDI child
1512 * is equal to the client rect of the MDI client window.
1514 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax )
1518 GetClientRect( client, &rect );
1519 AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ),
1520 0, GetWindowLongA( hwnd, GWL_EXSTYLE ));
1522 rect.right -= rect.left;
1523 rect.bottom -= rect.top;
1524 lpMinMax->ptMaxSize.x = rect.right;
1525 lpMinMax->ptMaxSize.y = rect.bottom;
1527 lpMinMax->ptMaxPosition.x = rect.left;
1528 lpMinMax->ptMaxPosition.y = rect.top;
1530 trace("max rect (%d,%d - %d, %d)\n",
1531 rect.left, rect.top, rect.right, rect.bottom);
1534 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1541 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1542 MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams;
1544 ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n");
1545 ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n");
1547 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n");
1548 ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n");
1549 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1550 ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n");
1551 ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner);
1553 /* MDICREATESTRUCT should have original values */
1554 ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff,
1555 "mdi_cs->style does not match (%08x)\n", mdi_cs->style);
1556 ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x);
1557 ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y);
1558 ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx);
1559 ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy);
1561 /* CREATESTRUCT should have fixed values */
1562 ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);
1563 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1565 /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */
1566 ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx);
1567 ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy);
1569 ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n");
1571 if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
1573 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS;
1574 ok(cs->style == style,
1575 "cs->style does not match (%08x)\n", cs->style);
1579 LONG style = mdi_cs->style;
1581 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
1582 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
1583 ok(cs->style == style,
1584 "cs->style does not match (%08x)\n", cs->style);
1589 case WM_GETMINMAXINFO:
1591 HWND client = GetParent(hwnd);
1593 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1594 MINMAXINFO my_minmax;
1595 LONG style, exstyle;
1597 style = GetWindowLongA(hwnd, GWL_STYLE);
1598 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1600 GetWindowRect(client, &rc);
1601 trace("MDI client %p window size = (%d x %d)\n", client, rc.right-rc.left, rc.bottom-rc.top);
1602 GetClientRect(client, &rc);
1603 trace("MDI client %p client size = (%d x %d)\n", client, rc.right, rc.bottom);
1604 trace("screen size: %d x %d\n", GetSystemMetrics(SM_CXSCREEN),
1605 GetSystemMetrics(SM_CYSCREEN));
1607 GetClientRect(client, &rc);
1608 if ((style & WS_CAPTION) == WS_CAPTION)
1609 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1610 AdjustWindowRectEx(&rc, style, 0, exstyle);
1611 trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top);
1612 dump_minmax_info( minmax );
1614 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1615 minmax->ptMaxSize.x, rc.right - rc.left);
1616 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1617 minmax->ptMaxSize.y, rc.bottom - rc.top);
1619 DefMDIChildProcA(hwnd, msg, wparam, lparam);
1621 trace("DefMDIChildProc returned:\n");
1622 dump_minmax_info( minmax );
1624 MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax);
1625 ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n",
1626 minmax->ptMaxSize.x, my_minmax.ptMaxSize.x);
1627 ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n",
1628 minmax->ptMaxSize.y, my_minmax.ptMaxSize.y);
1633 case WM_MDIACTIVATE:
1635 HWND active, client = GetParent(hwnd);
1636 /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/
1637 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0);
1638 if (hwnd == (HWND)lparam) /* if we are being activated */
1639 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active);
1641 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active);
1645 return DefMDIChildProcA(hwnd, msg, wparam, lparam);
1648 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1655 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam;
1657 trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE",
1658 cs->x, cs->y, cs->cx, cs->cy);
1660 ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n");
1661 ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n");
1663 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n");
1664 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n");
1666 /* CREATESTRUCT should have fixed values */
1667 /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT,
1669 /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/
1670 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y);
1672 /* cx/cy == CW_USEDEFAULT are translated to 0 */
1673 /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT,
1674 while Win95, Win2k, WinXP do. */
1675 /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/
1676 ok(cs->cy == 0, "%d != 0\n", cs->cy);
1680 case WM_GETMINMAXINFO:
1682 HWND parent = GetParent(hwnd);
1684 MINMAXINFO *minmax = (MINMAXINFO *)lparam;
1685 LONG style, exstyle;
1687 style = GetWindowLongA(hwnd, GWL_STYLE);
1688 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE);
1690 GetClientRect(parent, &rc);
1691 trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom);
1693 GetClientRect(parent, &rc);
1694 if ((style & WS_CAPTION) == WS_CAPTION)
1695 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
1696 AdjustWindowRectEx(&rc, style, 0, exstyle);
1697 dump_minmax_info( minmax );
1699 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n",
1700 minmax->ptMaxSize.x, rc.right - rc.left);
1701 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n",
1702 minmax->ptMaxSize.y, rc.bottom - rc.top);
1706 case WM_WINDOWPOSCHANGED:
1708 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1711 GetWindowRect(hwnd, &rc1);
1712 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1713 /* note: winpos coordinates are relative to parent */
1714 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1715 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) pos=(%d,%d)-(%d,%d)\n",
1716 rc1.left, rc1.top, rc1.right, rc1.bottom,
1717 rc2.left, rc2.top, rc2.right, rc2.bottom);
1718 GetWindowRect(hwnd, &rc1);
1719 GetClientRect(hwnd, &rc2);
1720 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1721 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1722 ok(EqualRect(&rc1, &rc2), "rects do not match, window=(%d,%d)-(%d,%d) client=(%d,%d)-(%d,%d)\n",
1723 rc1.left, rc1.top, rc1.right, rc1.bottom,
1724 rc2.left, rc2.top, rc2.right, rc2.bottom);
1727 case WM_WINDOWPOSCHANGING:
1729 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1730 WINDOWPOS my_winpos = *winpos;
1732 trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1733 (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED",
1734 winpos->hwnd, winpos->hwndInsertAfter,
1735 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1737 DefWindowProcA(hwnd, msg, wparam, lparam);
1739 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1740 "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1741 winpos->hwnd, winpos->hwndInsertAfter,
1742 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1747 return DefWindowProcA(hwnd, msg, wparam, lparam);
1750 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1752 static HWND mdi_client;
1758 CLIENTCREATESTRUCT client_cs;
1761 GetClientRect(hwnd, &rc);
1763 client_cs.hWindowMenu = 0;
1764 client_cs.idFirstChild = 1;
1766 /* MDIClient without MDIS_ALLCHILDSTYLES */
1767 mdi_client = CreateWindowExA(0, "mdiclient",
1769 WS_CHILD /*| WS_VISIBLE*/,
1770 /* tests depend on a not zero MDIClient size */
1771 0, 0, rc.right, rc.bottom,
1772 hwnd, 0, GetModuleHandle(0),
1775 test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
1776 DestroyWindow(mdi_client);
1778 /* MDIClient with MDIS_ALLCHILDSTYLES */
1779 mdi_client = CreateWindowExA(0, "mdiclient",
1781 WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/,
1782 /* tests depend on a not zero MDIClient size */
1783 0, 0, rc.right, rc.bottom,
1784 hwnd, 0, GetModuleHandle(0),
1787 test_MDI_create(hwnd, mdi_client, client_cs.idFirstChild);
1788 DestroyWindow(mdi_client);
1792 case WM_WINDOWPOSCHANGED:
1794 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1797 GetWindowRect(hwnd, &rc1);
1798 trace("window: (%d,%d)-(%d,%d)\n", rc1.left, rc1.top, rc1.right, rc1.bottom);
1799 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy);
1800 /* note: winpos coordinates are relative to parent */
1801 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2);
1802 trace("pos: (%d,%d)-(%d,%d)\n", rc2.left, rc2.top, rc2.right, rc2.bottom);
1803 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1805 GetWindowRect(hwnd, &rc1);
1806 GetClientRect(hwnd, &rc2);
1807 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1);
1808 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2);
1809 ok(EqualRect(&rc1, &rc2), "rects do not match\n");
1812 case WM_WINDOWPOSCHANGING:
1814 WINDOWPOS *winpos = (WINDOWPOS *)lparam;
1815 WINDOWPOS my_winpos = *winpos;
1817 trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED");
1818 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1819 winpos->hwnd, winpos->hwndInsertAfter,
1820 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1822 DefWindowProcA(hwnd, msg, wparam, lparam);
1824 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n",
1825 winpos->hwnd, winpos->hwndInsertAfter,
1826 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags);
1828 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)),
1829 "DefWindowProc should not change WINDOWPOS values\n");
1838 return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam);
1841 static BOOL mdi_RegisterWindowClasses(void)
1846 cls.lpfnWndProc = mdi_main_wnd_procA;
1849 cls.hInstance = GetModuleHandleA(0);
1851 cls.hCursor = LoadCursorA(0, IDC_ARROW);
1852 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1853 cls.lpszMenuName = NULL;
1854 cls.lpszClassName = "MDI_parent_Class";
1855 if(!RegisterClassA(&cls)) return FALSE;
1857 cls.lpfnWndProc = mdi_child_wnd_proc_1;
1858 cls.lpszClassName = "MDI_child_Class_1";
1859 if(!RegisterClassA(&cls)) return FALSE;
1861 cls.lpfnWndProc = mdi_child_wnd_proc_2;
1862 cls.lpszClassName = "MDI_child_Class_2";
1863 if(!RegisterClassA(&cls)) return FALSE;
1868 static void test_mdi(void)
1873 if (!mdi_RegisterWindowClasses()) assert(0);
1875 mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window",
1876 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
1877 WS_MAXIMIZEBOX /*| WS_VISIBLE*/,
1878 100, 100, CW_USEDEFAULT, CW_USEDEFAULT,
1879 GetDesktopWindow(), 0,
1880 GetModuleHandle(0), NULL);
1881 assert(mdi_hwndMain);
1883 while(GetMessage(&msg, 0, 0, 0))
1885 TranslateMessage(&msg);
1886 DispatchMessage(&msg);
1889 DestroyWindow(mdi_hwndMain);
1892 static void test_icons(void)
1896 HICON icon = LoadIconA(0, IDI_APPLICATION);
1897 HICON icon2 = LoadIconA(0, IDI_QUESTION);
1898 HICON small_icon = LoadImageA(0, IDI_APPLICATION, IMAGE_ICON,
1899 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
1902 cls.cbSize = sizeof(cls);
1904 cls.lpfnWndProc = DefWindowProcA;
1908 cls.hIcon = LoadIconA(0, IDI_HAND);
1909 cls.hIconSm = small_icon;
1910 cls.hCursor = LoadCursorA(0, IDC_ARROW);
1911 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
1912 cls.lpszMenuName = NULL;
1913 cls.lpszClassName = "IconWindowClass";
1915 RegisterClassExA(&cls);
1917 hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0,
1918 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL);
1921 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1922 ok( res == 0, "wrong big icon %p/0\n", res );
1923 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
1924 ok( res == 0, "wrong previous big icon %p/0\n", res );
1925 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1926 ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
1927 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
1928 ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
1929 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1930 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1932 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1933 ok( res == 0, "wrong small icon %p/0\n", res );
1934 /* this test is XP specific */
1935 /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1936 ok( res != 0, "wrong small icon %p\n", res );*/
1937 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
1938 ok( res == 0, "wrong previous small icon %p/0\n", res );
1939 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1940 ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
1941 /* this test is XP specific */
1942 /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1943 ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );*/
1944 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
1945 ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
1946 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
1947 ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
1948 /* this test is XP specific */
1949 /*res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
1950 ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );*/
1952 /* make sure the big icon hasn't changed */
1953 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
1954 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
1956 DestroyWindow( hwnd );
1959 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1961 if (msg == WM_NCCALCSIZE)
1963 RECT *rect = (RECT *)lparam;
1964 /* first time around increase the rectangle, next time decrease it */
1965 if (rect->left == 100) InflateRect( rect, 10, 10 );
1966 else InflateRect( rect, -10, -10 );
1969 return DefWindowProc( hwnd, msg, wparam, lparam );
1972 static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
1974 RECT orig_win_rc, rect;
1976 HWND hwnd_grandchild, hwnd_child, hwnd_child2;
1981 SetRect(&rect, 111, 222, 333, 444);
1982 ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
1983 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
1984 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
1986 SetRect(&rect, 111, 222, 333, 444);
1987 ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n");
1988 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444,
1989 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
1991 GetWindowRect(hwnd, &orig_win_rc);
1993 old_proc = SetWindowLongPtr( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
1994 ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
1995 ok(ret, "Got %d\n", ret);
1996 GetWindowRect( hwnd, &rect );
1997 ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
1998 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
1999 GetClientRect( hwnd, &rect );
2000 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2001 ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
2002 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2004 ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
2005 ok(ret, "Got %d\n", ret);
2006 GetWindowRect( hwnd, &rect );
2007 ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
2008 "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2009 GetClientRect( hwnd, &rect );
2010 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 );
2011 ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
2012 "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
2014 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2015 orig_win_rc.right, orig_win_rc.bottom, 0);
2016 ok(ret, "Got %d\n", ret);
2017 SetWindowLongPtr( hwnd, GWLP_WNDPROC, old_proc );
2019 /* Win9x truncates coordinates to 16-bit irrespectively */
2022 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
2023 ok(ret, "Got %d\n", ret);
2024 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
2025 ok(ret, "Got %d\n", ret);
2027 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
2028 ok(ret, "Got %d\n", ret);
2029 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
2030 ok(ret, "Got %d\n", ret);
2033 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
2034 orig_win_rc.right, orig_win_rc.bottom, 0);
2035 ok(ret, "Got %d\n", ret);
2037 ok(!(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2038 ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2039 ok(ret, "Got %d\n", ret);
2040 ok(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2041 ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2042 ok(ret, "Got %d\n", ret);
2043 ok(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
2044 ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
2045 ok(ret, "Got %d\n", ret);
2046 ok(!(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
2048 hwnd_desktop = GetDesktopWindow();
2049 ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
2050 hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2051 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2052 hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child);
2053 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
2054 hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
2055 ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError());
2057 ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2058 ok(ret, "Got %d\n", ret);
2059 check_active_state(hwnd, hwnd, hwnd);
2061 ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2062 ok(ret, "Got %d\n", ret);
2063 check_active_state(hwnd2, hwnd2, hwnd2);
2065 /* Returns TRUE also for windows that are not siblings */
2066 ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2067 ok(ret, "Got %d\n", ret);
2068 check_active_state(hwnd2, hwnd2, hwnd2);
2070 ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2071 ok(ret, "Got %d\n", ret);
2072 check_active_state(hwnd2, hwnd2, hwnd2);
2074 /* Does not seem to do anything even without passing flags, still returns TRUE */
2075 GetWindowRect(hwnd_child, &rc1);
2076 ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0);
2077 ok(ret, "Got %d\n", ret);
2078 GetWindowRect(hwnd_child, &rc2);
2079 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2080 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2081 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2082 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2083 check_active_state(hwnd2, hwnd2, hwnd2);
2085 /* Same thing the other way around. */
2086 GetWindowRect(hwnd2, &rc1);
2087 ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0);
2088 ok(ret, "Got %d\n", ret);
2089 GetWindowRect(hwnd2, &rc2);
2090 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2091 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2092 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2093 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2094 check_active_state(hwnd2, hwnd2, hwnd2);
2096 /* .. and with these windows. */
2097 GetWindowRect(hwnd_grandchild, &rc1);
2098 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0);
2099 ok(ret, "Got %d\n", ret);
2100 GetWindowRect(hwnd_grandchild, &rc2);
2101 ok(rc1.left == rc2.left && rc1.top == rc2.top &&
2102 rc1.right == rc2.right && rc1.bottom == rc2.bottom,
2103 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2104 rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
2105 check_active_state(hwnd2, hwnd2, hwnd2);
2107 /* Add SWP_NOZORDER and it will be properly resized. */
2108 GetWindowRect(hwnd_grandchild, &rc1);
2109 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER);
2110 ok(ret, "Got %d\n", ret);
2111 GetWindowRect(hwnd_grandchild, &rc2);
2112 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2113 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2114 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2115 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2116 check_active_state(hwnd2, hwnd2, hwnd2);
2118 /* Given a sibling window, the window is properly resized. */
2119 GetWindowRect(hwnd_child, &rc1);
2120 ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0);
2121 ok(ret, "Got %d\n", ret);
2122 GetWindowRect(hwnd_child, &rc2);
2123 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top &&
2124 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom,
2125 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2126 rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom);
2127 check_active_state(hwnd2, hwnd2, hwnd2);
2129 /* Involving the desktop window changes things. */
2130 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2131 ok(!ret, "Got %d\n", ret);
2132 check_active_state(hwnd2, hwnd2, hwnd2);
2134 GetWindowRect(hwnd_child, &rc1);
2135 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
2136 ok(!ret, "Got %d\n", ret);
2137 GetWindowRect(hwnd_child, &rc2);
2138 ok(rc1.top == rc2.top && rc1.left == rc2.left &&
2139 rc1.bottom == rc2.bottom && rc1.right == rc2.right,
2140 "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
2141 rc1.top, rc1.left, rc1.bottom, rc1.right, rc2.top, rc2.left, rc2.bottom, rc2.right);
2142 check_active_state(hwnd2, hwnd2, hwnd2);
2144 ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2145 ok(!ret, "Got %d\n", ret);
2146 check_active_state(hwnd2, hwnd2, hwnd2);
2148 ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2149 ok(!ret, "Got %d\n", ret);
2150 check_active_state(hwnd2, hwnd2, hwnd2);
2152 ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
2153 ok(!ret, "Got %d\n", ret);
2154 check_active_state(hwnd2, hwnd2, hwnd2);
2156 DestroyWindow(hwnd_grandchild);
2157 DestroyWindow(hwnd_child);
2158 DestroyWindow(hwnd_child2);
2161 static void test_SetMenu(HWND parent)
2168 hMenu = CreateMenu();
2171 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2174 /* fails on (at least) Wine, NT4, XP SP2 */
2175 test_nonclient_area(parent);
2177 ret = GetMenu(parent);
2178 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2179 /* test whether we can destroy a menu assigned to a window */
2180 retok = DestroyMenu(hMenu);
2181 ok( retok, "DestroyMenu error %d\n", GetLastError());
2182 retok = IsMenu(hMenu);
2183 ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n");
2184 ret = GetMenu(parent);
2185 /* This test fails on Win9x */
2187 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2188 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2189 test_nonclient_area(parent);
2191 hMenu = CreateMenu();
2195 ret = GetMenu(parent);
2196 ok(ret == 0, "unexpected menu id %p\n", ret);
2198 ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2199 test_nonclient_area(parent);
2200 ret = GetMenu(parent);
2201 ok(ret == 0, "unexpected menu id %p\n", ret);
2203 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n");
2206 /* fails on (at least) Wine, NT4, XP SP2 */
2207 test_nonclient_area(parent);
2209 ret = GetMenu(parent);
2210 ok(ret == hMenu, "unexpected menu id %p\n", ret);
2212 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n");
2213 test_nonclient_area(parent);
2214 ret = GetMenu(parent);
2215 ok(ret == 0, "unexpected menu id %p\n", ret);
2218 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL);
2221 ret = GetMenu(child);
2222 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2224 ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n");
2225 test_nonclient_area(child);
2226 ret = GetMenu(child);
2227 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2229 ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n");
2230 test_nonclient_area(child);
2231 ret = GetMenu(child);
2232 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2234 ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n");
2235 test_nonclient_area(child);
2236 ret = GetMenu(child);
2237 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret);
2239 style = GetWindowLong(child, GWL_STYLE);
2240 SetWindowLong(child, GWL_STYLE, style | WS_POPUP);
2241 ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n");
2242 ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n");
2243 SetWindowLong(child, GWL_STYLE, style);
2245 SetWindowLong(child, GWL_STYLE, style | WS_OVERLAPPED);
2246 ok(!SetMenu(child, hMenu), "SetMenu on a overlapped child window should fail\n");
2247 SetWindowLong(child, GWL_STYLE, style);
2249 DestroyWindow(child);
2253 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total)
2255 HWND child[5], hwnd;
2260 hwnd = GetWindow(parent, GW_CHILD);
2261 ok(!hwnd, "have to start without children to perform the test\n");
2263 for (i = 0; i < total; i++)
2265 if (style[i] & DS_CONTROL)
2267 child[i] = CreateWindowExA(0, MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE,
2268 0,0,0,0, parent, (HMENU)i, 0, NULL);
2269 if (style[i] & WS_VISIBLE)
2270 ShowWindow(child[i], SW_SHOW);
2272 SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE);
2275 child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10,
2276 parent, (HMENU)i, 0, NULL);
2277 trace("child[%ld] = %p\n", i, child[i]);
2278 ok(child[i] != 0, "CreateWindowEx failed to create child window\n");
2281 hwnd = GetWindow(parent, GW_CHILD);
2282 ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n");
2283 ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n");
2284 ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n");
2286 for (i = 0; i < total; i++)
2288 trace("hwnd[%ld] = %p\n", i, hwnd);
2289 ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i);
2291 hwnd = GetWindow(hwnd, GW_HWNDNEXT);
2294 for (i = 0; i < total; i++)
2295 ok(DestroyWindow(child[i]), "DestroyWindow failed\n");
2298 static void test_children_zorder(HWND parent)
2300 const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD,
2302 const int simple_order[5] = { 0, 1, 2, 3, 4 };
2304 const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE,
2305 WS_CHILD | WS_VISIBLE, WS_CHILD,
2306 WS_CHILD | WS_MAXIMIZE | WS_VISIBLE };
2307 const int complex_order_1[1] = { 0 };
2308 const int complex_order_2[2] = { 1, 0 };
2309 const int complex_order_3[3] = { 1, 0, 2 };
2310 const int complex_order_4[4] = { 1, 0, 2, 3 };
2311 const int complex_order_5[5] = { 4, 1, 0, 2, 3 };
2312 const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE,
2313 WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE,
2314 WS_CHILD | WS_VISIBLE };
2315 const int complex_order_6[3] = { 0, 1, 2 };
2317 /* simple WS_CHILD */
2318 test_window_tree(parent, simple_style, simple_order, 5);
2320 /* complex children styles */
2321 test_window_tree(parent, complex_style, complex_order_1, 1);
2322 test_window_tree(parent, complex_style, complex_order_2, 2);
2323 test_window_tree(parent, complex_style, complex_order_3, 3);
2324 test_window_tree(parent, complex_style, complex_order_4, 4);
2325 test_window_tree(parent, complex_style, complex_order_5, 5);
2327 /* another set of complex children styles */
2328 test_window_tree(parent, complex_style_6, complex_order_6, 3);
2331 #define check_z_order(hwnd, next, prev, owner, topmost) \
2332 check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \
2335 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner,
2336 BOOL topmost, const char *file, int line)
2341 test = GetWindow(hwnd, GW_HWNDNEXT);
2342 /* skip foreign windows */
2343 while (test && test != next &&
2344 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2345 UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0) ||
2346 GetWindow(test, GW_OWNER) == next))
2348 /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2349 test = GetWindow(test, GW_HWNDNEXT);
2351 ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test);
2353 test = GetWindow(hwnd, GW_HWNDPREV);
2354 /* skip foreign windows */
2355 while (test && test != prev &&
2356 (GetWindowThreadProcessId(test, NULL) != our_pid ||
2357 UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)) != GetModuleHandle(0) ||
2358 GetWindow(test, GW_OWNER) == hwnd))
2360 /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/
2361 test = GetWindow(test, GW_HWNDPREV);
2363 ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test);
2365 test = GetWindow(hwnd, GW_OWNER);
2366 ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test);
2368 ex_style = GetWindowLong(hwnd, GWL_EXSTYLE);
2369 ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n",
2370 hwnd, topmost ? "" : "NOT ");
2373 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style)
2375 HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F;
2377 trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E);
2379 SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2381 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2382 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2384 hwnd_F = CreateWindowEx(0, "MainWindowClass", "Owner window",
2385 WS_OVERLAPPED | WS_CAPTION,
2387 0, 0, GetModuleHandle(0), NULL);
2388 trace("hwnd_F %p\n", hwnd_F);
2389 check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE);
2391 SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2392 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2393 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2394 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE);
2396 hwnd_C = CreateWindowEx(0, "MainWindowClass", NULL,
2399 hwnd_F, 0, GetModuleHandle(0), NULL);
2400 trace("hwnd_C %p\n", hwnd_C);
2401 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2402 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2403 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2404 check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE);
2406 hwnd_B = CreateWindowEx(WS_EX_TOPMOST, "MainWindowClass", NULL,
2409 hwnd_F, 0, GetModuleHandle(0), NULL);
2410 trace("hwnd_B %p\n", hwnd_B);
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, hwnd_B, hwnd_F, FALSE);
2415 check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE);
2417 hwnd_A = CreateWindowEx(WS_EX_TOPMOST, "MainWindowClass", NULL,
2420 0, 0, GetModuleHandle(0), NULL);
2421 trace("hwnd_A %p\n", hwnd_A);
2422 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE);
2423 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE);
2424 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE);
2425 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE);
2426 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2427 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2429 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);
2431 /* move hwnd_F and its popups up */
2432 SetWindowPos(hwnd_F, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2433 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2434 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2435 check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE);
2436 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2437 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE);
2438 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE);
2440 /* move hwnd_F and its popups down */
2441 #if 0 /* enable once Wine is fixed to pass this test */
2442 SetWindowPos(hwnd_F, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE);
2443 check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE);
2444 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE);
2445 check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE);
2446 check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE);
2447 check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE);
2448 check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE);
2451 /* make hwnd_C owned by a topmost window */
2452 DestroyWindow( hwnd_C );
2453 hwnd_C = CreateWindowEx(0, "MainWindowClass", NULL,
2456 hwnd_A, 0, GetModuleHandle(0), NULL);
2457 trace("hwnd_C %p\n", hwnd_C);
2458 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE);
2459 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE);
2460 check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE);
2461 check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE);
2462 check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE);
2463 check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE);
2465 DestroyWindow(hwnd_A);
2466 DestroyWindow(hwnd_B);
2467 DestroyWindow(hwnd_C);
2468 DestroyWindow(hwnd_F);
2471 static void test_vis_rgn( HWND hwnd )
2473 RECT win_rect, rgn_rect;
2474 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
2477 ShowWindow(hwnd,SW_SHOW);
2478 hdc = GetDC( hwnd );
2479 ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" );
2480 GetWindowRect( hwnd, &win_rect );
2481 GetRgnBox( hrgn, &rgn_rect );
2484 trace("win9x, mapping to screen coords\n");
2485 MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 );
2487 trace("win: %d,%d-%d,%d\n", win_rect.left, win_rect.top, win_rect.right, win_rect.bottom );
2488 trace("rgn: %d,%d-%d,%d\n", rgn_rect.left, rgn_rect.top, rgn_rect.right, rgn_rect.bottom );
2489 ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n",
2490 rgn_rect.left, win_rect.left );
2491 ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n",
2492 rgn_rect.top, win_rect.top );
2493 ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n",
2494 rgn_rect.right, win_rect.right );
2495 ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n",
2496 rgn_rect.bottom, win_rect.bottom );
2497 ReleaseDC( hwnd, hdc );
2500 static LRESULT WINAPI set_focus_on_activate_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
2502 if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE)
2504 HWND child = GetWindow(hwnd, GW_CHILD);
2505 ok(child != 0, "couldn't find child window\n");
2507 ok(GetFocus() == child, "Focus should be on child %p\n", child);
2510 return DefWindowProc(hwnd, msg, wp, lp);
2513 static void test_SetFocus(HWND hwnd)
2516 WNDPROC old_wnd_proc;
2518 /* check if we can set focus to non-visible windows */
2520 ShowWindow(hwnd, SW_SHOW);
2523 ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd );
2524 ok( GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd );
2525 ShowWindow(hwnd, SW_HIDE);
2528 ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd );
2529 ok( !(GetWindowLong(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd );
2530 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2533 ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child );
2534 ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2535 ShowWindow(child, SW_SHOW);
2536 ok( GetWindowLong(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child );
2537 ok( GetFocus() == child, "Focus no longer on child %p\n", child );
2538 ShowWindow(child, SW_HIDE);
2539 ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2540 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2541 ShowWindow(child, SW_SHOW);
2542 child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL);
2544 ShowWindow(child2, SW_SHOW);
2546 ShowWindow(child, SW_HIDE);
2547 ok( !(GetWindowLong(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child );
2548 ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() );
2549 ShowWindow(child, SW_SHOW);
2551 ok( GetFocus() == child, "Focus should be on child %p\n", child );
2552 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW);
2553 ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2555 ShowWindow(child, SW_HIDE);
2557 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() );
2558 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
2559 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2560 ShowWindow(child, SW_HIDE);
2561 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() );
2563 ShowWindow(hwnd, SW_SHOW);
2564 ShowWindow(child, SW_SHOW);
2566 ok( GetFocus() == child, "Focus should be on child %p\n", child );
2567 EnableWindow(hwnd, FALSE);
2568 ok( GetFocus() == child, "Focus should still be on child %p\n", child );
2569 EnableWindow(hwnd, TRUE);
2571 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2572 ShowWindow(hwnd, SW_SHOWMINIMIZED);
2573 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2575 ok( GetFocus() != child, "Focus should not be on child %p\n", child );
2576 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
2577 ShowWindow(hwnd, SW_RESTORE);
2578 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2579 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd );
2580 ShowWindow(hwnd, SW_SHOWMINIMIZED);
2581 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2582 ok( GetFocus() != child, "Focus should not be on child %p\n", child );
2584 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd );
2585 old_wnd_proc = (WNDPROC)SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)set_focus_on_activate_proc);
2586 ShowWindow(hwnd, SW_RESTORE);
2587 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd);
2589 ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() );
2591 SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)old_wnd_proc);
2593 DestroyWindow( child2 );
2594 DestroyWindow( child );
2597 static void test_SetActiveWindow(HWND hwnd)
2601 flush_events( TRUE );
2602 ShowWindow(hwnd, SW_HIDE);
2605 check_wnd_state(0, 0, 0, 0);
2607 /*trace("testing SetActiveWindow %p\n", hwnd);*/
2609 ShowWindow(hwnd, SW_SHOW);
2610 check_wnd_state(hwnd, hwnd, hwnd, 0);
2612 hwnd2 = SetActiveWindow(0);
2613 ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd);
2614 if (!GetActiveWindow()) /* doesn't always work on vista */
2616 check_wnd_state(0, 0, 0, 0);
2617 hwnd2 = SetActiveWindow(hwnd);
2618 ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2);
2620 check_wnd_state(hwnd, hwnd, hwnd, 0);
2622 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2623 check_wnd_state(hwnd, hwnd, hwnd, 0);
2625 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2626 check_wnd_state(hwnd, hwnd, hwnd, 0);
2628 ShowWindow(hwnd, SW_HIDE);
2629 check_wnd_state(0, 0, 0, 0);
2631 /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/
2632 SetActiveWindow(hwnd);
2633 check_wnd_state(hwnd, hwnd, hwnd, 0);
2635 ShowWindow(hwnd, SW_SHOW);
2636 check_wnd_state(hwnd, hwnd, hwnd, 0);
2638 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2639 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2641 DestroyWindow(hwnd2);
2642 check_wnd_state(hwnd, hwnd, hwnd, 0);
2644 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2645 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2647 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2648 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2650 DestroyWindow(hwnd2);
2651 check_wnd_state(hwnd, hwnd, hwnd, 0);
2654 struct create_window_thread_params
2657 HANDLE window_created;
2658 HANDLE test_finished;
2661 static DWORD WINAPI create_window_thread(void *param)
2663 struct create_window_thread_params *p = param;
2667 p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
2669 ret = SetEvent(p->window_created);
2670 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError());
2672 res = WaitForSingleObject(p->test_finished, INFINITE);
2673 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2675 DestroyWindow(p->window);
2679 static void test_SetForegroundWindow(HWND hwnd)
2681 struct create_window_thread_params thread_params;
2688 flush_events( TRUE );
2689 ShowWindow(hwnd, SW_HIDE);
2692 check_wnd_state(0, 0, 0, 0);
2694 /*trace("testing SetForegroundWindow %p\n", hwnd);*/
2696 ShowWindow(hwnd, SW_SHOW);
2697 check_wnd_state(hwnd, hwnd, hwnd, 0);
2699 hwnd2 = SetActiveWindow(0);
2700 ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd);
2701 if (GetActiveWindow() == hwnd) /* doesn't always work on vista */
2702 check_wnd_state(hwnd, hwnd, hwnd, 0);
2704 check_wnd_state(0, 0, 0, 0);
2706 ret = SetForegroundWindow(hwnd);
2709 skip( "SetForegroundWindow not working\n" );
2712 check_wnd_state(hwnd, hwnd, hwnd, 0);
2714 SetLastError(0xdeadbeef);
2715 ret = SetForegroundWindow(0);
2716 ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n");
2717 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE ||
2718 broken(GetLastError() == 0xdeadbeef), /* win9x */
2719 "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError());
2720 check_wnd_state(hwnd, hwnd, hwnd, 0);
2722 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2723 check_wnd_state(hwnd, hwnd, hwnd, 0);
2725 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW);
2726 check_wnd_state(hwnd, hwnd, hwnd, 0);
2728 hwnd2 = GetForegroundWindow();
2729 ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2);
2730 ret = SetForegroundWindow( GetDesktopWindow() );
2731 ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError());
2732 hwnd2 = GetForegroundWindow();
2733 ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2);
2735 ShowWindow(hwnd, SW_HIDE);
2736 check_wnd_state(0, 0, 0, 0);
2738 /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/
2739 ret = SetForegroundWindow(hwnd);
2740 ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n");
2741 check_wnd_state(hwnd, hwnd, hwnd, 0);
2743 ShowWindow(hwnd, SW_SHOW);
2744 check_wnd_state(hwnd, hwnd, hwnd, 0);
2746 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2747 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2749 DestroyWindow(hwnd2);
2750 check_wnd_state(hwnd, hwnd, hwnd, 0);
2752 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL);
2753 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2755 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW);
2756 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2758 DestroyWindow(hwnd2);
2759 check_wnd_state(hwnd, hwnd, hwnd, 0);
2761 hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0);
2762 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2764 thread_params.window_created = CreateEvent(NULL, FALSE, FALSE, NULL);
2765 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError());
2766 thread_params.test_finished = CreateEvent(NULL, FALSE, FALSE, NULL);
2767 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError());
2768 thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid);
2769 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError());
2770 res = WaitForSingleObject(thread_params.window_created, INFINITE);
2771 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError());
2772 check_wnd_state(hwnd2, thread_params.window, hwnd2, 0);
2774 SetForegroundWindow(hwnd2);
2775 check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2777 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
2778 if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0);
2779 todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow());
2780 todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus());
2782 SetEvent(thread_params.test_finished);
2783 WaitForSingleObject(thread, INFINITE);
2784 CloseHandle(thread_params.test_finished);
2785 CloseHandle(thread_params.window_created);
2786 CloseHandle(thread);
2787 DestroyWindow(hwnd2);
2790 static WNDPROC old_button_proc;
2792 static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPARAM lparam)
2797 key_state = GetKeyState(VK_LBUTTON);
2798 ok(!(key_state & 0x8000), "VK_LBUTTON should not be pressed, state %04x\n", key_state);
2800 ret = CallWindowProcA(old_button_proc, button, msg, wparam, lparam);
2802 if (msg == WM_LBUTTONDOWN)
2806 check_wnd_state(button, button, button, button);
2808 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2810 trace("hwnd %p\n", hwnd);
2812 check_wnd_state(button, button, button, button);
2814 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2816 check_wnd_state(button, button, button, button);
2818 DestroyWindow(hwnd);
2820 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2822 trace("hwnd %p\n", hwnd);
2824 check_wnd_state(button, button, button, button);
2826 /* button wnd proc should release capture on WM_KILLFOCUS if it does
2827 * match internal button state.
2829 SendMessage(button, WM_KILLFOCUS, 0, 0);
2830 check_wnd_state(button, button, button, 0);
2832 ShowWindow(hwnd, SW_SHOW);
2833 check_wnd_state(hwnd, hwnd, hwnd, 0);
2835 capture = SetCapture(hwnd);
2836 ok(capture == 0, "SetCapture() = %p\n", capture);
2838 check_wnd_state(hwnd, hwnd, hwnd, hwnd);
2840 DestroyWindow(hwnd);
2842 check_wnd_state(button, 0, button, 0);
2848 static void test_capture_1(void)
2850 HWND button, capture;
2852 capture = GetCapture();
2853 ok(capture == 0, "GetCapture() = %p\n", capture);
2855 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
2857 trace("button %p\n", button);
2859 old_button_proc = (WNDPROC)SetWindowLongPtrA(button, GWLP_WNDPROC, (LONG_PTR)button_hook_proc);
2861 SendMessageA(button, WM_LBUTTONDOWN, 0, 0);
2863 capture = SetCapture(button);
2864 ok(capture == 0, "SetCapture() = %p\n", capture);
2865 check_wnd_state(button, 0, button, button);
2867 DestroyWindow(button);
2868 /* old active window test depends on previously executed window
2869 * activation tests, and fails under NT4.
2870 check_wnd_state(oldActive, 0, oldFocus, 0);*/
2873 static void test_capture_2(void)
2875 HWND button, hwnd, capture, oldFocus, oldActive;
2877 oldFocus = GetFocus();
2878 oldActive = GetActiveWindow();
2879 check_wnd_state(oldActive, 0, oldFocus, 0);
2881 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL);
2883 trace("button %p\n", button);
2885 check_wnd_state(button, button, button, 0);
2887 capture = SetCapture(button);
2888 ok(capture == 0, "SetCapture() = %p\n", capture);
2890 check_wnd_state(button, button, button, button);
2892 /* button wnd proc should ignore WM_KILLFOCUS if it doesn't match
2893 * internal button state.
2895 SendMessage(button, WM_KILLFOCUS, 0, 0);
2896 check_wnd_state(button, button, button, button);
2898 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2900 trace("hwnd %p\n", hwnd);
2902 check_wnd_state(button, button, button, button);
2904 ShowWindow(hwnd, SW_SHOWNOACTIVATE);
2906 check_wnd_state(button, button, button, button);
2908 DestroyWindow(hwnd);
2910 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL);
2912 trace("hwnd %p\n", hwnd);
2914 check_wnd_state(button, button, button, button);
2916 ShowWindow(hwnd, SW_SHOW);
2918 check_wnd_state(hwnd, hwnd, hwnd, button);
2920 capture = SetCapture(hwnd);
2921 ok(capture == button, "SetCapture() = %p\n", capture);
2923 check_wnd_state(hwnd, hwnd, hwnd, hwnd);
2925 DestroyWindow(hwnd);
2926 check_wnd_state(button, button, button, 0);
2928 DestroyWindow(button);
2929 check_wnd_state(oldActive, 0, oldFocus, 0);
2932 static void test_capture_3(HWND hwnd1, HWND hwnd2)
2936 ShowWindow(hwnd1, SW_HIDE);
2937 ShowWindow(hwnd2, SW_HIDE);
2939 ok(!IsWindowVisible(hwnd1), "%p should be invisible\n", hwnd1);
2940 ok(!IsWindowVisible(hwnd2), "%p should be invisible\n", hwnd2);
2943 check_wnd_state(0, 0, 0, hwnd1);
2946 check_wnd_state(0, 0, 0, hwnd2);
2948 ShowWindow(hwnd1, SW_SHOW);
2949 check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2);
2951 ret = ReleaseCapture();
2952 ok (ret, "releasecapture did not return TRUE.\n");
2953 ret = ReleaseCapture();
2954 ok (ret, "releasecapture did not return TRUE after second try.\n");
2957 static LRESULT CALLBACK test_capture_4_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
2960 HWND cap_wnd, cap_wnd2, set_cap_wnd;
2964 case WM_CAPTURECHANGED:
2966 /* now try to release capture from menu. this should fail */
2967 if (pGetGUIThreadInfo)
2969 memset(>i, 0, sizeof(GUITHREADINFO));
2970 gti.cbSize = sizeof(GUITHREADINFO);
2971 status = pGetGUIThreadInfo(GetCurrentThreadId(), >i);
2972 ok(status, "GetGUIThreadInfo() failed!\n");
2973 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
2975 cap_wnd = GetCapture();
2977 /* check that re-setting the capture for the menu fails */
2978 set_cap_wnd = SetCapture(cap_wnd);
2979 ok(!set_cap_wnd || broken(set_cap_wnd == cap_wnd), /* nt4 */
2980 "SetCapture should have failed!\n");
2983 DestroyWindow(hWnd);
2987 /* check that SetCapture fails for another window and that it does not touch the error code */
2988 set_cap_wnd = SetCapture(hWnd);
2989 ok(!set_cap_wnd, "SetCapture should have failed!\n");
2991 /* check that ReleaseCapture fails and does not touch the error code */
2992 status = ReleaseCapture();
2993 ok(!status, "ReleaseCapture should have failed!\n");
2995 /* check that thread info did not change */
2996 if (pGetGUIThreadInfo)
2998 memset(>i, 0, sizeof(GUITHREADINFO));
2999 gti.cbSize = sizeof(GUITHREADINFO);
3000 status = pGetGUIThreadInfo(GetCurrentThreadId(), >i);
3001 ok(status, "GetGUIThreadInfo() failed!\n");
3002 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags);
3005 /* verify that no capture change took place */
3006 cap_wnd2 = GetCapture();
3007 ok(cap_wnd2 == cap_wnd, "Capture changed!\n");
3009 /* we are done. kill the window */
3010 DestroyWindow(hWnd);
3014 return( DefWindowProcA( hWnd, msg, wParam, lParam ) );
3019 /* Test that no-one can mess around with the current capture while a menu is open */
3020 static void test_capture_4(void)
3026 HINSTANCE hInstance = GetModuleHandleA( NULL );
3029 if (!pGetGUIThreadInfo)
3031 win_skip("GetGUIThreadInfo is not available\n");
3034 wclass.lpszClassName = "TestCapture4Class";
3035 wclass.style = CS_HREDRAW | CS_VREDRAW;
3036 wclass.lpfnWndProc = test_capture_4_proc;
3037 wclass.hInstance = hInstance;
3038 wclass.hIcon = LoadIconA( 0, IDI_APPLICATION );
3039 wclass.hCursor = LoadCursorA( NULL, IDC_ARROW );
3040 wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
3041 wclass.lpszMenuName = 0;
3042 wclass.cbClsExtra = 0;
3043 wclass.cbWndExtra = 0;
3044 aclass = RegisterClassA( &wclass );
3045 ok( aclass, "RegisterClassA failed with error %d\n", GetLastError());
3046 hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest",
3047 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
3048 400, 200, NULL, NULL, hInstance, NULL);
3049 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError());
3051 hmenu = CreatePopupMenu();
3053 ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest2");
3054 ok( ret, "AppendMenuA has failed!\n");
3056 /* set main window to have initial capture */
3061 win_skip("TrackPopupMenu test crashes on Win9x/WinMe\n");
3065 /* create popup (it will self-destruct) */
3066 ret = TrackPopupMenu(hmenu, TPM_RETURNCMD, 100, 100, 0, hwnd, NULL);
3067 ok( ret == 0, "TrackPopupMenu returned %d expected zero\n", ret);
3072 DestroyWindow(hwnd);
3075 /* PeekMessage wrapper that ignores the messages we don't care about */
3076 static BOOL peek_message( MSG *msg )
3081 ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE);
3082 } while (ret && (msg->message == WM_TIMER || ignore_message(msg->message)));
3086 static void test_keyboard_input(HWND hwnd)
3091 flush_events( TRUE );
3092 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW);
3094 flush_events( TRUE );
3096 ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow());
3099 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3101 flush_events( TRUE );
3103 PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3104 ret = peek_message(&msg);
3105 ok( ret, "no message available\n");
3106 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3107 ret = peek_message(&msg);
3108 ok( !ret, "message %04x available\n", msg.message);
3110 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3112 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3113 ret = peek_message(&msg);
3114 ok(ret, "no message available\n");
3115 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3116 ret = peek_message(&msg);
3117 ok( !ret, "message %04x available\n", msg.message);
3119 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus());
3121 keybd_event(VK_SPACE, 0, 0, 0);
3122 if (!peek_message(&msg))
3124 skip( "keybd_event didn't work, skipping keyboard test\n" );
3127 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3128 ret = peek_message(&msg);
3129 ok( !ret, "message %04x available\n", msg.message);
3132 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3134 flush_events( TRUE );
3136 PostMessageA(hwnd, WM_KEYDOWN, 0, 0);
3137 ret = peek_message(&msg);
3138 ok(ret, "no message available\n");
3139 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3140 ret = peek_message(&msg);
3141 ok( !ret, "message %04x available\n", msg.message);
3143 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3145 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0);
3146 ret = peek_message(&msg);
3147 ok(ret, "no message available\n");
3148 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3149 ret = peek_message(&msg);
3150 ok( !ret, "message %04x available\n", msg.message);
3152 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus());
3154 keybd_event(VK_SPACE, 0, 0, 0);
3155 ret = peek_message(&msg);
3156 ok(ret, "no message available\n");
3157 ok(msg.hwnd == hwnd && msg.message == WM_SYSKEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3158 ret = peek_message(&msg);
3159 ok( !ret, "message %04x available\n", msg.message);
3162 static BOOL wait_for_message( MSG *msg )
3168 ret = peek_message(msg);
3171 if (msg->message == WM_PAINT) DispatchMessage(msg);
3174 else if (MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ) == WAIT_TIMEOUT) break;
3176 if (!ret) msg->message = 0;
3180 static void test_mouse_input(HWND hwnd)
3190 ShowWindow(hwnd, SW_SHOWNORMAL);
3192 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3194 GetWindowRect(hwnd, &rc);
3195 trace("main window %p: (%d,%d)-(%d,%d)\n", hwnd, rc.left, rc.top, rc.right, rc.bottom);
3197 popup = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP,
3198 rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
3201 ShowWindow(popup, SW_SHOW);
3202 UpdateWindow(popup);
3203 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3205 GetWindowRect(popup, &rc);
3206 trace("popup window %p: (%d,%d)-(%d,%d)\n", popup, rc.left, rc.top, rc.right, rc.bottom);
3208 x = rc.left + (rc.right - rc.left) / 2;
3209 y = rc.top + (rc.bottom - rc.top) / 2;
3210 trace("setting cursor to (%d,%d)\n", x, y);
3214 if (x != pt.x || y != pt.y)
3216 skip( "failed to set mouse position, skipping mouse input tests\n" );
3220 flush_events( TRUE );
3222 /* Check that setting the same position may generate WM_MOUSEMOVE */
3225 ret = peek_message(&msg);
3228 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n",
3229 msg.hwnd, msg.message);
3230 ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n",
3231 x, y, msg.pt.x, msg.pt.y);
3234 /* force the system to update its internal queue mouse position,
3235 * otherwise it won't generate relative mouse movements below.
3237 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3238 flush_events( TRUE );
3241 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3242 flush_events( FALSE );
3243 /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */
3244 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
3246 if (msg.message == WM_TIMER || ignore_message(msg.message)) continue;
3247 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE,
3248 "hwnd %p message %04x\n", msg.hwnd, msg.message);
3249 DispatchMessage(&msg);
3251 ret = peek_message(&msg);
3252 ok( !ret, "message %04x available\n", msg.message);
3254 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0);
3255 ShowWindow(popup, SW_HIDE);
3256 ret = wait_for_message( &msg );
3258 ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message);
3259 flush_events( TRUE );
3261 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0);
3262 ShowWindow(hwnd, SW_HIDE);
3263 ret = wait_for_message( &msg );
3264 ok( !ret, "message %04x available\n", msg.message);
3265 flush_events( TRUE );
3267 /* test mouse clicks */
3269 ShowWindow(hwnd, SW_SHOW);
3270 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3271 flush_events( TRUE );
3272 ShowWindow(popup, SW_SHOW);
3273 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE );
3274 flush_events( TRUE );
3276 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3277 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3278 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3279 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3281 ret = wait_for_message( &msg );
3284 skip( "simulating mouse click doesn't work, skipping mouse button tests\n" );
3287 if (msg.message == WM_MOUSEMOVE) /* win2k has an extra WM_MOUSEMOVE here */
3289 ret = wait_for_message( &msg );
3290 ok(ret, "no message available\n");
3293 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3294 msg.hwnd, popup, msg.message);
3296 ret = wait_for_message( &msg );
3297 ok(ret, "no message available\n");
3298 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3299 msg.hwnd, popup, msg.message);
3301 ret = wait_for_message( &msg );
3302 ok(ret, "no message available\n");
3303 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p/%p message %04x\n",
3304 msg.hwnd, popup, msg.message);
3306 ret = wait_for_message( &msg );
3307 ok(ret, "no message available\n");
3308 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3309 msg.hwnd, popup, msg.message);
3311 ret = peek_message(&msg);
3312 ok(!ret, "message %04x available\n", msg.message);
3314 ShowWindow(popup, SW_HIDE);
3315 flush_events( TRUE );
3317 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3318 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3319 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
3320 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
3322 ret = wait_for_message( &msg );
3323 ok(ret, "no message available\n");
3324 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3325 msg.hwnd, hwnd, msg.message);
3326 ret = wait_for_message( &msg );
3327 ok(ret, "no message available\n");
3328 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3329 msg.hwnd, hwnd, msg.message);
3331 test_lbuttondown_flag = TRUE;
3332 SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0);
3333 test_lbuttondown_flag = FALSE;
3335 ret = wait_for_message( &msg );
3336 ok(ret, "no message available\n");
3337 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n",
3338 msg.hwnd, popup, msg.message);
3339 ok(peek_message(&msg), "no message available\n");
3340 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n",
3341 msg.hwnd, popup, msg.message);
3342 ok(peek_message(&msg), "no message available\n");
3344 /* Test WM_MOUSEACTIVATE */
3345 #define TEST_MOUSEACTIVATE(A,B) \
3346 res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \
3347 ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res);
3349 TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE);
3350 TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE);
3351 TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE);
3352 TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE);
3353 TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE);
3354 TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE);
3355 TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE);
3356 TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE);
3357 TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE);
3358 TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE);
3359 TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE);
3360 TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE);
3361 TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE);
3362 TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE);
3363 TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE);
3364 TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE);
3365 TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE);
3366 TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE);
3367 TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE);
3368 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE);
3369 TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE);
3370 TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE);
3371 TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE);
3372 TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE);
3375 /* Clear any messages left behind by WM_MOUSEACTIVATE tests */
3376 flush_events( TRUE );
3378 DestroyWindow(popup);
3381 static void test_validatergn(HWND hwnd)
3387 child = CreateWindowExA(0, "static", NULL, WS_CHILD| WS_VISIBLE, 10, 10, 10, 10, hwnd, 0, 0, NULL);
3388 ShowWindow(hwnd, SW_SHOW);
3389 UpdateWindow( hwnd);
3390 /* test that ValidateRect validates children*/
3391 InvalidateRect( child, NULL, 1);
3392 GetWindowRect( child, &rc);
3393 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3394 ret = GetUpdateRect( child, &rc2, 0);
3395 ok( ret == 1, "Expected GetUpdateRect to return non-zero, got %d\n", ret);
3396 ok( rc2.right > rc2.left && rc2.bottom > rc2.top,
3397 "Update rectangle is empty!\n");
3398 ValidateRect( hwnd, &rc);
3399 ret = GetUpdateRect( child, &rc2, 0);
3400 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3401 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3402 "Update rectangle %d,%d-%d,%d is not empty!\n", rc2.left, rc2.top,
3403 rc2.right, rc2.bottom);
3405 /* now test ValidateRgn */
3406 InvalidateRect( child, NULL, 1);
3407 GetWindowRect( child, &rc);
3408 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2);
3409 rgn = CreateRectRgnIndirect( &rc);
3410 ValidateRgn( hwnd, rgn);
3411 ret = GetUpdateRect( child, &rc2, 0);
3412 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret);
3413 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0,
3414 "Update rectangle %d,%d-%d,%d is not empty!\n", rc2.left, rc2.top,
3415 rc2.right, rc2.bottom);
3418 DestroyWindow( child );
3421 static void nccalchelper(HWND hwnd, INT x, INT y, RECT *prc)
3424 MoveWindow( hwnd, 0, 0, x, y, 0);
3425 GetWindowRect( hwnd, prc);
3427 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc);
3428 trace("window rect is %d,%d - %d,%d, nccalc rect is %d,%d - %d,%d\n",
3429 rc.left,rc.top,rc.right,rc.bottom, prc->left,prc->top,prc->right,prc->bottom);
3432 static void test_nccalcscroll(HWND parent)
3435 INT sbheight = GetSystemMetrics( SM_CYHSCROLL);
3436 INT sbwidth = GetSystemMetrics( SM_CXVSCROLL);
3437 HWND hwnd = CreateWindowExA(0, "static", NULL,
3438 WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL ,
3439 10, 10, 200, 200, parent, 0, 0, NULL);
3440 ShowWindow( parent, SW_SHOW);
3441 UpdateWindow( parent);
3443 /* test window too low for a horizontal scroll bar */
3444 nccalchelper( hwnd, 100, sbheight, &rc1);
3445 ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %d,%d - %d,%d\n",
3446 sbheight, rc1.left, rc1.top, rc1.right, rc1.bottom);
3448 /* test window just high enough for a horizontal scroll bar */
3449 nccalchelper( hwnd, 100, sbheight + 1, &rc1);
3450 ok( rc1.bottom - rc1.top == 1, "Height should be %d size is %d,%d - %d,%d\n",
3451 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
3453 /* test window too narrow for a vertical scroll bar */
3454 nccalchelper( hwnd, sbwidth - 1, 100, &rc1);
3455 ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %d,%d - %d,%d\n",
3456 sbwidth - 1, rc1.left, rc1.top, rc1.right, rc1.bottom);
3458 /* test window just wide enough for a vertical scroll bar */
3459 nccalchelper( hwnd, sbwidth, 100, &rc1);
3460 ok( rc1.right - rc1.left == 0, "Width should be %d size is %d,%d - %d,%d\n",
3461 0, rc1.left, rc1.top, rc1.right, rc1.bottom);
3463 /* same test, but with client edge: not enough width */
3464 SetWindowLong( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLong( hwnd, GWL_EXSTYLE));
3465 nccalchelper( hwnd, sbwidth, 100, &rc1);
3466 ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE),
3467 "Width should be %d size is %d,%d - %d,%d\n",
3468 sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), rc1.left, rc1.top, rc1.right, rc1.bottom);
3470 DestroyWindow( hwnd);
3473 static void test_SetParent(void)
3475 HWND desktop = GetDesktopWindow();
3477 HWND ret, parent, child1, child2, child3, child4, sibling, popup;
3480 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3481 100, 100, 200, 200, 0, 0, 0, NULL);
3482 assert(parent != 0);
3483 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3484 0, 0, 50, 50, parent, 0, 0, NULL);
3485 assert(child1 != 0);
3486 child2 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3487 0, 0, 50, 50, child1, 0, 0, NULL);
3488 assert(child2 != 0);
3489 child3 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3490 0, 0, 50, 50, child2, 0, 0, NULL);
3491 assert(child3 != 0);
3492 child4 = CreateWindowExA(0, "static", NULL, WS_POPUP,
3493 0, 0, 50, 50, child3, 0, 0, NULL);
3494 assert(child4 != 0);
3496 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n",
3497 parent, child1, child2, child3, child4);
3499 check_parents(parent, desktop, 0, 0, 0, parent, parent);
3500 check_parents(child1, parent, parent, parent, 0, parent, parent);
3501 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3502 check_parents(child3, child2, child2, child2, 0, child2, parent);
3503 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3505 ok(!IsChild(desktop, parent), "wrong parent/child %p/%p\n", desktop, parent);
3506 ok(!IsChild(desktop, child1), "wrong parent/child %p/%p\n", desktop, child1);
3507 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
3508 ok(!IsChild(desktop, child3), "wrong parent/child %p/%p\n", desktop, child3);
3509 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
3511 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1);
3512 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2);
3513 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2);
3514 ok(!IsChild(child1, child2), "wrong parent/child %p/%p\n", child1, child2);
3515 ok(!IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3);
3516 ok(IsChild(child2, child3), "wrong parent/child %p/%p\n", child2, child3);
3517 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4);
3518 ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4);
3519 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4);
3521 if (!is_win9x) /* Win9x doesn't survive this test */
3523 ok(!SetParent(parent, child1), "SetParent should fail\n");
3524 ok(!SetParent(child2, child3), "SetParent should fail\n");
3525 ok(SetParent(child1, parent) != 0, "SetParent should not fail\n");
3526 ret = SetParent(parent, child2);
3527 todo_wine ok( !ret || broken( ret != 0 ), "SetParent should fail\n");
3528 if (ret) /* nt4, win2k */
3530 ret = SetParent(parent, child3);
3531 ok(ret != 0, "SetParent should not fail\n");
3532 ret = SetParent(child2, parent);
3533 ok(!ret, "SetParent should fail\n");
3534 ret = SetParent(parent, child4);
3535 ok(ret != 0, "SetParent should not fail\n");
3536 check_parents(parent, child4, child4, 0, 0, child4, parent);
3537 check_parents(child1, parent, parent, parent, 0, child4, parent);
3538 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3539 check_parents(child3, child2, child2, child2, 0, child2, parent);
3540 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3544 ret = SetParent(parent, child3);
3545 ok(ret != 0, "SetParent should not fail\n");
3546 ret = SetParent(child2, parent);
3547 ok(!ret, "SetParent should fail\n");
3548 ret = SetParent(parent, child4);
3549 ok(!ret, "SetParent should fail\n");
3550 check_parents(parent, child3, child3, 0, 0, child2, parent);
3551 check_parents(child1, parent, parent, parent, 0, child2, parent);
3552 check_parents(child2, desktop, parent, parent, parent, child2, parent);
3553 check_parents(child3, child2, child2, child2, 0, child2, parent);
3554 check_parents(child4, desktop, child2, child2, child2, child4, parent);
3558 skip("Win9x/WinMe crash\n");
3560 hMenu = CreateMenu();
3561 sibling = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3562 100, 100, 200, 200, 0, hMenu, 0, NULL);
3563 assert(sibling != 0);
3565 ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n");
3566 ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n");
3568 ok(DestroyWindow(parent), "DestroyWindow() failed\n");
3570 ok(!IsWindow(parent), "parent still exists\n");
3571 ok(!IsWindow(sibling), "sibling still exists\n");
3572 ok(!IsWindow(child1), "child1 still exists\n");
3573 ok(!IsWindow(child2), "child2 still exists\n");
3574 ok(!IsWindow(child3), "child3 still exists\n");
3575 ok(!IsWindow(child4), "child4 still exists\n");
3577 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW,
3578 100, 100, 200, 200, 0, 0, 0, NULL);
3579 assert(parent != 0);
3580 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD,
3581 0, 0, 50, 50, parent, 0, 0, NULL);
3582 assert(child1 != 0);
3583 popup = CreateWindowExA(0, "static", NULL, WS_POPUP,
3584 0, 0, 50, 50, 0, 0, 0, NULL);
3587 trace("parent %p, child %p, popup %p\n", parent, child1, popup);
3589 check_parents(parent, desktop, 0, 0, 0, parent, parent);
3590 check_parents(child1, parent, parent, parent, 0, parent, parent);
3591 check_parents(popup, desktop, 0, 0, 0, popup, popup);
3593 SetActiveWindow(parent);
3595 check_active_state(parent, 0, parent);
3597 ret = SetParent(popup, child1);
3598 ok(ret == desktop, "expected %p, got %p\n", desktop, ret);
3599 check_parents(popup, child1, child1, 0, 0, parent, popup);
3601 check_active_state(popup, 0, popup);
3603 SetActiveWindow(parent);
3605 check_active_state(parent, 0, parent);
3607 bret = SetForegroundWindow(popup);
3609 ok(bret || broken(!bret), "SetForegroundWindow() failed\n");
3611 check_active_state(popup, 0, popup);
3613 check_active_state(popup, popup, popup);
3616 ok(DestroyWindow(parent), "DestroyWindow() failed\n");
3618 ok(!IsWindow(parent), "parent still exists\n");
3619 ok(!IsWindow(child1), "child1 still exists\n");
3620 ok(!IsWindow(popup), "popup still exists\n");
3623 static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
3625 LPCREATESTRUCT lpcs;
3632 lpcs = (LPCREATESTRUCT)lparam;
3633 lpss = lpcs->lpCreateParams;
3636 if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) ||
3637 ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) &&
3638 (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME))))
3639 ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n");
3641 ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n");
3643 ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE),
3644 "Ex style (0x%08lx) should match what the caller passed to CreateWindowEx (0x%08lx)\n",
3645 (lpss->styleOld & ~WS_EX_WINDOWEDGE), (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE));
3647 ok(lpss->styleNew == lpcs->style,
3648 "Style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n",
3649 lpss->styleNew, lpcs->style);
3653 return DefWindowProc(hwnd, msg, wparam, lparam);
3656 static ATOM atomStyleCheckClass;
3658 static void register_style_check_class(void)
3666 GetModuleHandle(NULL),
3668 LoadCursor(NULL, IDC_ARROW),
3669 (HBRUSH)(COLOR_BTNFACE+1),
3671 TEXT("WineStyleCheck"),
3674 atomStyleCheckClass = RegisterClass(&wc);
3677 static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut)
3679 DWORD dwActualStyle;
3680 DWORD dwActualExStyle;
3683 HWND hwndParent = NULL;
3685 ss.styleNew = dwStyleIn;
3686 ss.styleOld = dwExStyleIn;
3688 if (dwStyleIn & WS_CHILD)
3690 hwndParent = CreateWindowEx(0, MAKEINTATOM(atomStyleCheckClass), NULL,
3691 WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
3694 hwnd = CreateWindowEx(dwExStyleIn, MAKEINTATOM(atomStyleCheckClass), NULL,
3695 dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss);
3698 flush_events( TRUE );
3700 dwActualStyle = GetWindowLong(hwnd, GWL_STYLE);
3701 dwActualExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
3702 ok((dwActualStyle == dwStyleOut) && (dwActualExStyle == dwExStyleOut),
3703 "Style (0x%08x) should really be 0x%08x and/or Ex style (0x%08x) should really be 0x%08x\n",
3704 dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut);
3706 /* try setting the styles explicitly */
3707 SetWindowLong( hwnd, GWL_EXSTYLE, dwExStyleIn );
3708 SetWindowLong( hwnd, GWL_STYLE, dwStyleIn );
3709 dwActualStyle = GetWindowLong(hwnd, GWL_STYLE);
3710 dwActualExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
3711 /* WS_CLIPSIBLINGS can't be reset on top-level windows */
3712 if (dwStyleIn & WS_CHILD) dwStyleOut = dwStyleIn;
3713 else dwStyleOut = dwStyleIn | WS_CLIPSIBLINGS;
3714 /* WS_EX_WINDOWEDGE can't always be changed */
3715 if ((dwExStyleIn & WS_EX_DLGMODALFRAME) || (dwStyleIn & WS_THICKFRAME))
3716 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE;
3717 else if (dwStyleIn & (WS_CHILD | WS_POPUP))
3718 dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE;
3720 dwExStyleOut = dwExStyleIn;
3721 ok((dwActualStyle == dwStyleOut) && (dwActualExStyle == dwExStyleOut),
3722 "%08x/%08x: Style (0x%08x) should really be 0x%08x and/or Ex style (0x%08x) should really be 0x%08x\n",
3723 dwStyleIn, dwExStyleIn, dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut);
3725 DestroyWindow(hwnd);
3726 if (hwndParent) DestroyWindow(hwndParent);
3729 /* tests what window styles the window manager automatically adds */
3730 static void test_window_styles(void)
3732 register_style_check_class();
3734 check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE);
3735 check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE);
3736 check_window_style(WS_CHILD, 0, WS_CHILD, 0);
3737 check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0);
3738 check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW);
3739 check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0);
3740 check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0);
3741 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
3742 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME);
3743 check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE);
3744 check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE);
3746 if (pGetLayeredWindowAttributes)
3748 check_window_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE);
3749 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE);
3750 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION,
3751 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE);
3755 static void test_scrollwindow( HWND hwnd)
3761 ShowWindow( hwnd, SW_SHOW);
3762 UpdateWindow( hwnd);
3763 flush_events( TRUE );
3764 GetClientRect( hwnd, &rc);
3766 /* test ScrollWindow(Ex) with no clip rectangle */
3767 /* paint the lower half of the window black */
3769 rc2.top = ( rc2.top + rc2.bottom) / 2;
3770 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
3771 /* paint the upper half of the window white */
3772 rc2.bottom = rc2.top;
3774 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
3775 /* scroll lower half up */
3777 rc2.top = ( rc2.top + rc2.bottom) / 2;
3778 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, NULL, NULL, NULL, SW_ERASE);
3779 flush_events(FALSE);
3780 /* expected: black should have scrolled to the upper half */
3781 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 );
3782 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
3783 /* Repeat that test of ScrollWindow(Ex) now with clip rectangle */
3784 /* paint the lower half of the window black */
3786 rc2.top = ( rc2.top + rc2.bottom) / 2;
3787 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
3788 /* paint the upper half of the window white */
3789 rc2.bottom = rc2.top;
3791 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH));
3792 /* scroll lower half up */
3794 rc2.top = ( rc2.top + rc2.bottom) / 2;
3796 rc3.left = rc3.right / 4;
3797 rc3.right -= rc3.right / 4;
3798 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, &rc3, NULL, NULL, SW_ERASE);
3799 flush_events(FALSE);
3800 /* expected: black should have scrolled to the upper half */
3801 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 );
3802 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
3805 ReleaseDC( hwnd, hdc);
3808 static void test_scrollvalidate( HWND parent)
3811 HRGN hrgn=CreateRectRgn(0,0,0,0);
3812 HRGN exprgn, tmprgn, clipping;
3813 RECT rc, rcu, cliprc;
3814 /* create two overlapping child windows. The visual region
3815 * of hwnd1 is clipped by the overlapping part of
3816 * hwnd2 because of the WS_CLIPSIBLING style */
3819 clipping = CreateRectRgn(0,0,0,0);
3820 tmprgn = CreateRectRgn(0,0,0,0);
3821 exprgn = CreateRectRgn(0,0,0,0);
3822 hwnd2 = CreateWindowExA(0, "static", NULL,
3823 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
3824 75, 30, 100, 100, parent, 0, 0, NULL);
3825 hwnd1 = CreateWindowExA(0, "static", NULL,
3826 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER ,
3827 25, 50, 100, 100, parent, 0, 0, NULL);
3828 ShowWindow( parent, SW_SHOW);
3829 UpdateWindow( parent);
3830 GetClientRect( hwnd1, &rc);
3832 SetRectRgn( clipping, 10, 10, 90, 90);
3833 hdc = GetDC( hwnd1);
3834 /* for a visual touch */
3835 TextOut( hdc, 0,10, "0123456789", 10);
3836 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
3837 if (winetest_debug > 0) dump_region(hrgn);
3838 /* create a region with what is expected */
3839 SetRectRgn( exprgn, 39,0,49,74);
3840 SetRectRgn( tmprgn, 88,79,98,93);
3841 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3842 SetRectRgn( tmprgn, 0,93,98,98);
3843 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3844 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3845 trace("update rect is %d,%d - %d,%d\n",
3846 rcu.left,rcu.top,rcu.right,rcu.bottom);
3847 /* now with clipping region */
3848 SelectClipRgn( hdc, clipping);
3849 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu);
3850 if (winetest_debug > 0) dump_region(hrgn);
3851 /* create a region with what is expected */
3852 SetRectRgn( exprgn, 39,10,49,74);
3853 SetRectRgn( tmprgn, 80,79,90,85);
3854 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3855 SetRectRgn( tmprgn, 10,85,90,90);
3856 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3857 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3858 trace("update rect is %d,%d - %d,%d\n",
3859 rcu.left,rcu.top,rcu.right,rcu.bottom);
3860 ReleaseDC( hwnd1, hdc);
3862 /* test scrolling a window with an update region */
3863 DestroyWindow( hwnd2);
3864 ValidateRect( hwnd1, NULL);
3865 SetRect( &rc, 40,40, 50,50);
3866 InvalidateRect( hwnd1, &rc, 1);
3867 GetClientRect( hwnd1, &rc);
3869 ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu,
3870 SW_SCROLLCHILDREN | SW_INVALIDATE);
3871 if (winetest_debug > 0) dump_region(hrgn);
3872 SetRectRgn( exprgn, 88,0,98,98);
3873 SetRectRgn( tmprgn, 30, 40, 50, 50);
3874 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3875 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3877 /* clear an update region */
3878 UpdateWindow( hwnd1 );
3880 SetRect( &rc, 0,40, 100,60);
3881 SetRect( &cliprc, 0,0, 100,100);
3882 ScrollWindowEx( hwnd1, 0, -25, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
3883 if (winetest_debug > 0) dump_region( hrgn );
3884 SetRectRgn( exprgn, 0, 40, 98, 60 );
3885 ok( EqualRgn( exprgn, hrgn), "wrong update region in excessive scroll\n");
3887 /* now test ScrollWindowEx with a combination of
3888 * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */
3889 /* make hwnd2 the child of hwnd1 */
3890 hwnd2 = CreateWindowExA(0, "static", NULL,
3891 WS_CHILD| WS_VISIBLE | WS_BORDER ,
3892 50, 50, 100, 100, hwnd1, 0, 0, NULL);
3893 SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS);
3894 GetClientRect( hwnd1, &rc);
3897 /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */
3898 SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
3899 ValidateRect( hwnd1, NULL);
3900 ValidateRect( hwnd2, NULL);
3901 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu,
3902 SW_SCROLLCHILDREN | SW_INVALIDATE);
3903 if (winetest_debug > 0) dump_region(hrgn);
3904 SetRectRgn( exprgn, 88,0,98,88);
3905 SetRectRgn( tmprgn, 0,88,98,98);
3906 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3907 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3909 /* SW_SCROLLCHILDREN */
3910 SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
3911 ValidateRect( hwnd1, NULL);
3912 ValidateRect( hwnd2, NULL);
3913 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE);
3914 if (winetest_debug > 0) dump_region(hrgn);
3915 /* expected region is the same as in previous test */
3916 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3918 /* no SW_SCROLLCHILDREN */
3919 SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN );
3920 ValidateRect( hwnd1, NULL);
3921 ValidateRect( hwnd2, NULL);
3922 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
3923 if (winetest_debug > 0) dump_region(hrgn);
3924 /* expected region is the same as in previous test */
3925 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3927 /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */
3928 SetWindowLong( hwnd1, GWL_STYLE, GetWindowLong( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN );
3929 ValidateRect( hwnd1, NULL);
3930 ValidateRect( hwnd2, NULL);
3931 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE);
3932 if (winetest_debug > 0) dump_region(hrgn);
3933 SetRectRgn( exprgn, 88,0,98,20);
3934 SetRectRgn( tmprgn, 20,20,98,30);
3935 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3936 SetRectRgn( tmprgn, 20,30,30,88);
3937 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3938 SetRectRgn( tmprgn, 0,88,30,98);
3939 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR);
3940 ok( EqualRgn( exprgn, hrgn), "wrong update region\n");
3943 DeleteObject( hrgn);
3944 DeleteObject( exprgn);
3945 DeleteObject( tmprgn);
3946 DestroyWindow( hwnd1);
3947 DestroyWindow( hwnd2);
3950 /* couple of tests of return values of scrollbar functions
3951 * called on a scrollbarless window */
3952 static void test_scroll(void)
3957 HWND hwnd = CreateWindowExA(0, "Static", "Wine test window",
3958 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP,
3959 100, 100, 200, 200, 0, 0, 0, NULL);
3961 ret = GetScrollRange( hwnd, SB_HORZ, &min, &max);
3962 if (!ret) /* win9x */
3964 win_skip( "GetScrollRange doesn't work\n" );
3965 DestroyWindow( hwnd);
3968 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
3969 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
3970 si.cbSize = sizeof( si);
3971 si.fMask = SIF_PAGE;
3972 si.nPage = 0xdeadbeef;
3973 ret = GetScrollInfo( hwnd, SB_HORZ, &si);
3974 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
3975 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
3977 ret = GetScrollRange( hwnd, SB_VERT, &min, &max);
3978 ok( ret, "GetScrollRange returns FALSE\n");
3979 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min);
3980 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min);
3981 si.cbSize = sizeof( si);
3982 si.fMask = SIF_PAGE;
3983 si.nPage = 0xdeadbeef;
3984 ret = GetScrollInfo( hwnd, SB_VERT, &si);
3985 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret);
3986 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage);
3988 DestroyWindow( hwnd);
3991 static void test_scrolldc( HWND parent)
3994 HRGN exprgn, tmprgn, hrgn;
3995 RECT rc, rc2, rcu, cliprc;
3999 hrgn = CreateRectRgn(0,0,0,0);
4000 tmprgn = CreateRectRgn(0,0,0,0);
4001 exprgn = CreateRectRgn(0,0,0,0);
4003 hwnd1 = CreateWindowExA(0, "static", NULL,
4004 WS_CHILD| WS_VISIBLE,
4005 25, 50, 100, 100, parent, 0, 0, NULL);
4006 ShowWindow( parent, SW_SHOW);
4007 UpdateWindow( parent);
4008 flush_events( TRUE );
4009 GetClientRect( hwnd1, &rc);
4010 hdc = GetDC( hwnd1);
4011 /* paint the upper half of the window black */
4013 rc2.bottom = ( rc.top + rc.bottom) /2;
4014 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4015 /* clip region is the lower half */
4017 cliprc.top = (rc.top + rc.bottom) /2;
4018 /* test whether scrolled pixels are properly clipped */
4019 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
4020 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4021 /* this scroll should not cause any visible changes */
4022 ScrollDC( hdc, 5, -20, &rc, &cliprc, hrgn, &rcu);
4023 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1);
4024 ok ( colr == 0, "pixel should be black, color is %08x\n", colr);
4025 /* test with NULL clip rect */
4026 ScrollDC( hdc, 20, -20, &rc, NULL, hrgn, &rcu);
4027 /*FillRgn(hdc, hrgn, GetStockObject(WHITE_BRUSH));*/
4028 trace("update rect: %d,%d - %d,%d\n",
4029 rcu.left, rcu.top, rcu.right, rcu.bottom);
4030 if (winetest_debug > 0) dump_region(hrgn);
4031 SetRect(&rc2, 0, 0, 100, 100);
4032 ok(EqualRect(&rcu, &rc2), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n",
4033 rcu.left, rcu.top, rcu.right, rcu.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom);
4035 SetRectRgn( exprgn, 0, 0, 20, 80);
4036 SetRectRgn( tmprgn, 0, 80, 100, 100);
4037 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
4038 if (winetest_debug > 0) dump_region(exprgn);
4039 ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
4040 /* test clip rect > scroll rect */
4041 FillRect( hdc, &rc, GetStockObject(WHITE_BRUSH));
4043 InflateRect( &rc2, -(rc.right-rc.left)/4, -(rc.bottom-rc.top)/4);
4044 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH));
4045 ScrollDC( hdc, 10, 10, &rc2, &rc, hrgn, &rcu);
4046 SetRectRgn( exprgn, 25, 25, 75, 35);
4047 SetRectRgn( tmprgn, 25, 35, 35, 75);
4048 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR);
4049 ok(EqualRgn(exprgn, hrgn), "wrong update region\n");
4050 trace("update rect: %d,%d - %d,%d\n",
4051 rcu.left, rcu.top, rcu.right, rcu.bottom);
4052 if (winetest_debug > 0) dump_region(hrgn);
4056 DeleteObject(exprgn);
4057 DeleteObject(tmprgn);
4058 DestroyWindow(hwnd1);
4061 static void test_params(void)
4066 ok(!IsWindow(0), "IsWindow(0)\n");
4067 ok(!IsWindow(HWND_BROADCAST), "IsWindow(HWND_BROADCAST)\n");
4068 ok(!IsWindow(HWND_TOPMOST), "IsWindow(HWND_TOPMOST)\n");
4070 /* Just a param check */
4071 if (pGetMonitorInfoA)
4073 SetLastError(0xdeadbeef);
4074 rc = GetWindowText(hwndMain2, NULL, 1024);
4075 ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError());
4079 /* Skips actually on Win95 and NT4 */
4080 win_skip("Test would crash on Win95\n");
4083 SetLastError(0xdeadbeef);
4084 hwnd=CreateWindow("LISTBOX", "TestList",
4085 (LBS_STANDARD & ~LBS_SORT),
4087 NULL, (HMENU)1, NULL, 0);
4089 ok(!hwnd || broken(hwnd != NULL), /* w2k3 sp2 */
4090 "CreateWindow with invalid menu handle should fail\n");
4092 ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */
4093 GetLastError() == 0xdeadbeef, /* Win9x */
4094 "wrong last error value %d\n", GetLastError());
4097 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu)
4101 hwnd = CreateWindowEx(exStyle, class, class, style,
4108 trace("Failed to create window class=%s, style=0x%08x, exStyle=0x%08x\n", class, style, exStyle);
4111 ShowWindow(hwnd, SW_SHOW);
4113 test_nonclient_area(hwnd);
4116 DestroyWindow(hwnd);
4119 static BOOL AWR_init(void)
4123 class.style = CS_HREDRAW | CS_VREDRAW;
4124 class.lpfnWndProc = DefWindowProcA;
4125 class.cbClsExtra = 0;
4126 class.cbWndExtra = 0;
4127 class.hInstance = 0;
4128 class.hIcon = LoadIcon (0, IDI_APPLICATION);
4129 class.hCursor = LoadCursor (0, IDC_ARROW);
4130 class.hbrBackground = 0;
4131 class.lpszMenuName = 0;
4132 class.lpszClassName = szAWRClass;
4134 if (!RegisterClass (&class)) {
4135 ok(FALSE, "RegisterClass failed\n");
4139 hmenu = CreateMenu();
4142 ok(hmenu != 0, "Failed to create menu\n");
4143 ok(AppendMenu(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n");
4149 static void test_AWR_window_size(BOOL menu)
4153 WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME,
4156 WS_MINIMIZEBOX, WS_MAXIMIZEBOX,
4157 WS_HSCROLL, WS_VSCROLL
4161 WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE,
4164 /* These styles have problems on (at least) WinXP (SP2) and Wine */
4165 WS_EX_DLGMODALFRAME,
4172 /* A exhaustive check of all the styles takes too long
4173 * so just do a (hopefully representative) sample
4175 for (i = 0; i < COUNTOF(styles); ++i)
4176 test_AWRwindow(szAWRClass, styles[i], 0, menu);
4177 for (i = 0; i < COUNTOF(exStyles); ++i) {
4178 test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu);
4179 test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu);
4184 #define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM))
4186 static void test_AdjustWindowRect(void)
4191 SHOWSYSMETRIC(SM_CYCAPTION);
4192 SHOWSYSMETRIC(SM_CYSMCAPTION);
4193 SHOWSYSMETRIC(SM_CYMENU);
4194 SHOWSYSMETRIC(SM_CXEDGE);
4195 SHOWSYSMETRIC(SM_CYEDGE);
4196 SHOWSYSMETRIC(SM_CXVSCROLL);
4197 SHOWSYSMETRIC(SM_CYHSCROLL);
4198 SHOWSYSMETRIC(SM_CXFRAME);
4199 SHOWSYSMETRIC(SM_CYFRAME);
4200 SHOWSYSMETRIC(SM_CXDLGFRAME);
4201 SHOWSYSMETRIC(SM_CYDLGFRAME);
4202 SHOWSYSMETRIC(SM_CXBORDER);
4203 SHOWSYSMETRIC(SM_CYBORDER);
4205 test_AWR_window_size(FALSE);
4206 test_AWR_window_size(TRUE);
4210 #undef SHOWSYSMETRIC
4213 /* Global variables to trigger exit from loop */
4214 static int redrawComplete, WMPAINT_count;
4216 static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4221 trace("doing WM_PAINT %d\n", WMPAINT_count);
4223 if (WMPAINT_count > 10 && redrawComplete == 0) {
4225 BeginPaint(hwnd, &ps);
4226 EndPaint(hwnd, &ps);
4231 return DefWindowProc(hwnd, msg, wparam, lparam);
4234 /* Ensure we exit from RedrawNow regardless of invalidated area */
4235 static void test_redrawnow(void)
4240 cls.style = CS_DBLCLKS;
4241 cls.lpfnWndProc = redraw_window_procA;
4244 cls.hInstance = GetModuleHandleA(0);
4246 cls.hCursor = LoadCursorA(0, IDC_ARROW);
4247 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4248 cls.lpszMenuName = NULL;
4249 cls.lpszClassName = "RedrawWindowClass";
4251 if(!RegisterClassA(&cls)) {
4252 trace("Register failed %d\n", GetLastError());
4256 hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
4257 CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL);
4259 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4260 ShowWindow(hwndMain, SW_SHOW);
4261 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4262 RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN);
4263 ok( WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */
4264 "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count);
4265 redrawComplete = TRUE;
4266 ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count);
4269 DestroyWindow( hwndMain);
4272 struct parentdc_stat {
4278 struct parentdc_test {
4279 struct parentdc_stat main, main_todo;
4280 struct parentdc_stat child1, child1_todo;
4281 struct parentdc_stat child2, child2_todo;
4284 static LRESULT WINAPI parentdc_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4289 struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
4294 GetClientRect(hwnd, &rc);
4295 CopyRect(&t->client, &rc);
4296 GetWindowRect(hwnd, &rc);
4297 trace("WM_PAINT: hwnd %p, client rect (%d,%d)-(%d,%d), window rect (%d,%d)-(%d,%d)\n", hwnd,
4298 t->client.left, t->client.top, t->client.right, t->client.bottom,
4299 rc.left, rc.top, rc.right, rc.bottom);
4300 BeginPaint(hwnd, &ps);
4301 CopyRect(&t->paint, &ps.rcPaint);
4302 GetClipBox(ps.hdc, &rc);
4303 CopyRect(&t->clip, &rc);
4304 trace("clip rect (%d,%d)-(%d,%d), paint rect (%d,%d)-(%d,%d)\n",
4305 rc.left, rc.top, rc.right, rc.bottom,
4306 ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
4307 EndPaint(hwnd, &ps);
4310 return DefWindowProc(hwnd, msg, wparam, lparam);
4313 static void zero_parentdc_stat(struct parentdc_stat *t)
4315 SetRectEmpty(&t->client);
4316 SetRectEmpty(&t->clip);
4317 SetRectEmpty(&t->paint);
4320 static void zero_parentdc_test(struct parentdc_test *t)
4322 zero_parentdc_stat(&t->main);
4323 zero_parentdc_stat(&t->child1);
4324 zero_parentdc_stat(&t->child2);
4327 #define parentdc_field_ok(t, w, r, f, got) \
4328 ok (t.w.r.f==got.w.r.f, "window " #w ", rect " #r ", field " #f \
4329 ": expected %d, got %d\n", \
4332 #define parentdc_todo_field_ok(t, w, r, f, got) \
4333 if (t.w##_todo.r.f) todo_wine { parentdc_field_ok(t, w, r, f, got); } \
4334 else parentdc_field_ok(t, w, r, f, got)
4336 #define parentdc_rect_ok(t, w, r, got) \
4337 parentdc_todo_field_ok(t, w, r, left, got); \
4338 parentdc_todo_field_ok(t, w, r, top, got); \
4339 parentdc_todo_field_ok(t, w, r, right, got); \
4340 parentdc_todo_field_ok(t, w, r, bottom, got);
4342 #define parentdc_win_ok(t, w, got) \
4343 parentdc_rect_ok(t, w, client, got); \
4344 parentdc_rect_ok(t, w, clip, got); \
4345 parentdc_rect_ok(t, w, paint, got);
4347 #define parentdc_ok(t, got) \
4348 parentdc_win_ok(t, main, got); \
4349 parentdc_win_ok(t, child1, got); \
4350 parentdc_win_ok(t, child2, got);
4352 static void test_csparentdc(void)
4354 WNDCLASSA clsMain, cls;
4355 HWND hwndMain, hwnd1, hwnd2;
4358 struct parentdc_test test_answer;
4360 #define nothing_todo {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}
4361 const struct parentdc_test test1 =
4363 {{0, 0, 150, 150}, {0, 0, 150, 150}, {0, 0, 150, 150}}, nothing_todo,
4364 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
4365 {{0, 0, 40, 40}, {-40, -40, 110, 110}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
4368 const struct parentdc_test test2 =
4370 {{0, 0, 150, 150}, {0, 0, 50, 50}, {0, 0, 50, 50}}, nothing_todo,
4371 {{0, 0, 40, 40}, {-20, -20, 30, 30}, {0, 0, 30, 30}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
4372 {{0, 0, 40, 40}, {-40, -40, 10, 10}, {0, 0, 10, 10}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
4375 const struct parentdc_test test3 =
4377 {{0, 0, 150, 150}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
4378 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4379 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4382 const struct parentdc_test test4 =
4384 {{0, 0, 150, 150}, {40, 40, 50, 50}, {40, 40, 50, 50}}, nothing_todo,
4385 {{0, 0, 40, 40}, {20, 20, 30, 30}, {20, 20, 30, 30}}, nothing_todo,
4386 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
4389 const struct parentdc_test test5 =
4391 {{0, 0, 150, 150}, {20, 20, 60, 60}, {20, 20, 60, 60}}, nothing_todo,
4392 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
4393 {{0, 0, 40, 40}, {-20, -20, 20, 20}, {0, 0, 20, 20}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}},
4396 const struct parentdc_test test6 =
4398 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4399 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo,
4400 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4403 const struct parentdc_test test7 =
4405 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4406 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}},
4407 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo,
4411 clsMain.style = CS_DBLCLKS;
4412 clsMain.lpfnWndProc = parentdc_window_procA;
4413 clsMain.cbClsExtra = 0;
4414 clsMain.cbWndExtra = 0;
4415 clsMain.hInstance = GetModuleHandleA(0);
4417 clsMain.hCursor = LoadCursorA(0, IDC_ARROW);
4418 clsMain.hbrBackground = GetStockObject(WHITE_BRUSH);
4419 clsMain.lpszMenuName = NULL;
4420 clsMain.lpszClassName = "ParentDcMainWindowClass";
4422 if(!RegisterClassA(&clsMain)) {
4423 trace("Register failed %d\n", GetLastError());
4427 cls.style = CS_DBLCLKS | CS_PARENTDC;
4428 cls.lpfnWndProc = parentdc_window_procA;
4431 cls.hInstance = GetModuleHandleA(0);
4433 cls.hCursor = LoadCursorA(0, IDC_ARROW);
4434 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4435 cls.lpszMenuName = NULL;
4436 cls.lpszClassName = "ParentDcWindowClass";
4438 if(!RegisterClassA(&cls)) {
4439 trace("Register failed %d\n", GetLastError());
4443 SetRect(&rc, 0, 0, 150, 150);
4444 AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
4445 hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW,
4446 CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL);
4447 SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main);
4448 hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD,
4449 20, 20, 40, 40, hwndMain, NULL, 0, NULL);
4450 SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1);
4451 hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD,
4452 40, 40, 40, 40, hwndMain, NULL, 0, NULL);
4453 SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2);
4454 ShowWindow(hwndMain, SW_SHOW);
4455 ShowWindow(hwnd1, SW_SHOW);
4456 ShowWindow(hwnd2, SW_SHOW);
4457 SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
4458 flush_events( TRUE );
4460 zero_parentdc_test(&test_answer);
4461 InvalidateRect(hwndMain, NULL, TRUE);
4462 flush_events( TRUE );
4463 parentdc_ok(test1, test_answer);
4465 zero_parentdc_test(&test_answer);
4466 SetRect(&rc, 0, 0, 50, 50);
4467 InvalidateRect(hwndMain, &rc, TRUE);
4468 flush_events( TRUE );
4469 parentdc_ok(test2, test_answer);
4471 zero_parentdc_test(&test_answer);
4472 SetRect(&rc, 0, 0, 10, 10);
4473 InvalidateRect(hwndMain, &rc, TRUE);
4474 flush_events( TRUE );
4475 parentdc_ok(test3, test_answer);
4477 zero_parentdc_test(&test_answer);
4478 SetRect(&rc, 40, 40, 50, 50);
4479 InvalidateRect(hwndMain, &rc, TRUE);
4480 flush_events( TRUE );
4481 parentdc_ok(test4, test_answer);
4483 zero_parentdc_test(&test_answer);
4484 SetRect(&rc, 20, 20, 60, 60);
4485 InvalidateRect(hwndMain, &rc, TRUE);
4486 flush_events( TRUE );
4487 parentdc_ok(test5, test_answer);
4489 zero_parentdc_test(&test_answer);
4490 SetRect(&rc, 0, 0, 10, 10);
4491 InvalidateRect(hwnd1, &rc, TRUE);
4492 flush_events( TRUE );
4493 parentdc_ok(test6, test_answer);
4495 zero_parentdc_test(&test_answer);
4496 SetRect(&rc, -5, -5, 65, 65);
4497 InvalidateRect(hwnd1, &rc, TRUE);
4498 flush_events( TRUE );
4499 parentdc_ok(test7, test_answer);
4501 DestroyWindow(hwndMain);
4502 DestroyWindow(hwnd1);
4503 DestroyWindow(hwnd2);
4506 static LRESULT WINAPI def_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4508 return DefWindowProcA(hwnd, msg, wparam, lparam);
4511 static LRESULT WINAPI def_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
4513 return DefWindowProcW(hwnd, msg, wparam, lparam);
4516 static void test_IsWindowUnicode(void)
4518 static const char ansi_class_nameA[] = "ansi class name";
4519 static const WCHAR ansi_class_nameW[] = {'a','n','s','i',' ','c','l','a','s','s',' ','n','a','m','e',0};
4520 static const char unicode_class_nameA[] = "unicode class name";
4521 static const WCHAR unicode_class_nameW[] = {'u','n','i','c','o','d','e',' ','c','l','a','s','s',' ','n','a','m','e',0};
4526 memset(&classW, 0, sizeof(classW));
4527 classW.hInstance = GetModuleHandleA(0);
4528 classW.lpfnWndProc = def_window_procW;
4529 classW.lpszClassName = unicode_class_nameW;
4530 if (!RegisterClassW(&classW)) return; /* this catches Win9x as well */
4532 memset(&classA, 0, sizeof(classA));
4533 classA.hInstance = GetModuleHandleA(0);
4534 classA.lpfnWndProc = def_window_procA;
4535 classA.lpszClassName = ansi_class_nameA;
4536 assert(RegisterClassA(&classA));
4538 /* unicode class: window proc */
4539 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
4540 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4543 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4544 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
4545 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4546 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
4547 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4549 DestroyWindow(hwnd);
4551 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
4552 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4555 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4556 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
4557 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4558 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
4559 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4561 DestroyWindow(hwnd);
4563 /* ansi class: window proc */
4564 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
4565 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4568 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4569 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
4570 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4571 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
4572 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4574 DestroyWindow(hwnd);
4576 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
4577 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4580 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4581 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW);
4582 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4583 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA);
4584 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4586 DestroyWindow(hwnd);
4588 /* unicode class: class proc */
4589 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP,
4590 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4593 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4594 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
4595 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4596 /* do not restore class window proc back to unicode */
4598 DestroyWindow(hwnd);
4600 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP,
4601 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4604 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4605 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
4606 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4608 DestroyWindow(hwnd);
4610 /* ansi class: class proc */
4611 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP,
4612 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4615 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4616 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW);
4617 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n");
4618 /* do not restore class window proc back to ansi */
4620 DestroyWindow(hwnd);
4622 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP,
4623 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL);
4626 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4627 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA);
4628 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n");
4630 DestroyWindow(hwnd);
4633 static LRESULT CALLBACK minmax_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
4637 if (msg != WM_GETMINMAXINFO)
4638 return DefWindowProc(hwnd, msg, wp, lp);
4640 minmax = (MINMAXINFO *)lp;
4642 if ((GetWindowLong(hwnd, GWL_STYLE) & WS_CHILD))
4644 minmax->ptReserved.x = 0;
4645 minmax->ptReserved.y = 0;
4646 minmax->ptMaxSize.x = 400;
4647 minmax->ptMaxSize.y = 400;
4648 minmax->ptMaxPosition.x = 300;
4649 minmax->ptMaxPosition.y = 300;
4650 minmax->ptMaxTrackSize.x = 200;
4651 minmax->ptMaxTrackSize.y = 200;
4652 minmax->ptMinTrackSize.x = 100;
4653 minmax->ptMinTrackSize.y = 100;
4656 DefWindowProc(hwnd, msg, wp, lp);
4660 static int expected_cx, expected_cy;
4661 static RECT expected_rect, broken_rect;
4663 static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
4667 case WM_GETMINMAXINFO:
4670 GetWindowRect( hwnd, &rect );
4671 ok( !rect.left && !rect.top && !rect.right && !rect.bottom,
4672 "wrong rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
4673 return DefWindowProc(hwnd, msg, wp, lp);
4678 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
4680 GetWindowRect( hwnd, &rect );
4681 trace( "hwnd %p msg %x size %dx%d rect %d,%d-%d,%d\n",
4682 hwnd, msg, cs->cx, cs->cy, rect.left, rect.top, rect.right, rect.bottom );
4683 ok( cs->cx == expected_cx || broken(cs->cx == (short)expected_cx),
4684 "wrong x size %d/%d\n", cs->cx, expected_cx );
4685 ok( cs->cy == expected_cy || broken(cs->cy == (short)expected_cy),
4686 "wrong y size %d/%d\n", cs->cy, expected_cy );
4687 ok( (rect.right - rect.left == expected_rect.right - expected_rect.left &&
4688 rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) ||
4689 (rect.right - rect.left == min( 65535, expected_rect.right - expected_rect.left ) &&
4690 rect.bottom - rect.top == min( 65535, expected_rect.bottom - expected_rect.top )) ||
4691 broken( rect.right - rect.left == broken_rect.right - broken_rect.left &&
4692 rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) ||
4693 broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left &&
4694 rect.bottom - rect.top == (short)broken_rect.bottom - (short)broken_rect.top),
4695 "wrong rect %d,%d-%d,%d / %d,%d-%d,%d\n",
4696 rect.left, rect.top, rect.right, rect.bottom,
4697 expected_rect.left, expected_rect.top, expected_rect.right, expected_rect.bottom );
4698 return DefWindowProc(hwnd, msg, wp, lp);
4702 RECT rect, *r = (RECT *)lp;
4703 GetWindowRect( hwnd, &rect );
4704 ok( !memcmp( &rect, r, sizeof(rect) ),
4705 "passed rect %d,%d-%d,%d doesn't match window rect %d,%d-%d,%d\n",
4706 r->left, r->top, r->right, r->bottom, rect.left, rect.top, rect.right, rect.bottom );
4707 return DefWindowProc(hwnd, msg, wp, lp);
4710 return DefWindowProc(hwnd, msg, wp, lp);
4714 static void test_CreateWindow(void)
4723 #define expect_menu(window, menu) \
4724 SetLastError(0xdeadbeef); \
4725 res = (GetMenu(window) == (HMENU)menu); \
4726 ok(res, "GetMenu error %d\n", GetLastError())
4728 #define expect_style(window, style)\
4729 ok((ULONG)GetWindowLong(window, GWL_STYLE) == (style), "expected style %x != %x\n", (LONG)(style), GetWindowLong(window, GWL_STYLE))
4731 #define expect_ex_style(window, ex_style)\
4732 ok((ULONG)GetWindowLong(window, GWL_EXSTYLE) == (ex_style), "expected ex_style %x != %x\n", (LONG)(ex_style), GetWindowLong(window, GWL_EXSTYLE))
4734 #define expect_gle_broken_9x(gle)\
4735 ok(GetLastError() == gle ||\
4736 broken(GetLastError() == 0xdeadbeef),\
4737 "IsMenu set error %d\n", GetLastError())
4739 hmenu = CreateMenu();
4741 parent = GetDesktopWindow();
4742 assert(parent != 0);
4744 SetLastError(0xdeadbeef);
4745 res = IsMenu(hmenu);
4746 ok(res, "IsMenu error %d\n", GetLastError());
4749 SetLastError(0xdeadbeef);
4750 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD,
4751 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4752 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4753 expect_menu(hwnd, 1);
4754 expect_style(hwnd, WS_CHILD);
4755 expect_ex_style(hwnd, WS_EX_APPWINDOW);
4756 DestroyWindow(hwnd);
4758 SetLastError(0xdeadbeef);
4759 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_CAPTION,
4760 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4761 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4762 expect_menu(hwnd, 1);
4763 expect_style(hwnd, WS_CHILD | WS_CAPTION);
4764 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
4765 DestroyWindow(hwnd);
4767 SetLastError(0xdeadbeef);
4768 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD,
4769 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4770 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4771 expect_menu(hwnd, 1);
4772 expect_style(hwnd, WS_CHILD);
4773 expect_ex_style(hwnd, 0);
4774 DestroyWindow(hwnd);
4776 SetLastError(0xdeadbeef);
4777 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_CAPTION,
4778 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4779 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4780 expect_menu(hwnd, 1);
4781 expect_style(hwnd, WS_CHILD | WS_CAPTION);
4782 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
4783 DestroyWindow(hwnd);
4786 SetLastError(0xdeadbeef);
4787 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
4788 0, 0, 100, 100, parent, hmenu, 0, NULL);
4789 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4790 expect_menu(hwnd, hmenu);
4791 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
4792 expect_ex_style(hwnd, WS_EX_APPWINDOW);
4793 DestroyWindow(hwnd);
4794 SetLastError(0xdeadbeef);
4795 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4796 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4798 hmenu = CreateMenu();
4800 SetLastError(0xdeadbeef);
4801 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP | WS_CAPTION,
4802 0, 0, 100, 100, parent, hmenu, 0, NULL);
4803 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4804 expect_menu(hwnd, hmenu);
4805 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
4806 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
4807 DestroyWindow(hwnd);
4808 SetLastError(0xdeadbeef);
4809 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4810 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4812 hmenu = CreateMenu();
4814 SetLastError(0xdeadbeef);
4815 hwnd = CreateWindowEx(0, "static", NULL, WS_POPUP,
4816 0, 0, 100, 100, parent, hmenu, 0, NULL);
4817 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4818 expect_menu(hwnd, hmenu);
4819 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS);
4820 expect_ex_style(hwnd, 0);
4821 DestroyWindow(hwnd);
4822 SetLastError(0xdeadbeef);
4823 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4824 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4826 hmenu = CreateMenu();
4828 SetLastError(0xdeadbeef);
4829 hwnd = CreateWindowEx(0, "static", NULL, WS_POPUP | WS_CAPTION,
4830 0, 0, 100, 100, parent, hmenu, 0, NULL);
4831 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4832 expect_menu(hwnd, hmenu);
4833 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
4834 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
4835 DestroyWindow(hwnd);
4836 SetLastError(0xdeadbeef);
4837 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4838 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4840 /* WS_CHILD | WS_POPUP */
4841 SetLastError(0xdeadbeef);
4842 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
4843 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4844 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
4845 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4847 DestroyWindow(hwnd);
4849 hmenu = CreateMenu();
4851 SetLastError(0xdeadbeef);
4852 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP,
4853 0, 0, 100, 100, parent, hmenu, 0, NULL);
4854 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4855 expect_menu(hwnd, hmenu);
4856 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
4857 expect_ex_style(hwnd, WS_EX_APPWINDOW);
4858 DestroyWindow(hwnd);
4859 SetLastError(0xdeadbeef);
4860 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4861 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4863 SetLastError(0xdeadbeef);
4864 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
4865 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4866 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
4867 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4869 DestroyWindow(hwnd);
4871 hmenu = CreateMenu();
4873 SetLastError(0xdeadbeef);
4874 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
4875 0, 0, 100, 100, parent, hmenu, 0, NULL);
4876 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4877 expect_menu(hwnd, hmenu);
4878 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
4879 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
4880 DestroyWindow(hwnd);
4881 SetLastError(0xdeadbeef);
4882 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4883 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4885 SetLastError(0xdeadbeef);
4886 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP,
4887 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4888 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
4889 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4891 DestroyWindow(hwnd);
4893 hmenu = CreateMenu();
4895 SetLastError(0xdeadbeef);
4896 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP,
4897 0, 0, 100, 100, parent, hmenu, 0, NULL);
4898 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4899 expect_menu(hwnd, hmenu);
4900 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS);
4901 expect_ex_style(hwnd, 0);
4902 DestroyWindow(hwnd);
4903 SetLastError(0xdeadbeef);
4904 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4905 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4907 SetLastError(0xdeadbeef);
4908 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
4909 0, 0, 100, 100, parent, (HMENU)1, 0, NULL);
4910 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n");
4911 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4913 DestroyWindow(hwnd);
4915 hmenu = CreateMenu();
4917 SetLastError(0xdeadbeef);
4918 hwnd = CreateWindowEx(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION,
4919 0, 0, 100, 100, parent, hmenu, 0, NULL);
4920 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4921 expect_menu(hwnd, hmenu);
4922 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS);
4923 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
4924 DestroyWindow(hwnd);
4925 SetLastError(0xdeadbeef);
4926 ok(!IsMenu(hmenu), "IsMenu should fail\n");
4927 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE);
4929 /* test child window sizing */
4931 cls.lpfnWndProc = minmax_wnd_proc;
4934 cls.hInstance = GetModuleHandle(0);
4936 cls.hCursor = LoadCursorA(0, IDC_ARROW);
4937 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
4938 cls.lpszMenuName = NULL;
4939 cls.lpszClassName = "MinMax_WndClass";
4940 RegisterClass(&cls);
4942 SetLastError(0xdeadbeef);
4943 parent = CreateWindowEx(0, "MinMax_WndClass", NULL, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
4944 0, 0, 100, 100, 0, 0, 0, NULL);
4945 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
4946 expect_menu(parent, 0);
4947 expect_style(parent, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPSIBLINGS);
4948 expect_ex_style(parent, WS_EX_WINDOWEDGE);
4950 memset(&minmax, 0, sizeof(minmax));
4951 SendMessage(parent, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
4952 SetRect(&rc_minmax, 0, 0, minmax.ptMaxSize.x, minmax.ptMaxSize.y);
4953 ok(IsRectEmpty(&rc_minmax), "ptMaxSize is not empty\n");
4954 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
4955 ok(IsRectEmpty(&rc_minmax), "ptMaxTrackSize is not empty\n");
4957 GetWindowRect(parent, &rc);
4958 ok(!IsRectEmpty(&rc), "parent window rect is empty\n");
4959 GetClientRect(parent, &rc);
4960 ok(!IsRectEmpty(&rc), "parent client rect is empty\n");
4962 InflateRect(&rc, 200, 200);
4963 trace("creating child with rect (%d,%d-%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom);
4965 SetLastError(0xdeadbeef);
4966 hwnd = CreateWindowEx(0, "MinMax_WndClass", NULL, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME,
4967 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
4968 parent, (HMENU)1, 0, NULL);
4969 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError());
4970 expect_menu(hwnd, 1);
4971 expect_style(hwnd, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
4972 expect_ex_style(hwnd, WS_EX_WINDOWEDGE);
4974 memset(&minmax, 0, sizeof(minmax));
4975 SendMessage(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax);
4976 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y);
4978 GetWindowRect(hwnd, &rc);
4979 OffsetRect(&rc, -rc.left, -rc.top);
4980 ok(EqualRect(&rc, &rc_minmax), "rects don't match: (%d,%d-%d,%d) and (%d,%d-%d,%d)\n",
4981 rc.left, rc.top, rc.right, rc.bottom,
4982 rc_minmax.left, rc_minmax.top, rc_minmax.right, rc_minmax.bottom);
4983 DestroyWindow(hwnd);
4985 cls.lpfnWndProc = winsizes_wnd_proc;
4986 cls.lpszClassName = "Sizes_WndClass";
4987 RegisterClass(&cls);
4989 expected_cx = expected_cy = 200000;
4990 SetRect( &expected_rect, 0, 0, 200000, 200000 );
4991 broken_rect = expected_rect;
4992 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL);
4993 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
4994 GetClientRect( hwnd, &rc );
4995 ok( rc.right == 200000 || rc.right == 65535 || broken(rc.right == (short)200000),
4996 "invalid rect right %u\n", rc.right );
4997 ok( rc.bottom == 200000 || rc.bottom == 65535 || broken(rc.bottom == (short)200000),
4998 "invalid rect bottom %u\n", rc.bottom );
4999 DestroyWindow(hwnd);
5001 expected_cx = expected_cy = -10;
5002 SetRect( &expected_rect, 0, 0, 0, 0 );
5003 SetRect( &broken_rect, 0, 0, -10, -10 );
5004 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL);
5005 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5006 GetClientRect( hwnd, &rc );
5007 ok( rc.right == 0, "invalid rect right %u\n", rc.right );
5008 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
5009 DestroyWindow(hwnd);
5011 expected_cx = expected_cy = -200000;
5012 SetRect( &expected_rect, 0, 0, 0, 0 );
5013 SetRect( &broken_rect, 0, 0, -200000, -200000 );
5014 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL);
5015 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5016 GetClientRect( hwnd, &rc );
5017 ok( rc.right == 0, "invalid rect right %u\n", rc.right );
5018 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom );
5019 DestroyWindow(hwnd);
5021 /* we need a parent at 0,0 so that child coordinates match */
5022 DestroyWindow(parent);
5023 parent = CreateWindowEx(0, "MinMax_WndClass", NULL, WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL);
5024 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError());
5027 expected_cy = 0x7fffffff;
5028 SetRect( &expected_rect, 10, 10, 110, 0x7fffffff );
5029 SetRect( &broken_rect, 10, 10, 110, 0x7fffffffU + 10 );
5030 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 10, 10, 100, 0x7fffffff, parent, 0, 0, NULL);
5031 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5032 GetClientRect( hwnd, &rc );
5033 ok( rc.right == 100, "invalid rect right %u\n", rc.right );
5034 ok( rc.bottom == 0x7fffffff - 10 || rc.bottom ==65535 || broken(rc.bottom == 0),
5035 "invalid rect bottom %u\n", rc.bottom );
5036 DestroyWindow(hwnd);
5038 expected_cx = 0x7fffffff;
5039 expected_cy = 0x7fffffff;
5040 SetRect( &expected_rect, 20, 10, 0x7fffffff, 0x7fffffff );
5041 SetRect( &broken_rect, 20, 10, 0x7fffffffU + 20, 0x7fffffffU + 10 );
5042 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL);
5043 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5044 GetClientRect( hwnd, &rc );
5045 ok( rc.right == 0x7fffffff - 20 || rc.right == 65535 || broken(rc.right == 0),
5046 "invalid rect right %u\n", rc.right );
5047 ok( rc.bottom == 0x7fffffff - 10 || rc.right == 65535 || broken(rc.bottom == 0),
5048 "invalid rect bottom %u\n", rc.bottom );
5049 DestroyWindow(hwnd);
5051 /* top level window */
5052 expected_cx = expected_cy = 200000;
5053 SetRect( &expected_rect, 0, 0, GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK) );
5054 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_OVERLAPPEDWINDOW, 300000, 300000, 200000, 200000, 0, 0, 0, NULL);
5055 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5056 GetClientRect( hwnd, &rc );
5057 ok( rc.right <= expected_cx, "invalid rect right %u\n", rc.right );
5058 ok( rc.bottom <= expected_cy, "invalid rect bottom %u\n", rc.bottom );
5059 DestroyWindow(hwnd);
5061 if (pGetLayout && pSetLayout)
5063 HDC hdc = GetDC( parent );
5064 pSetLayout( hdc, LAYOUT_RTL );
5065 if (pGetLayout( hdc ))
5067 ReleaseDC( parent, hdc );
5068 DestroyWindow( parent );
5069 SetLastError( 0xdeadbeef );
5070 parent = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP,
5071 0, 0, 100, 100, 0, 0, 0, NULL);
5072 ok( parent != 0, "creation failed err %u\n", GetLastError());
5073 expect_ex_style( parent, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
5074 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
5075 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5076 expect_ex_style( hwnd, WS_EX_LAYOUTRTL );
5077 DestroyWindow( hwnd );
5078 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 20, 20, parent, 0, 0, NULL);
5079 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5080 expect_ex_style( hwnd, 0 );
5081 DestroyWindow( hwnd );
5082 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT );
5083 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL);
5084 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5085 expect_ex_style( hwnd, 0 );
5086 DestroyWindow( hwnd );
5088 if (pGetProcessDefaultLayout && pSetProcessDefaultLayout)
5092 SetLastError( 0xdeadbeef );
5093 ok( !pGetProcessDefaultLayout( NULL ), "GetProcessDefaultLayout succeeded\n" );
5094 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() );
5095 SetLastError( 0xdeadbeef );
5096 ok( pGetProcessDefaultLayout( &layout ),
5097 "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5098 ok( layout == 0, "GetProcessDefaultLayout wrong layout %x\n", layout );
5099 SetLastError( 0xdeadbeef );
5100 ok( pSetProcessDefaultLayout( 7 ),
5101 "SetProcessDefaultLayout failed err %u\n", GetLastError ());
5102 ok( pGetProcessDefaultLayout( &layout ),
5103 "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5104 ok( layout == 7, "GetProcessDefaultLayout wrong layout %x\n", layout );
5105 SetLastError( 0xdeadbeef );
5106 ok( pSetProcessDefaultLayout( LAYOUT_RTL ),
5107 "SetProcessDefaultLayout failed err %u\n", GetLastError ());
5108 ok( pGetProcessDefaultLayout( &layout ),
5109 "GetProcessDefaultLayout failed err %u\n", GetLastError ());
5110 ok( layout == LAYOUT_RTL, "GetProcessDefaultLayout wrong layout %x\n", layout );
5111 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5112 0, 0, 100, 100, 0, 0, 0, NULL);
5113 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5114 expect_ex_style( hwnd, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL );
5115 DestroyWindow( hwnd );
5116 hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP,
5117 0, 0, 100, 100, parent, 0, 0, NULL);
5118 ok( hwnd != 0, "creation failed err %u\n", GetLastError());
5119 expect_ex_style( hwnd, WS_EX_APPWINDOW );
5120 DestroyWindow( hwnd );
5121 pSetProcessDefaultLayout( 0 );
5123 else win_skip( "SetProcessDefaultLayout not supported\n" );
5125 else win_skip( "SetLayout not supported\n" );
5127 else win_skip( "SetLayout not available\n" );
5129 DestroyWindow(parent);
5131 UnregisterClass("MinMax_WndClass", GetModuleHandle(0));
5132 UnregisterClass("Sizes_WndClass", GetModuleHandle(0));
5134 #undef expect_gle_broken_9x
5137 #undef expect_ex_style
5140 /* function that remembers whether the system the test is running on sets the
5141 * last error for user32 functions to make the tests stricter */
5142 static int check_error(DWORD actual, DWORD expected)
5144 static int sets_last_error = -1;
5145 if (sets_last_error == -1)
5146 sets_last_error = (actual != 0xdeadbeef);
5147 return (!sets_last_error && (actual == 0xdeadbeef)) || (actual == expected);
5150 static void test_SetWindowLong(void)
5153 WNDPROC old_window_procW;
5155 SetLastError(0xdeadbeef);
5156 retval = SetWindowLongPtr(NULL, GWLP_WNDPROC, 0);
5157 ok(!retval, "SetWindowLongPtr on invalid window handle should have returned 0 instead of 0x%lx\n", retval);
5158 ok(check_error(GetLastError(), ERROR_INVALID_WINDOW_HANDLE),
5159 "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instad of %d\n", GetLastError());
5161 SetLastError(0xdeadbeef);
5162 retval = SetWindowLongPtr(hwndMain, 0xdeadbeef, 0);
5163 ok(!retval, "SetWindowLongPtr on invalid index should have returned 0 instead of 0x%lx\n", retval);
5164 ok(check_error(GetLastError(), ERROR_INVALID_INDEX),
5165 "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instad of %d\n", GetLastError());
5167 SetLastError(0xdeadbeef);
5168 retval = SetWindowLongPtr(hwndMain, GWLP_WNDPROC, 0);
5169 ok((WNDPROC)retval == main_window_procA || broken(!retval), /* win9x */
5170 "SetWindowLongPtr on invalid window proc should have returned address of main_window_procA instead of 0x%lx\n", retval);
5171 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
5172 retval = GetWindowLongPtr(hwndMain, GWLP_WNDPROC);
5173 ok((WNDPROC)retval == main_window_procA,
5174 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
5175 ok(!IsWindowUnicode(hwndMain), "hwndMain shouldn't be Unicode\n");
5177 old_window_procW = (WNDPROC)GetWindowLongPtrW(hwndMain, GWLP_WNDPROC);
5178 SetLastError(0xdeadbeef);
5179 retval = SetWindowLongPtrW(hwndMain, GWLP_WNDPROC, 0);
5180 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED)
5182 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError());
5183 ok(retval != 0, "SetWindowLongPtr error %d\n", GetLastError());
5184 ok((WNDPROC)retval == old_window_procW,
5185 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval);
5186 ok(IsWindowUnicode(hwndMain), "hwndMain should now be Unicode\n");
5188 /* set it back to ANSI */
5189 SetWindowLongPtr(hwndMain, GWLP_WNDPROC, 0);
5193 static void test_ShowWindow(void)
5197 RECT rcMain, rc, rcMinimized;
5200 SetRect(&rcMain, 120, 120, 210, 210);
5202 hwnd = CreateWindowEx(0, "MainWindowClass", NULL,
5203 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
5204 WS_MAXIMIZEBOX | WS_POPUP,
5205 rcMain.left, rcMain.top,
5206 rcMain.right - rcMain.left, rcMain.bottom - rcMain.top,
5210 style = GetWindowLong(hwnd, GWL_STYLE);
5211 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5212 ok(!(style & WS_VISIBLE), "window should not be visible\n");
5213 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5214 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5215 GetWindowRect(hwnd, &rc);
5216 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5217 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5218 rc.left, rc.top, rc.right, rc.bottom);
5220 ret = ShowWindow(hwnd, SW_SHOW);
5221 ok(!ret, "not expected ret: %lu\n", ret);
5222 style = GetWindowLong(hwnd, GWL_STYLE);
5223 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5224 ok(style & WS_VISIBLE, "window should be visible\n");
5225 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5226 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5227 GetWindowRect(hwnd, &rc);
5228 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5229 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5230 rc.left, rc.top, rc.right, rc.bottom);
5232 ret = ShowWindow(hwnd, SW_MINIMIZE);
5233 ok(ret, "not expected ret: %lu\n", ret);
5234 style = GetWindowLong(hwnd, GWL_STYLE);
5235 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5236 ok(style & WS_VISIBLE, "window should be visible\n");
5237 ok(style & WS_MINIMIZE, "window should be minimized\n");
5238 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5239 GetWindowRect(hwnd, &rcMinimized);
5240 ok(!EqualRect(&rcMain, &rcMinimized), "rects shouldn't match\n");
5241 /* shouldn't be able to resize minized windows */
5242 ret = SetWindowPos(hwnd, 0, 0, 0,
5243 (rcMinimized.right - rcMinimized.left) * 2,
5244 (rcMinimized.bottom - rcMinimized.top) * 2,
5245 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
5246 ok(ret, "not expected ret: %lu\n", ret);
5247 GetWindowRect(hwnd, &rc);
5248 ok(EqualRect(&rc, &rcMinimized), "rects should match\n");
5250 ShowWindow(hwnd, SW_RESTORE);
5251 ok(ret, "not expected ret: %lu\n", ret);
5252 style = GetWindowLong(hwnd, GWL_STYLE);
5253 ok(!(style & WS_DISABLED), "window should not be disabled\n");
5254 ok(style & WS_VISIBLE, "window should be visible\n");
5255 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5256 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5257 GetWindowRect(hwnd, &rc);
5258 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5259 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5260 rc.left, rc.top, rc.right, rc.bottom);
5262 ret = EnableWindow(hwnd, FALSE);
5263 ok(!ret, "not expected ret: %lu\n", ret);
5264 style = GetWindowLong(hwnd, GWL_STYLE);
5265 ok(style & WS_DISABLED, "window should be disabled\n");
5267 ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
5268 ok(!ret, "not expected ret: %lu\n", ret);
5269 style = GetWindowLong(hwnd, GWL_STYLE);
5270 ok(style & WS_DISABLED, "window should be disabled\n");
5271 ok(style & WS_VISIBLE, "window should be visible\n");
5272 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5273 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5274 GetWindowRect(hwnd, &rc);
5275 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5276 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5277 rc.left, rc.top, rc.right, rc.bottom);
5279 ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
5280 ok(!ret, "not expected ret: %lu\n", ret);
5281 style = GetWindowLong(hwnd, GWL_STYLE);
5282 ok(style & WS_DISABLED, "window should be disabled\n");
5283 ok(style & WS_VISIBLE, "window should be visible\n");
5284 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5285 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5286 GetWindowRect(hwnd, &rc);
5287 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5288 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5289 rc.left, rc.top, rc.right, rc.bottom);
5291 ret = ShowWindow(hwnd, SW_MINIMIZE);
5292 ok(ret, "not expected ret: %lu\n", ret);
5293 style = GetWindowLong(hwnd, GWL_STYLE);
5294 ok(style & WS_DISABLED, "window should be disabled\n");
5295 ok(style & WS_VISIBLE, "window should be visible\n");
5296 ok(style & WS_MINIMIZE, "window should be minimized\n");
5297 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5298 GetWindowRect(hwnd, &rc);
5299 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
5301 ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
5302 ok(!ret, "not expected ret: %lu\n", ret);
5303 style = GetWindowLong(hwnd, GWL_STYLE);
5304 ok(style & WS_DISABLED, "window should be disabled\n");
5305 ok(style & WS_VISIBLE, "window should be visible\n");
5306 ok(style & WS_MINIMIZE, "window should be minimized\n");
5307 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5308 GetWindowRect(hwnd, &rc);
5309 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n");
5311 ret = ShowWindow(hwnd, SW_RESTORE);
5312 ok(ret, "not expected ret: %lu\n", ret);
5313 style = GetWindowLong(hwnd, GWL_STYLE);
5314 ok(style & WS_DISABLED, "window should be disabled\n");
5315 ok(style & WS_VISIBLE, "window should be visible\n");
5316 ok(!(style & WS_MINIMIZE), "window should not be minimized\n");
5317 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n");
5318 GetWindowRect(hwnd, &rc);
5319 ok(EqualRect(&rcMain, &rc), "expected (%d,%d)-(%d,%d), got (%d,%d)-(%d,%d)\n",
5320 rcMain.left, rcMain.top, rcMain.right, rcMain.bottom,
5321 rc.left, rc.top, rc.right, rc.bottom);
5323 ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
5324 ok(!ret, "not expected ret: %lu\n", ret);
5325 ok(IsWindow(hwnd), "window should exist\n");
5327 ret = EnableWindow(hwnd, TRUE);
5328 ok(ret, "not expected ret: %lu\n", ret);
5330 ret = DefWindowProc(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
5331 ok(!ret, "not expected ret: %lu\n", ret);
5332 ok(!IsWindow(hwnd), "window should not exist\n");
5335 static void test_gettext(void)
5338 LPCSTR clsname = "gettexttest";
5342 memset( &cls, 0, sizeof cls );
5343 cls.lpfnWndProc = DefWindowProc;
5344 cls.lpszClassName = clsname;
5345 cls.hInstance = GetModuleHandle(NULL);
5347 if (!RegisterClass( &cls )) return;
5349 hwnd = CreateWindow( clsname, "test text", WS_OVERLAPPED, 0, 0, 10, 10, 0, NULL, NULL, NULL);
5350 ok( hwnd != NULL, "window was null\n");
5352 r = SendMessage( hwnd, WM_GETTEXT, 0x10, 0x1000);
5353 ok( r == 0, "settext should return zero\n");
5355 r = SendMessage( hwnd, WM_GETTEXT, 0x10000, 0);
5356 ok( r == 0, "settext should return zero (%ld)\n", r);
5358 r = SendMessage( hwnd, WM_GETTEXT, 0xff000000, 0x1000);
5359 ok( r == 0, "settext should return zero (%ld)\n", r);
5361 r = SendMessage( hwnd, WM_GETTEXT, 0x1000, 0xff000000);
5362 ok( r == 0, "settext should return zero (%ld)\n", r);
5364 DestroyWindow(hwnd);
5365 UnregisterClass( clsname, NULL );
5369 static void test_GetUpdateRect(void)
5372 BOOL ret, parent_wm_paint, grandparent_wm_paint;
5374 HWND hgrandparent, hparent, hchild;
5376 static const char classNameA[] = "GetUpdateRectClass";
5378 hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW,
5379 0, 0, 100, 100, NULL, NULL, 0, NULL);
5381 hparent = CreateWindowA("static", "parent", WS_CHILD|WS_VISIBLE,
5382 0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
5384 hchild = CreateWindowA("static", "child", WS_CHILD|WS_VISIBLE,
5385 10, 10, 30, 30, hparent, NULL, 0, NULL);
5387 ShowWindow(hgrandparent, SW_SHOW);
5388 UpdateWindow(hgrandparent);
5389 flush_events( TRUE );
5391 ShowWindow(hchild, SW_HIDE);
5392 SetRect(&rc2, 0, 0, 0, 0);
5393 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
5394 ok(!ret, "GetUpdateRect returned not empty region\n");
5395 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
5396 rc1.left, rc1.top, rc1.right, rc1.bottom,
5397 rc2.left, rc2.top, rc2.right, rc2.bottom);
5399 SetRect(&rc2, 10, 10, 40, 40);
5400 ret = GetUpdateRect(hparent, &rc1, FALSE);
5401 ok(ret, "GetUpdateRect returned empty region\n");
5402 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
5403 rc1.left, rc1.top, rc1.right, rc1.bottom,
5404 rc2.left, rc2.top, rc2.right, rc2.bottom);
5406 parent_wm_paint = FALSE;
5407 grandparent_wm_paint = FALSE;
5408 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
5410 if (msg.message == WM_PAINT)
5412 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
5413 if (msg.hwnd == hparent) parent_wm_paint = TRUE;
5415 DispatchMessage(&msg);
5417 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
5418 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
5420 DestroyWindow(hgrandparent);
5423 cls.lpfnWndProc = DefWindowProcA;
5426 cls.hInstance = GetModuleHandleA(0);
5428 cls.hCursor = LoadCursorA(0, IDC_ARROW);
5429 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5430 cls.lpszMenuName = NULL;
5431 cls.lpszClassName = classNameA;
5433 if(!RegisterClassA(&cls)) {
5434 trace("Register failed %d\n", GetLastError());
5438 hgrandparent = CreateWindowA(classNameA, "grandparent", WS_OVERLAPPEDWINDOW,
5439 0, 0, 100, 100, NULL, NULL, 0, NULL);
5441 hparent = CreateWindowA(classNameA, "parent", WS_CHILD|WS_VISIBLE,
5442 0, 0, 100, 100, hgrandparent, NULL, 0, NULL);
5444 hchild = CreateWindowA(classNameA, "child", WS_CHILD|WS_VISIBLE,
5445 10, 10, 30, 30, hparent, NULL, 0, NULL);
5447 ShowWindow(hgrandparent, SW_SHOW);
5448 UpdateWindow(hgrandparent);
5449 flush_events( TRUE );
5451 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
5452 ok(!ret, "GetUpdateRect returned not empty region\n");
5454 ShowWindow(hchild, SW_HIDE);
5456 SetRect(&rc2, 0, 0, 0, 0);
5457 ret = GetUpdateRect(hgrandparent, &rc1, FALSE);
5458 ok(!ret, "GetUpdateRect returned not empty region\n");
5459 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
5460 rc1.left, rc1.top, rc1.right, rc1.bottom,
5461 rc2.left, rc2.top, rc2.right, rc2.bottom);
5463 SetRect(&rc2, 10, 10, 40, 40);
5464 ret = GetUpdateRect(hparent, &rc1, FALSE);
5465 ok(ret, "GetUpdateRect returned empty region\n");
5466 ok(EqualRect(&rc1, &rc2), "rects do not match (%d,%d,%d,%d) / (%d,%d,%d,%d)\n",
5467 rc1.left, rc1.top, rc1.right, rc1.bottom,
5468 rc2.left, rc2.top, rc2.right, rc2.bottom);
5470 parent_wm_paint = FALSE;
5471 grandparent_wm_paint = FALSE;
5472 while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
5474 if (msg.message == WM_PAINT)
5476 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE;
5477 if (msg.hwnd == hparent) parent_wm_paint = TRUE;
5479 DispatchMessage(&msg);
5481 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n");
5482 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n");
5484 DestroyWindow(hgrandparent);
5488 static LRESULT CALLBACK TestExposedRegion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
5496 const int waitTime = 2000;
5498 BeginPaint(hwnd, &ps);
5500 /* create and destroy window to create an exposed region on this window */
5501 win = CreateWindowA("static", "win", WS_VISIBLE,
5502 10,10,50,50, NULL, NULL, 0, NULL);
5505 waitResult = MsgWaitForMultipleObjects( 0, NULL, FALSE, waitTime, QS_PAINT );
5507 ValidateRect(hwnd, NULL);
5508 EndPaint(hwnd, &ps);
5510 if(waitResult != WAIT_TIMEOUT)
5512 GetUpdateRect(hwnd, &updateRect, FALSE);
5513 ok(IsRectEmpty(&updateRect), "Exposed rect should be empty\n");
5518 return DefWindowProc(hwnd, msg, wParam, lParam);
5521 static void test_Expose(void)
5526 memset(&cls, 0, sizeof(WNDCLASSA));
5527 cls.lpfnWndProc = TestExposedRegion_WndProc;
5528 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5529 cls.lpszClassName = "TestExposeClass";
5530 RegisterClassA(&cls);
5532 mw = CreateWindowA("TestExposeClass", "MainWindow", WS_VISIBLE|WS_OVERLAPPEDWINDOW,
5533 0, 0, 200, 100, NULL, NULL, 0, NULL);
5539 static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
5541 static UINT ncredrawflags;
5547 ncredrawflags = *(UINT *) (((CREATESTRUCT *)lParam)->lpCreateParams);
5550 RedrawWindow(hwnd, NULL, NULL, ncredrawflags);
5553 BeginPaint(hwnd, &ps);
5554 EndPaint(hwnd, &ps);
5557 return DefWindowProc(hwnd, msg, wParam, lParam);
5560 static void run_NCRedrawLoop(UINT flags)
5567 hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow",
5568 WS_OVERLAPPEDWINDOW, 0, 0, 200, 100,
5569 NULL, NULL, 0, &flags);
5570 ShowWindow(hwnd, SW_SHOW);
5572 flush_events( FALSE );
5573 while(PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE) != 0)
5575 if (msg.message == WM_PAINT) loopcount++;
5576 if (loopcount >= 100) break;
5577 TranslateMessage(&msg);
5578 DispatchMessage(&msg);
5579 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT);
5581 if (flags == (RDW_INVALIDATE | RDW_FRAME))
5582 todo_wine ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
5584 ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags);
5585 DestroyWindow(hwnd);
5588 static void test_NCRedraw(void)
5592 wndclass.lpszClassName = "TestNCRedrawClass";
5593 wndclass.style = CS_HREDRAW | CS_VREDRAW;
5594 wndclass.lpfnWndProc = TestNCRedraw_WndProc;
5595 wndclass.cbClsExtra = 0;
5596 wndclass.cbWndExtra = 0;
5597 wndclass.hInstance = 0;
5598 wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
5599 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
5600 wndclass.hbrBackground = GetStockObject(WHITE_BRUSH);
5601 wndclass.lpszMenuName = NULL;
5603 RegisterClassA(&wndclass);
5605 run_NCRedrawLoop(RDW_INVALIDATE | RDW_FRAME);
5606 run_NCRedrawLoop(RDW_INVALIDATE);
5609 static void test_GetWindowModuleFileName(void)
5614 char buf1[MAX_PATH], buf2[MAX_PATH];
5616 if (!pGetWindowModuleFileNameA)
5618 win_skip("GetWindowModuleFileNameA is not available\n");
5622 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL);
5625 hinst = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
5626 ok(hinst == 0 || broken(hinst == GetModuleHandle(0)), /* win9x */ "expected 0, got %p\n", hinst);
5629 SetLastError(0xdeadbeef);
5630 ret1 = GetModuleFileName(hinst, buf1, sizeof(buf1));
5631 ok(ret1, "GetModuleFileName error %u\n", GetLastError());
5634 SetLastError(0xdeadbeef);
5635 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
5636 ok(ret2 || broken(!ret2), /* nt4 sp 3 */
5637 "GetWindowModuleFileNameA error %u\n", GetLastError());
5641 ok(ret1 == ret2 || broken(ret2 == ret1 + 1), /* win98 */ "%u != %u\n", ret1, ret2);
5642 ok(!strcmp(buf1, buf2), "%s != %s\n", buf1, buf2);
5644 hinst = GetModuleHandle(0);
5646 SetLastError(0xdeadbeef);
5647 ret2 = GetModuleFileName(hinst, buf2, ret1 - 2);
5648 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */
5649 "expected %u, got %u\n", ret1 - 2, ret2);
5650 ok(GetLastError() == 0xdeadbeef /* XP */ ||
5651 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
5652 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
5654 SetLastError(0xdeadbeef);
5655 ret2 = GetModuleFileName(hinst, buf2, 0);
5656 ok(!ret2, "GetModuleFileName should return 0\n");
5657 ok(GetLastError() == 0xdeadbeef /* XP */ ||
5658 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
5659 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
5661 SetLastError(0xdeadbeef);
5662 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, ret1 - 2);
5663 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3) /* win98 */ || broken(!ret2), /* nt4 sp3 */
5664 "expected %u, got %u\n", ret1 - 2, ret2);
5665 ok(GetLastError() == 0xdeadbeef /* XP */ ||
5666 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
5667 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
5669 SetLastError(0xdeadbeef);
5670 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, 0);
5671 ok(!ret2, "expected 0, got %u\n", ret2);
5672 ok(GetLastError() == 0xdeadbeef /* XP */ ||
5673 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */
5674 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError());
5676 DestroyWindow(hwnd);
5679 hwnd = (HWND)0xdeadbeef;
5680 SetLastError(0xdeadbeef);
5681 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
5682 ok(!ret1, "expected 0, got %u\n", ret1);
5683 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), /* win9x */
5684 "expected ERROR_INVALID_WINDOW_HANDLE, got %u\n", GetLastError());
5686 hwnd = FindWindow("Shell_TrayWnd", NULL);
5687 ok(IsWindow(hwnd) || broken(!hwnd), "got invalid tray window %p\n", hwnd);
5688 SetLastError(0xdeadbeef);
5689 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1));
5690 ok(!ret1 || broken(ret1), /* win98 */ "expected 0, got %u\n", ret1);
5692 if (!ret1) /* inter-process GetWindowModuleFileName works on win9x, so don't test the desktop there */
5694 ret1 = GetModuleFileName(0, buf1, sizeof(buf1));
5695 hwnd = GetDesktopWindow();
5696 ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd);
5697 SetLastError(0xdeadbeef);
5698 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2));
5700 ret1 == ret2 || /* vista */
5701 broken(ret2), /* some win98 return user.exe as file name */
5702 "expected 0 or %u, got %u %s\n", ret1, ret2, buf2);
5706 static void test_hwnd_message(void)
5708 static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0};
5709 static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0};
5711 HWND parent = 0, hwnd, found;
5714 /* HWND_MESSAGE is not supported below w2k, but win9x return != 0
5715 on CreateWindowExA and crash later in the test.
5716 Use UNICODE here to fail on win9x */
5717 hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, WS_CAPTION | WS_VISIBLE,
5718 100, 100, 200, 200, HWND_MESSAGE, 0, 0, NULL);
5721 win_skip("CreateWindowExW with parent HWND_MESSAGE failed\n");
5725 ok( !GetParent(hwnd), "GetParent should return 0 for message only windows\n" );
5729 HWND root, desktop = GetDesktopWindow();
5731 parent = pGetAncestor(hwnd, GA_PARENT);
5732 ok(parent != 0, "GetAncestor(GA_PARENT) should not return 0 for message windows\n");
5733 ok(parent != desktop, "GetAncestor(GA_PARENT) should not return desktop for message windows\n");
5734 root = pGetAncestor(hwnd, GA_ROOT);
5735 ok(root == hwnd, "GetAncestor(GA_ROOT) should return hwnd for message windows\n");
5736 ok( !pGetAncestor(parent, GA_PARENT) || broken(pGetAncestor(parent, GA_PARENT) != 0), /* win2k */
5737 "parent shouldn't have parent %p\n", pGetAncestor(parent, GA_PARENT) );
5738 trace("parent %p root %p desktop %p\n", parent, root, desktop);
5739 if (!GetClassNameA( parent, buffer, sizeof(buffer) )) buffer[0] = 0;
5740 ok( !lstrcmpi( buffer, "Message" ), "wrong parent class '%s'\n", buffer );
5741 GetWindowRect( parent, &rect );
5742 ok( rect.left == 0 && rect.right == 100 && rect.top == 0 && rect.bottom == 100,
5743 "wrong parent rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
5745 GetWindowRect( hwnd, &rect );
5746 ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300,
5747 "wrong window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
5749 /* test FindWindow behavior */
5751 found = FindWindowExA( 0, 0, 0, "message window" );
5752 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
5753 SetLastError(0xdeadbeef);
5754 found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" );
5755 ok( found == 0, "found message window %p/%p\n", found, hwnd );
5756 ok( GetLastError() == 0xdeadbeef, "expected deadbeef, got %d\n", GetLastError() );
5759 found = FindWindowExA( parent, 0, 0, "message window" );
5760 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd );
5763 /* test IsChild behavior */
5765 if (parent) ok( !IsChild( parent, hwnd ), "HWND_MESSAGE is child of top window\n" );
5767 /* test IsWindowVisible behavior */
5769 ok( !IsWindowVisible( hwnd ), "HWND_MESSAGE window is visible\n" );
5770 if (parent) ok( !IsWindowVisible( parent ), "HWND_MESSAGE parent is visible\n" );
5772 DestroyWindow(hwnd);
5775 static void test_layered_window(void)
5781 POINT pt = { 0, 0 };
5782 SIZE sz = { 200, 200 };
5787 if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes || !pUpdateLayeredWindow)
5789 win_skip( "layered windows not supported\n" );
5793 hdc = CreateCompatibleDC( 0 );
5794 hbm = CreateCompatibleBitmap( hdc, 200, 200 );
5795 SelectObject( hdc, hbm );
5797 hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION,
5798 100, 100, 200, 200, 0, 0, 0, NULL);
5800 SetLastError( 0xdeadbeef );
5801 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5802 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
5803 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
5804 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5805 ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" );
5806 ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA );
5807 ok( !ret, "SetLayeredWindowAttributes should fail on non-layered window\n" );
5808 SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
5809 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5810 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
5811 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5812 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
5813 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5814 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
5815 ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA );
5816 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
5817 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5818 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
5819 ok( key == 0x123456 || key == 0, "wrong color key %x\n", key );
5820 ok( alpha == 44, "wrong alpha %u\n", alpha );
5821 ok( flags == LWA_ALPHA, "wrong flags %x\n", flags );
5822 SetLastError( 0xdeadbeef );
5823 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5824 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
5825 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
5827 /* clearing WS_EX_LAYERED resets attributes */
5828 SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
5829 SetLastError( 0xdeadbeef );
5830 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5831 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" );
5832 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5833 ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" );
5834 SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
5835 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5836 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" );
5837 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5838 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" );
5839 ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA );
5840 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
5841 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5842 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
5843 ok( key == 0x654321, "wrong color key %x\n", key );
5844 ok( alpha == 22, "wrong alpha %u\n", alpha );
5845 ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags );
5846 SetLastError( 0xdeadbeef );
5847 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE );
5848 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" );
5849 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
5851 ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY );
5852 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
5854 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5855 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
5856 ok( key == 0x888888, "wrong color key %x\n", key );
5857 /* alpha not changed on vista if LWA_ALPHA is not set */
5858 ok( alpha == 22 || alpha == 33, "wrong alpha %u\n", alpha );
5859 ok( flags == LWA_COLORKEY, "wrong flags %x\n", flags );
5861 /* color key may or may not be changed without LWA_COLORKEY */
5862 ret = pSetLayeredWindowAttributes( hwnd, 0x999999, 44, 0 );
5863 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
5865 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5866 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
5867 ok( key == 0x888888 || key == 0x999999, "wrong color key %x\n", key );
5868 ok( alpha == 22 || alpha == 44, "wrong alpha %u\n", alpha );
5869 ok( flags == 0, "wrong flags %x\n", flags );
5871 /* default alpha and color key is 0 */
5872 SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED );
5873 SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED );
5874 ret = pSetLayeredWindowAttributes( hwnd, 0x222222, 55, 0 );
5875 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" );
5876 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags );
5877 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" );
5878 ok( key == 0 || key == 0x222222, "wrong color key %x\n", key );
5879 ok( alpha == 0 || alpha == 55, "wrong alpha %u\n", alpha );
5880 ok( flags == 0, "wrong flags %x\n", flags );
5882 DestroyWindow( hwnd );
5884 DeleteObject( hbm );
5887 static MONITORINFO mi;
5889 static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
5895 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
5896 trace("WM_NCCREATE: rect %d,%d-%d,%d\n", cs->x, cs->y, cs->cx, cs->cy);
5897 ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top &&
5898 cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom,
5899 "expected %d,%d-%d,%d, got %d,%d-%d,%d\n",
5900 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
5901 cs->x, cs->y, cs->cx, cs->cy);
5904 case WM_GETMINMAXINFO:
5906 MINMAXINFO *minmax = (MINMAXINFO *)lp;
5907 dump_minmax_info(minmax);
5908 ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left);
5909 ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top);
5910 ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right);
5911 ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom);
5915 return DefWindowProc(hwnd, msg, wp, lp);
5918 static void test_fullscreen(void)
5920 static const DWORD t_style[] = {
5921 WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME
5923 static const DWORD t_ex_style[] = {
5924 0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW
5934 if (!pGetMonitorInfoA || !pMonitorFromPoint)
5936 win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n");
5941 SetLastError(0xdeadbeef);
5942 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
5943 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError());
5945 mi.cbSize = sizeof(mi);
5946 SetLastError(0xdeadbeef);
5947 ret = pGetMonitorInfoA(hmon, &mi);
5948 ok(ret, "GetMonitorInfo error %u\n", GetLastError());
5949 trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n",
5950 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
5951 mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom);
5954 cls.lpfnWndProc = fullscreen_wnd_proc;
5957 cls.hInstance = GetModuleHandle(0);
5959 cls.hCursor = LoadCursorA(0, IDC_ARROW);
5960 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
5961 cls.lpszMenuName = NULL;
5962 cls.lpszClassName = "fullscreen_class";
5963 RegisterClass(&cls);
5965 for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++)
5967 DWORD style, ex_style;
5969 /* avoid a WM interaction */
5970 assert(!(t_style[i] & WS_VISIBLE));
5972 for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++)
5977 ex_style = t_ex_style[j];
5979 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
5980 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
5981 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
5982 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
5983 GetWindowRect(hwnd, &rc);
5984 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
5985 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
5986 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
5987 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
5988 DestroyWindow(hwnd);
5990 style = t_style[i] | WS_MAXIMIZE;
5991 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
5992 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
5993 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
5994 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
5995 GetWindowRect(hwnd, &rc);
5996 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
5997 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
5998 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
5999 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6000 DestroyWindow(hwnd);
6002 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION;
6003 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6004 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6005 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
6006 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6007 GetWindowRect(hwnd, &rc);
6008 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6009 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6010 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6011 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6012 DestroyWindow(hwnd);
6014 style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX;
6015 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6016 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6017 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
6018 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6019 GetWindowRect(hwnd, &rc);
6020 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6021 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6022 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6023 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6024 DestroyWindow(hwnd);
6026 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX;
6027 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6028 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6029 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
6030 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6031 GetWindowRect(hwnd, &rc);
6032 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6033 /* Windows makes a maximized window slightly larger (to hide the borders?) */
6034 fixup = min(abs(rc.left), abs(rc.top));
6035 InflateRect(&rc, -fixup, -fixup);
6036 ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
6037 rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
6038 "%#x/%#x: window rect %d,%d-%d,%d must be in %d,%d-%d,%d\n",
6039 ex_style, style, rc.left, rc.top, rc.right, rc.bottom,
6040 mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom);
6041 DestroyWindow(hwnd);
6043 style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX;
6044 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
6045 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
6046 GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
6047 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
6048 GetWindowRect(hwnd, &rc);
6049 trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6050 /* Windows makes a maximized window slightly larger (to hide the borders?) */
6051 fixup = min(abs(rc.left), abs(rc.top));
6052 InflateRect(&rc, -fixup, -fixup);
6053 if (style & (WS_CHILD | WS_POPUP))
6054 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
6055 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
6056 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6058 ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
6059 rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
6060 "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
6061 DestroyWindow(hwnd);
6065 UnregisterClass("fullscreen_class", GetModuleHandle(0));
6068 static BOOL test_thick_child_got_minmax;
6069 static const char * test_thick_child_name;
6070 static LONG test_thick_child_style;
6071 static LONG test_thick_child_exStyle;
6073 static LRESULT WINAPI test_thick_child_size_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
6076 int expectedMinTrackX;
6077 int expectedMinTrackY;
6078 int actualMinTrackX;
6079 int actualMinTrackY;
6080 int expectedMaxTrackX;
6081 int expectedMaxTrackY;
6082 int actualMaxTrackX;
6083 int actualMaxTrackY;
6084 int expectedMaxSizeX;
6085 int expectedMaxSizeY;
6096 case WM_GETMINMAXINFO:
6098 minmax = (MINMAXINFO *)lparam;
6099 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam);
6100 dump_minmax_info( minmax );
6102 test_thick_child_got_minmax = TRUE;
6105 adjustedStyle = test_thick_child_style;
6106 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
6107 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
6108 GetClientRect(GetParent(hwnd), &rect);
6109 AdjustWindowRectEx(&rect, adjustedStyle, FALSE, test_thick_child_exStyle);
6111 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
6113 expectedMinTrackX = GetSystemMetrics(SM_CXMINTRACK);
6114 expectedMinTrackY = GetSystemMetrics(SM_CYMINTRACK);
6118 expectedMinTrackX = -2 * rect.left;
6119 expectedMinTrackY = -2 * rect.top;
6121 actualMinTrackX = minmax->ptMinTrackSize.x;
6122 actualMinTrackY = minmax->ptMinTrackSize.y;
6124 ok(actualMinTrackX == expectedMinTrackX && actualMinTrackY == expectedMinTrackY,
6125 "expected minTrack %dx%d, actual minTrack %dx%d for %s\n",
6126 expectedMinTrackX, expectedMinTrackY, actualMinTrackX, actualMinTrackY,
6127 test_thick_child_name);
6129 actualMaxTrackX = minmax->ptMaxTrackSize.x;
6130 actualMaxTrackY = minmax->ptMaxTrackSize.y;
6131 expectedMaxTrackX = GetSystemMetrics(SM_CXMAXTRACK);
6132 expectedMaxTrackY = GetSystemMetrics(SM_CYMAXTRACK);
6133 ok(actualMaxTrackX == expectedMaxTrackX && actualMaxTrackY == expectedMaxTrackY,
6134 "expected maxTrack %dx%d, actual maxTrack %dx%d for %s\n",
6135 expectedMaxTrackX, expectedMaxTrackY, actualMaxTrackX, actualMaxTrackY,
6136 test_thick_child_name);
6138 expectedMaxSizeX = rect.right - rect.left;
6139 expectedMaxSizeY = rect.bottom - rect.top;
6140 actualMaxSizeX = minmax->ptMaxSize.x;
6141 actualMaxSizeY = minmax->ptMaxSize.y;
6143 ok(actualMaxSizeX == expectedMaxSizeX && actualMaxSizeY == expectedMaxSizeY,
6144 "expected maxSize %dx%d, actual maxSize %dx%d for %s\n",
6145 expectedMaxSizeX, expectedMaxSizeY, actualMaxSizeX, actualMaxSizeY,
6146 test_thick_child_name);
6149 expectedPosX = rect.left;
6150 expectedPosY = rect.top;
6151 actualPosX = minmax->ptMaxPosition.x;
6152 actualPosY = minmax->ptMaxPosition.y;
6153 ok(actualPosX == expectedPosX && actualPosY == expectedPosY,
6154 "expected maxPosition (%d/%d), actual maxPosition (%d/%d) for %s\n",
6155 expectedPosX, expectedPosY, actualPosX, actualPosY, test_thick_child_name);
6161 return DefWindowProcA(hwnd, msg, wparam, lparam);
6164 #define NUMBER_OF_THICK_CHILD_TESTS 16
6165 static void test_thick_child_size(HWND parentWindow)
6169 RECT adjustedParentRect;
6174 LONG expectedHeight;
6176 LPCTSTR className = "THICK_CHILD_CLASS";
6179 static const LONG styles[NUMBER_OF_THICK_CHILD_TESTS] = {
6180 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
6181 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
6182 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
6183 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
6184 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
6185 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
6186 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
6187 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
6188 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
6189 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
6190 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
6191 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
6192 WS_CHILD | WS_VISIBLE | WS_THICKFRAME,
6193 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME,
6194 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER,
6195 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER,
6198 static const LONG exStyles[NUMBER_OF_THICK_CHILD_TESTS] = {
6203 WS_EX_DLGMODALFRAME,
6204 WS_EX_DLGMODALFRAME,
6205 WS_EX_DLGMODALFRAME,
6206 WS_EX_DLGMODALFRAME,
6211 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
6212 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
6213 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
6214 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME,
6216 static const char *styleName[NUMBER_OF_THICK_CHILD_TESTS] = {
6217 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME",
6218 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME",
6219 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER",
6220 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER",
6221 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_DLGMODALFRAME",
6222 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_DLGMODALFRAME",
6223 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
6224 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME",
6225 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME exstyle= WS_EX_STATICEDGE",
6226 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE",
6227 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
6228 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE",
6229 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
6230 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
6231 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
6232 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME",
6236 cls.lpfnWndProc = test_thick_child_size_winproc;
6239 cls.hInstance = GetModuleHandleA(0);
6241 cls.hCursor = LoadCursorA(0, IDC_ARROW);
6242 cls.hbrBackground = GetStockObject(WHITE_BRUSH);
6243 cls.lpszMenuName = NULL;
6244 cls.lpszClassName = className;
6245 SetLastError(0xdeadbeef);
6246 success = RegisterClassA(&cls);
6247 ok(success,"RegisterClassA failed, error: %u\n", GetLastError());
6249 for(i = 0; i < NUMBER_OF_THICK_CHILD_TESTS; i++)
6251 test_thick_child_name = styleName[i];
6252 test_thick_child_style = styles[i];
6253 test_thick_child_exStyle = exStyles[i];
6254 test_thick_child_got_minmax = FALSE;
6256 SetLastError(0xdeadbeef);
6257 childWindow = CreateWindowEx( exStyles[i], className, "", styles[i], 0, 0, 0, 0, parentWindow, 0, GetModuleHandleA(0), NULL );
6258 ok(childWindow != NULL, "Failed to create child window, error: %u\n", GetLastError());
6260 ok(test_thick_child_got_minmax, "Got no WM_GETMINMAXINFO\n");
6262 SetLastError(0xdeadbeef);
6263 success = GetWindowRect(childWindow, &childRect);
6264 ok(success,"GetWindowRect call failed, error: %u\n", GetLastError());
6265 childWidth = childRect.right - childRect.left;
6266 childHeight = childRect.bottom - childRect.top;
6268 adjustedStyle = styles[i];
6269 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION)
6270 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
6271 GetClientRect(GetParent(childWindow), &adjustedParentRect);
6272 AdjustWindowRectEx(&adjustedParentRect, adjustedStyle, FALSE, test_thick_child_exStyle);
6275 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER))
6277 expectedWidth = GetSystemMetrics(SM_CXMINTRACK);
6278 expectedHeight = GetSystemMetrics(SM_CYMINTRACK);
6282 expectedWidth = -2 * adjustedParentRect.left;
6283 expectedHeight = -2 * adjustedParentRect.top;
6286 ok((childWidth == expectedWidth) && (childHeight == expectedHeight),
6287 "size of window (%s) is wrong: expected size %dx%d != actual size %dx%d\n",
6288 test_thick_child_name, expectedWidth, expectedHeight, childWidth, childHeight);
6290 SetLastError(0xdeadbeef);
6291 success = DestroyWindow(childWindow);
6292 ok(success,"DestroyWindow call failed, error: %u\n", GetLastError());
6294 ok(UnregisterClass(className, GetModuleHandleA(0)),"UnregisterClass call failed\n");
6297 static void test_handles( HWND full_hwnd )
6299 HWND hwnd = full_hwnd;
6303 SetLastError( 0xdeadbeef );
6304 ret = GetWindowRect( hwnd, &rect );
6305 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
6308 if ((ULONG_PTR)full_hwnd >> 32)
6309 hwnd = (HWND)((ULONG_PTR)full_hwnd & ~0u);
6311 hwnd = (HWND)((ULONG_PTR)full_hwnd | ((ULONG_PTR)~0u << 32));
6312 SetLastError( 0xdeadbeef );
6313 ret = GetWindowRect( hwnd, &rect );
6314 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
6316 hwnd = (HWND)(((ULONG_PTR)full_hwnd & ~0u) | ((ULONG_PTR)0x1234 << 32));
6317 SetLastError( 0xdeadbeef );
6318 ret = GetWindowRect( hwnd, &rect );
6319 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() );
6321 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x9876 << 16));
6322 SetLastError( 0xdeadbeef );
6323 ret = GetWindowRect( hwnd, &rect );
6324 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
6325 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
6327 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x12345678 << 16));
6328 SetLastError( 0xdeadbeef );
6329 ret = GetWindowRect( hwnd, &rect );
6330 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd );
6331 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() );
6335 static void test_winregion(void)
6342 if (!pGetWindowRgnBox)
6344 win_skip("GetWindowRgnBox not supported\n");
6348 hwnd = CreateWindowExA(0, "static", NULL, WS_VISIBLE, 10, 10, 10, 10, NULL, 0, 0, NULL);
6350 SetLastError(0xdeadbeef);
6351 ret = pGetWindowRgnBox(hwnd, NULL);
6352 ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
6353 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
6355 hrgn = CreateRectRgn(2, 3, 10, 15);
6356 ok( hrgn != NULL, "Region creation failed\n");
6359 SetWindowRgn(hwnd, hrgn, FALSE);
6361 SetLastError(0xdeadbeef);
6362 ret = pGetWindowRgnBox(hwnd, NULL);
6363 ok( ret == ERROR, "Expected ERROR, got %d\n", ret);
6364 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError());
6366 r.left = r.top = r.right = r.bottom = 0;
6367 ret = pGetWindowRgnBox(hwnd, &r);
6368 ok( ret == SIMPLEREGION, "Expected SIMPLEREGION, got %d\n", ret);
6369 ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15,
6370 "Expected (2,3,10,15), got (%d,%d,%d,%d)\n", r.left, r.top,
6374 hrgn = CreateRectRgn(2, 3, 10, 15);
6375 ret = pMirrorRgn( hwnd, hrgn );
6376 ok( ret == TRUE, "MirrorRgn failed %u\n", ret );
6377 r.left = r.top = r.right = r.bottom = 0;
6378 GetWindowRect( hwnd, &r );
6379 width = r.right - r.left;
6380 r.left = r.top = r.right = r.bottom = 0;
6381 ret = GetRgnBox( hrgn, &r );
6382 ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret );
6383 ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15,
6384 "Wrong rectangle (%d,%d,%d,%d) for width %d\n", r.left, r.top, r.right, r.bottom, width );
6386 else win_skip( "MirrorRgn not supported\n" );
6388 DestroyWindow(hwnd);
6391 static void test_rtl_layout(void)
6397 if (!pSetProcessDefaultLayout)
6399 win_skip( "SetProcessDefaultLayout not supported\n" );
6403 parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL);
6404 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL);
6406 GetWindowRect( parent, &r );
6407 ok( r.left == 100 && r.right == 400, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6408 GetClientRect( parent, &r );
6409 ok( r.left == 0 && r.right == 300, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6410 GetClientRect( child, &r );
6411 ok( r.left == 0 && r.right == 20, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6412 MapWindowPoints( child, parent, (POINT *)&r, 2 );
6413 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6414 GetWindowRect( child, &r );
6415 ok( r.left == 370 && r.right == 390, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6416 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
6417 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6418 GetWindowRect( child, &r );
6419 MapWindowPoints( NULL, parent, (POINT *)&r, 1 );
6420 MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 );
6421 ok( r.left == 30 && r.right == 10, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6423 MapWindowPoints( child, parent, &pt, 1 );
6424 ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y );
6425 SetWindowPos( parent, 0, 0, 0, 250, 250, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
6426 GetWindowRect( parent, &r );
6427 ok( r.left == 100 && r.right == 350, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6428 GetWindowRect( child, &r );
6429 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6430 SetWindowLongW( parent, GWL_EXSTYLE, 0 );
6431 GetWindowRect( child, &r );
6432 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6433 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
6434 ok( r.left == 220 && r.right == 240, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6435 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_LAYOUTRTL );
6436 GetWindowRect( child, &r );
6437 ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6438 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
6439 ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6440 SetWindowPos( child, 0, 0, 0, 30, 30, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
6441 GetWindowRect( child, &r );
6442 ok( r.left == 310 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6443 MapWindowPoints( NULL, parent, (POINT *)&r, 2 );
6444 ok( r.left == 10 && r.right == 40, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom );
6445 DestroyWindow( child );
6446 DestroyWindow( parent );
6449 static void test_FindWindowEx(void)
6454 hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
6455 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
6459 found = FindWindowExA( 0, 0, "MainWindowClass", title );
6460 ok( found == NULL, "expected a NULL hwnd\n" );
6461 found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
6462 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
6464 DestroyWindow( hwnd );
6466 hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL );
6467 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() );
6469 found = FindWindowExA( 0, 0, "MainWindowClass", title );
6470 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
6471 found = FindWindowExA( 0, 0, "MainWindowClass", NULL );
6472 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found );
6474 DestroyWindow( hwnd );
6476 /* test behaviour with a window title that is an empty character */
6477 found = FindWindowExA( 0, 0, "Shell_TrayWnd", title );
6478 ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
6479 found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL );
6480 ok( found != NULL, "found is NULL, expected a valid hwnd\n" );
6483 static void test_GetLastActivePopup(void)
6485 HWND hwndOwner, hwndPopup1, hwndPopup2;
6487 hwndOwner = CreateWindowExA(0, "MainWindowClass", NULL,
6488 WS_VISIBLE | WS_POPUPWINDOW,
6490 NULL, 0, GetModuleHandle(0), NULL);
6491 hwndPopup1 = CreateWindowExA(0, "MainWindowClass", NULL,
6492 WS_VISIBLE | WS_POPUPWINDOW,
6494 hwndOwner, 0, GetModuleHandle(0), NULL);
6495 hwndPopup2 = CreateWindowExA(0, "MainWindowClass", NULL,
6496 WS_VISIBLE | WS_POPUPWINDOW,
6498 hwndPopup1, 0, GetModuleHandle(0), NULL);
6499 ok( GetLastActivePopup(hwndOwner) == hwndPopup2, "wrong last active popup\n" );
6500 DestroyWindow( hwndPopup2 );
6501 DestroyWindow( hwndPopup1 );
6502 DestroyWindow( hwndOwner );
6507 HMODULE user32 = GetModuleHandleA( "user32.dll" );
6508 HMODULE gdi32 = GetModuleHandleA("gdi32.dll");
6509 pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" );
6510 pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" );
6511 pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" );
6512 pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" );
6513 pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" );
6514 pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" );
6515 pGetMonitorInfoA = (void *)GetProcAddress( user32, "GetMonitorInfoA" );
6516 pMonitorFromPoint = (void *)GetProcAddress( user32, "MonitorFromPoint" );
6517 pGetWindowRgnBox = (void *)GetProcAddress( user32, "GetWindowRgnBox" );
6518 pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" );
6519 pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" );
6520 pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" );
6521 pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" );
6522 pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" );
6523 pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" );
6525 if (!RegisterWindowClasses()) assert(0);
6527 SetLastError(0xdeafbeef);
6528 GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC);
6529 is_win9x = (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED);
6531 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId());
6532 if (!hhook) win_skip( "Cannot set CBT hook, skipping some tests\n" );
6534 /* make sure that these tests are executed first */
6535 test_FindWindowEx();
6538 hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window",
6539 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
6540 WS_MAXIMIZEBOX | WS_POPUP,
6542 0, 0, GetModuleHandle(0), NULL);
6543 hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2",
6544 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
6545 WS_MAXIMIZEBOX | WS_POPUP,
6547 0, 0, GetModuleHandle(0), NULL);
6549 assert( hwndMain2 );
6551 our_pid = GetWindowThreadProcessId(hwndMain, NULL);
6553 /* Add the tests below this line */
6554 test_thick_child_size(hwndMain);
6556 test_hwnd_message();
6557 test_nonclient_area(hwndMain);
6559 test_GetWindowModuleFileName();
6562 test_capture_3(hwndMain, hwndMain2);
6566 test_CreateWindow();
6567 test_parent_owner();
6568 test_enum_thread_windows();
6572 test_SetWindowPos(hwndMain, hwndMain2);
6573 test_SetMenu(hwndMain);
6574 test_SetFocus(hwndMain);
6575 test_SetActiveWindow(hwndMain);
6578 test_children_zorder(hwndMain);
6579 test_popup_zorder(hwndMain2, hwndMain, WS_POPUP);
6580 test_popup_zorder(hwndMain2, hwndMain, 0);
6581 test_GetLastActivePopup();
6582 test_keyboard_input(hwndMain);
6583 test_mouse_input(hwndMain);
6584 test_validatergn(hwndMain);
6585 test_nccalcscroll( hwndMain);
6586 test_scrollwindow( hwndMain);
6587 test_scrollvalidate( hwndMain);
6588 test_scrolldc( hwndMain);
6590 test_IsWindowUnicode();
6591 test_vis_rgn(hwndMain);
6593 test_AdjustWindowRect();
6594 test_window_styles();
6597 test_SetWindowLong();
6599 if (0) test_gettext(); /* crashes on NT4 */
6600 test_GetUpdateRect();
6602 test_layered_window();
6604 test_SetForegroundWindow(hwndMain);
6605 test_shell_window();
6606 test_handles( hwndMain );
6609 /* add the tests above this line */
6610 if (hhook) UnhookWindowsHookEx(hhook);
6612 DestroyWindow(hwndMain2);
6613 DestroyWindow(hwndMain);