1 /* 2 * Unit tests for window handling 3 * 4 * Copyright 2002 Bill Medland 5 * Copyright 2002 Alexandre Julliard 6 * Copyright 2003 Dmitry Timoshkov 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include "precomp.h" 24 25 #ifndef SPI_GETDESKWALLPAPER 26 #define SPI_GETDESKWALLPAPER 0x0073 27 #endif 28 29 #ifndef WM_SYSTIMER 30 #define WM_SYSTIMER 0x0118 31 #endif 32 33 #define LONG_PTR INT_PTR 34 #define ULONG_PTR UINT_PTR 35 36 void dump_region(HRGN hrgn); 37 38 static HWND (WINAPI *pGetAncestor)(HWND,UINT); 39 static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*); 40 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT); 41 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*); 42 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); 43 static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); 44 static BOOL (WINAPI *pUpdateLayeredWindowIndirect)(HWND,const UPDATELAYEREDWINDOWINFO*); 45 static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); 46 static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); 47 static int (WINAPI *pGetWindowRgnBox)(HWND,LPRECT); 48 static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*); 49 static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout ); 50 static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout ); 51 static BOOL (WINAPI *pFlashWindow)( HWND hwnd, BOOL bInvert ); 52 static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi ); 53 static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); 54 static DWORD (WINAPI *pGetLayout)(HDC hdc); 55 static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn); 56 57 static BOOL test_lbuttondown_flag; 58 static DWORD num_gettext_msgs; 59 static DWORD num_settext_msgs; 60 static HWND hwndMessage; 61 static HWND hwndMain, hwndMain2; 62 static HHOOK hhook; 63 static BOOL app_activated, app_deactivated; 64 65 static const char* szAWRClass = "Winsize"; 66 static HMENU hmenu; 67 static DWORD our_pid; 68 69 static BOOL is_win9x = FALSE; 70 71 #define COUNTOF(arr) (sizeof(arr)/sizeof(arr[0])) 72 73 static void dump_minmax_info( const MINMAXINFO *minmax ) 74 { 75 trace("Reserved=%d,%d MaxSize=%d,%d MaxPos=%d,%d MinTrack=%d,%d MaxTrack=%d,%d\n", 76 minmax->ptReserved.x, minmax->ptReserved.y, 77 minmax->ptMaxSize.x, minmax->ptMaxSize.y, 78 minmax->ptMaxPosition.x, minmax->ptMaxPosition.y, 79 minmax->ptMinTrackSize.x, minmax->ptMinTrackSize.y, 80 minmax->ptMaxTrackSize.x, minmax->ptMaxTrackSize.y); 81 } 82 83 /* try to make sure pending X events have been processed before continuing */ 84 static void flush_events( BOOL remove_messages ) 85 { 86 MSG msg; 87 int diff = 200; 88 int min_timeout = 100; 89 DWORD time = GetTickCount() + diff; 90 91 while (diff > 0) 92 { 93 if (MsgWaitForMultipleObjects( 0, NULL, FALSE, min_timeout, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 94 if (remove_messages) 95 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) DispatchMessageA( &msg ); 96 diff = time - GetTickCount(); 97 min_timeout = 50; 98 } 99 } 100 101 static BOOL wait_for_event(HANDLE event, int timeout) 102 { 103 DWORD end_time = GetTickCount() + timeout; 104 MSG msg; 105 106 do { 107 if(MsgWaitForMultipleObjects(1, &event, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0) 108 return TRUE; 109 while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 110 DispatchMessageA(&msg); 111 timeout = end_time - GetTickCount(); 112 }while(timeout > 0); 113 114 return FALSE; 115 } 116 117 /* check the values returned by the various parent/owner functions on a given window */ 118 static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_parent, 119 HWND gw_owner, HWND ga_root, HWND ga_root_owner ) 120 { 121 HWND res; 122 123 if (pGetAncestor) 124 { 125 res = pGetAncestor( hwnd, GA_PARENT ); 126 ok( res == ga_parent, "Wrong result for GA_PARENT %p expected %p\n", res, ga_parent ); 127 } 128 res = (HWND)GetWindowLongPtrA( hwnd, GWLP_HWNDPARENT ); 129 ok( res == gwl_parent, "Wrong result for GWL_HWNDPARENT %p expected %p\n", res, gwl_parent ); 130 res = GetParent( hwnd ); 131 ok( res == get_parent, "Wrong result for GetParent %p expected %p\n", res, get_parent ); 132 res = GetWindow( hwnd, GW_OWNER ); 133 ok( res == gw_owner, "Wrong result for GW_OWNER %p expected %p\n", res, gw_owner ); 134 if (pGetAncestor) 135 { 136 res = pGetAncestor( hwnd, GA_ROOT ); 137 ok( res == ga_root, "Wrong result for GA_ROOT %p expected %p\n", res, ga_root ); 138 res = pGetAncestor( hwnd, GA_ROOTOWNER ); 139 ok( res == ga_root_owner, "Wrong result for GA_ROOTOWNER %p expected %p\n", res, ga_root_owner ); 140 } 141 } 142 143 #define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d) 144 static void check_wnd_state_(const char *file, int line, 145 HWND active, HWND foreground, HWND focus, HWND capture) 146 { 147 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow()); 148 /* only check foreground if it belongs to the current thread */ 149 /* foreground can be moved to a different app pretty much at any time */ 150 if (foreground && GetForegroundWindow() && 151 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId()) 152 disable_success_count 153 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow()); 154 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus()); 155 ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture()); 156 } 157 158 /* same as above but without capture test */ 159 #define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c) 160 static void check_active_state_(const char *file, int line, 161 HWND active, HWND foreground, HWND focus) 162 { 163 ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow()); 164 /* only check foreground if it belongs to the current thread */ 165 /* foreground can be moved to a different app pretty much at any time */ 166 if (foreground && GetForegroundWindow() && 167 GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId()) 168 disable_success_count 169 ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow()); 170 ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus()); 171 } 172 173 static BOOL ignore_message( UINT message ) 174 { 175 /* these are always ignored */ 176 return (message >= 0xc000 || 177 message == WM_GETICON || 178 message == WM_GETOBJECT || 179 message == WM_TIMER || 180 message == WM_SYSTIMER || 181 message == WM_TIMECHANGE || 182 message == WM_DEVICECHANGE); 183 } 184 185 static BOOL CALLBACK EnumChildProc( HWND hwndChild, LPARAM lParam) 186 { 187 (*(LPINT)lParam)++; 188 trace("EnumChildProc on %p\n", hwndChild); 189 if (*(LPINT)lParam > 1) return FALSE; 190 return TRUE; 191 } 192 193 /* will search for the given window */ 194 static BOOL CALLBACK EnumChildProc1( HWND hwndChild, LPARAM lParam) 195 { 196 trace("EnumChildProc1 on %p\n", hwndChild); 197 if ((HWND)lParam == hwndChild) return FALSE; 198 return TRUE; 199 } 200 201 static HWND create_tool_window( LONG style, HWND parent ) 202 { 203 HWND ret = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", style, 204 0, 0, 100, 100, parent, 0, 0, NULL ); 205 ok( ret != 0, "Creation failed\n" ); 206 return ret; 207 } 208 209 /* test parent and owner values for various combinations */ 210 static void test_parent_owner(void) 211 { 212 LONG style; 213 HWND test, owner, ret; 214 HWND desktop = GetDesktopWindow(); 215 HWND child = create_tool_window( WS_CHILD, hwndMain ); 216 INT numChildren; 217 218 trace( "main window %p main2 %p desktop %p child %p\n", hwndMain, hwndMain2, desktop, child ); 219 220 /* child without parent, should fail */ 221 SetLastError(0xdeadbeef); 222 test = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", 223 WS_CHILD, 0, 0, 100, 100, 0, 0, 0, NULL ); 224 ok( !test, "WS_CHILD without parent created\n" ); 225 ok( GetLastError() == ERROR_TLW_WITH_WSCHILD || 226 broken(GetLastError() == 0xdeadbeef), /* win9x */ 227 "CreateWindowExA error %u\n", GetLastError() ); 228 229 /* desktop window */ 230 check_parents( desktop, 0, 0, 0, 0, 0, 0 ); 231 style = GetWindowLongA( desktop, GWL_STYLE ); 232 ok( !SetWindowLongA( desktop, GWL_STYLE, WS_POPUP ), "Set GWL_STYLE on desktop succeeded\n" ); 233 ok( !SetWindowLongA( desktop, GWL_STYLE, 0 ), "Set GWL_STYLE on desktop succeeded\n" ); 234 ok( GetWindowLongA( desktop, GWL_STYLE ) == style, "Desktop style changed\n" ); 235 236 /* normal child window */ 237 test = create_tool_window( WS_CHILD, hwndMain ); 238 trace( "created child %p\n", test ); 239 check_parents( test, hwndMain, hwndMain, hwndMain, 0, hwndMain, hwndMain ); 240 SetWindowLongA( test, GWL_STYLE, 0 ); 241 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test ); 242 SetWindowLongA( test, GWL_STYLE, WS_POPUP ); 243 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test ); 244 SetWindowLongA( test, GWL_STYLE, WS_POPUP|WS_CHILD ); 245 check_parents( test, hwndMain, hwndMain, 0, 0, hwndMain, test ); 246 SetWindowLongA( test, GWL_STYLE, WS_CHILD ); 247 DestroyWindow( test ); 248 249 /* normal child window with WS_MAXIMIZE */ 250 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, hwndMain ); 251 DestroyWindow( test ); 252 253 /* normal child window with WS_THICKFRAME */ 254 test = create_tool_window( WS_CHILD | WS_THICKFRAME, hwndMain ); 255 DestroyWindow( test ); 256 257 /* popup window with WS_THICKFRAME */ 258 test = create_tool_window( WS_POPUP | WS_THICKFRAME, hwndMain ); 259 DestroyWindow( test ); 260 261 /* child of desktop */ 262 test = create_tool_window( WS_CHILD, desktop ); 263 trace( "created child of desktop %p\n", test ); 264 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 265 SetWindowLongA( test, GWL_STYLE, WS_POPUP ); 266 check_parents( test, desktop, 0, 0, 0, test, test ); 267 SetWindowLongA( test, GWL_STYLE, 0 ); 268 check_parents( test, desktop, 0, 0, 0, test, test ); 269 DestroyWindow( test ); 270 271 /* child of desktop with WS_MAXIMIZE */ 272 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, desktop ); 273 DestroyWindow( test ); 274 275 /* child of desktop with WS_MINIMIZE */ 276 test = create_tool_window( WS_CHILD | WS_MINIMIZE, desktop ); 277 DestroyWindow( test ); 278 279 /* child of child */ 280 test = create_tool_window( WS_CHILD, child ); 281 trace( "created child of child %p\n", test ); 282 check_parents( test, child, child, child, 0, hwndMain, hwndMain ); 283 SetWindowLongA( test, GWL_STYLE, 0 ); 284 check_parents( test, child, child, 0, 0, hwndMain, test ); 285 SetWindowLongA( test, GWL_STYLE, WS_POPUP ); 286 check_parents( test, child, child, 0, 0, hwndMain, test ); 287 DestroyWindow( test ); 288 289 /* child of child with WS_MAXIMIZE */ 290 test = create_tool_window( WS_CHILD | WS_MAXIMIZE, child ); 291 DestroyWindow( test ); 292 293 /* child of child with WS_MINIMIZE */ 294 test = create_tool_window( WS_CHILD | WS_MINIMIZE, child ); 295 DestroyWindow( test ); 296 297 /* not owned top-level window */ 298 test = create_tool_window( 0, 0 ); 299 trace( "created top-level %p\n", test ); 300 check_parents( test, desktop, 0, 0, 0, test, test ); 301 SetWindowLongA( test, GWL_STYLE, WS_POPUP ); 302 check_parents( test, desktop, 0, 0, 0, test, test ); 303 SetWindowLongA( test, GWL_STYLE, WS_CHILD ); 304 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 305 DestroyWindow( test ); 306 307 /* not owned top-level window with WS_MAXIMIZE */ 308 test = create_tool_window( WS_MAXIMIZE, 0 ); 309 DestroyWindow( test ); 310 311 /* owned top-level window */ 312 test = create_tool_window( 0, hwndMain ); 313 trace( "created owned top-level %p\n", test ); 314 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test ); 315 SetWindowLongA( test, GWL_STYLE, WS_POPUP ); 316 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain ); 317 SetWindowLongA( test, GWL_STYLE, WS_CHILD ); 318 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop ); 319 DestroyWindow( test ); 320 321 /* owned top-level window with WS_MAXIMIZE */ 322 test = create_tool_window( WS_MAXIMIZE, hwndMain ); 323 DestroyWindow( test ); 324 325 /* not owned popup */ 326 test = create_tool_window( WS_POPUP, 0 ); 327 trace( "created popup %p\n", test ); 328 check_parents( test, desktop, 0, 0, 0, test, test ); 329 SetWindowLongA( test, GWL_STYLE, WS_CHILD ); 330 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 331 SetWindowLongA( test, GWL_STYLE, 0 ); 332 check_parents( test, desktop, 0, 0, 0, test, test ); 333 DestroyWindow( test ); 334 335 /* not owned popup with WS_MAXIMIZE */ 336 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, 0 ); 337 DestroyWindow( test ); 338 339 /* owned popup */ 340 test = create_tool_window( WS_POPUP, hwndMain ); 341 trace( "created owned popup %p\n", test ); 342 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain ); 343 SetWindowLongA( test, GWL_STYLE, WS_CHILD ); 344 check_parents( test, desktop, hwndMain, desktop, hwndMain, test, desktop ); 345 SetWindowLongA( test, GWL_STYLE, 0 ); 346 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test ); 347 DestroyWindow( test ); 348 349 /* owned popup with WS_MAXIMIZE */ 350 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, hwndMain ); 351 DestroyWindow( test ); 352 353 /* top-level window owned by child (same as owned by top-level) */ 354 test = create_tool_window( 0, child ); 355 trace( "created top-level owned by child %p\n", test ); 356 check_parents( test, desktop, hwndMain, 0, hwndMain, test, test ); 357 DestroyWindow( test ); 358 359 /* top-level window owned by child (same as owned by top-level) with WS_MAXIMIZE */ 360 test = create_tool_window( WS_MAXIMIZE, child ); 361 DestroyWindow( test ); 362 363 /* popup owned by desktop (same as not owned) */ 364 test = create_tool_window( WS_POPUP, desktop ); 365 trace( "created popup owned by desktop %p\n", test ); 366 check_parents( test, desktop, 0, 0, 0, test, test ); 367 DestroyWindow( test ); 368 369 /* popup owned by desktop (same as not owned) with WS_MAXIMIZE */ 370 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, desktop ); 371 DestroyWindow( test ); 372 373 /* popup owned by child (same as owned by top-level) */ 374 test = create_tool_window( WS_POPUP, child ); 375 trace( "created popup owned by child %p\n", test ); 376 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain ); 377 DestroyWindow( test ); 378 379 /* popup owned by child (same as owned by top-level) with WS_MAXIMIZE */ 380 test = create_tool_window( WS_POPUP | WS_MAXIMIZE, child ); 381 DestroyWindow( test ); 382 383 /* not owned popup with WS_CHILD (same as WS_POPUP only) */ 384 test = create_tool_window( WS_POPUP | WS_CHILD, 0 ); 385 trace( "created WS_CHILD popup %p\n", test ); 386 check_parents( test, desktop, 0, 0, 0, test, test ); 387 DestroyWindow( test ); 388 389 /* not owned popup with WS_CHILD | WS_MAXIMIZE (same as WS_POPUP only) */ 390 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, 0 ); 391 DestroyWindow( test ); 392 393 /* owned popup with WS_CHILD (same as WS_POPUP only) */ 394 test = create_tool_window( WS_POPUP | WS_CHILD, hwndMain ); 395 trace( "created owned WS_CHILD popup %p\n", test ); 396 check_parents( test, desktop, hwndMain, hwndMain, hwndMain, test, hwndMain ); 397 DestroyWindow( test ); 398 399 /* owned popup with WS_CHILD (same as WS_POPUP only) with WS_MAXIMIZE */ 400 test = create_tool_window( WS_POPUP | WS_CHILD | WS_MAXIMIZE, hwndMain ); 401 DestroyWindow( test ); 402 403 /******************** parent changes *************************/ 404 trace( "testing parent changes\n" ); 405 406 /* desktop window */ 407 check_parents( desktop, 0, 0, 0, 0, 0, 0 ); 408 if (0) 409 { 410 /* this test succeeds on NT but crashes on win9x systems */ 411 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 ); 412 ok( !ret, "Set GWL_HWNDPARENT succeeded on desktop\n" ); 413 check_parents( desktop, 0, 0, 0, 0, 0, 0 ); 414 ok( !SetParent( desktop, hwndMain ), "SetParent succeeded on desktop\n" ); 415 check_parents( desktop, 0, 0, 0, 0, 0, 0 ); 416 } 417 /* normal child window */ 418 test = create_tool_window( WS_CHILD, hwndMain ); 419 trace( "created child %p\n", test ); 420 421 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 ); 422 ok( ret == hwndMain, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain ); 423 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 ); 424 425 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child ); 426 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 ); 427 check_parents( test, child, child, child, 0, hwndMain, hwndMain ); 428 429 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)desktop ); 430 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child ); 431 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 432 433 /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */ 434 if (!is_win9x) 435 { 436 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test ); 437 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); 438 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 439 } 440 else 441 win_skip("Test creates circular window tree under Win9x/WinMe\n" ); 442 443 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child ); 444 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); 445 check_parents( test, desktop, child, desktop, child, test, desktop ); 446 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, desktop, 0, test, desktop ); 450 DestroyWindow( test ); 451 452 /* not owned top-level window */ 453 test = create_tool_window( 0, 0 ); 454 trace( "created top-level %p\n", test ); 455 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, 0, hwndMain2, test, test ); 459 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, 0, child, test, test ); 463 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 ); 468 469 /* not owned popup */ 470 test = create_tool_window( WS_POPUP, 0 ); 471 trace( "created popup %p\n", test ); 472 473 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)hwndMain2 ); 474 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); 475 check_parents( test, desktop, hwndMain2, hwndMain2, hwndMain2, test, hwndMain2 ); 476 477 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child ); 478 ok( ret == hwndMain2, "GWL_HWNDPARENT return value %p expected %p\n", ret, hwndMain2 ); 479 check_parents( test, desktop, child, child, child, test, hwndMain ); 480 481 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, 0 ); 482 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child ); 483 check_parents( test, desktop, 0, 0, 0, test, test ); 484 DestroyWindow( test ); 485 486 /* normal child window */ 487 test = create_tool_window( WS_CHILD, hwndMain ); 488 trace( "created child %p\n", test ); 489 490 ret = SetParent( test, desktop ); 491 ok( ret == hwndMain, "SetParent return value %p expected %p\n", ret, hwndMain ); 492 check_parents( test, desktop, 0, desktop, 0, test, desktop ); 493 494 ret = SetParent( test, child ); 495 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 496 check_parents( test, child, child, child, 0, hwndMain, hwndMain ); 497 498 ret = SetParent( test, hwndMain2 ); 499 ok( ret == child, "SetParent return value %p expected %p\n", ret, child ); 500 check_parents( test, hwndMain2, hwndMain2, hwndMain2, 0, hwndMain2, hwndMain2 ); 501 DestroyWindow( test ); 502 503 /* not owned top-level window */ 504 test = create_tool_window( 0, 0 ); 505 trace( "created top-level %p\n", test ); 506 507 ret = SetParent( test, child ); 508 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 509 check_parents( test, child, child, 0, 0, hwndMain, test ); 510 511 if (!is_win9x) 512 { 513 ShowWindow( test, SW_SHOW ); 514 ret = SetParent( test, test ); 515 ok( ret == NULL, "SetParent return value %p expected %p\n", ret, NULL ); 516 ok( GetWindowLongA( test, GWL_STYLE ) & WS_VISIBLE, "window is not visible after SetParent\n" ); 517 check_parents( test, child, child, 0, 0, hwndMain, test ); 518 } 519 else 520 win_skip( "Test crashes on Win9x/WinMe\n" ); 521 DestroyWindow( test ); 522 523 /* owned popup */ 524 test = create_tool_window( WS_POPUP, hwndMain2 ); 525 trace( "created owned popup %p\n", test ); 526 527 ret = SetParent( test, child ); 528 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 529 check_parents( test, child, child, hwndMain2, hwndMain2, hwndMain, hwndMain2 ); 530 531 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)hwndMain ); 532 ok( ret == child, "GWL_HWNDPARENT return value %p expected %p\n", ret, child ); 533 check_parents( test, hwndMain, hwndMain, hwndMain2, hwndMain2, hwndMain, hwndMain2 ); 534 DestroyWindow( test ); 535 536 /**************** test owner destruction *******************/ 537 538 /* owned child 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 ret = SetParent( test, child ); 543 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 544 check_parents( test, child, child, owner, owner, hwndMain, owner ); 545 /* window is now child of 'child' but owned by 'owner' */ 546 DestroyWindow( owner ); 547 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test ); 548 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner, 549 * while Win95, Win2k, WinXP do. 550 */ 551 /*check_parents( test, child, child, owner, owner, hwndMain, owner );*/ 552 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner ); 553 DestroyWindow(test); 554 555 /* owned top-level popup */ 556 owner = create_tool_window( 0, 0 ); 557 test = create_tool_window( WS_POPUP, owner ); 558 trace( "created owner %p and popup %p\n", owner, test ); 559 check_parents( test, desktop, owner, owner, owner, test, owner ); 560 DestroyWindow( owner ); 561 ok( !IsWindow(test), "Window %p not destroyed by owner destruction\n", test ); 562 563 /* top-level popup owned by child */ 564 owner = create_tool_window( WS_CHILD, hwndMain2 ); 565 test = create_tool_window( WS_POPUP, 0 ); 566 trace( "created owner %p and popup %p\n", owner, test ); 567 ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (ULONG_PTR)owner ); 568 ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); 569 check_parents( test, desktop, owner, owner, owner, test, hwndMain2 ); 570 DestroyWindow( owner ); 571 ok( IsWindow(test), "Window %p destroyed by owner destruction\n", test ); 572 ok( !IsWindow(owner), "Owner %p not destroyed\n", owner ); 573 /* Win98 doesn't pass this test. It doesn't allow a destroyed owner, 574 * while Win95, Win2k, WinXP do. 575 */ 576 /*check_parents( test, desktop, owner, owner, owner, test, owner );*/ 577 DestroyWindow(test); 578 579 /* final cleanup */ 580 DestroyWindow(child); 581 582 583 owner = create_tool_window( WS_OVERLAPPED, 0 ); 584 test = create_tool_window( WS_POPUP, desktop ); 585 586 ok( !GetWindow( test, GW_OWNER ), "Wrong owner window\n" ); 587 numChildren = 0; 588 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 589 "EnumChildWindows should have returned FALSE\n" ); 590 ok( numChildren == 0, "numChildren should be 0 got %d\n", numChildren ); 591 592 SetWindowLongA( test, GWL_STYLE, (GetWindowLongA( test, GWL_STYLE ) & ~WS_POPUP) | WS_CHILD ); 593 ret = SetParent( test, owner ); 594 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 595 596 numChildren = 0; 597 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 598 "EnumChildWindows should have returned TRUE\n" ); 599 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren ); 600 601 child = create_tool_window( WS_CHILD, owner ); 602 numChildren = 0; 603 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 604 "EnumChildWindows should have returned FALSE\n" ); 605 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren ); 606 DestroyWindow( child ); 607 608 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner ); 609 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" ); 610 numChildren = 0; 611 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 612 "EnumChildWindows should have returned TRUE\n" ); 613 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren ); 614 615 ret = SetParent( child, owner ); 616 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" ); 617 ok( ret == desktop, "SetParent return value %p expected %p\n", ret, desktop ); 618 numChildren = 0; 619 ok( !EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 620 "EnumChildWindows should have returned FALSE\n" ); 621 ok( numChildren == 2, "numChildren should be 2 got %d\n", numChildren ); 622 623 ret = SetParent( child, NULL ); 624 ok( GetWindow( child, GW_OWNER ) == owner, "Wrong owner window\n" ); 625 ok( ret == owner, "SetParent return value %p expected %p\n", ret, owner ); 626 numChildren = 0; 627 ok( EnumChildWindows( owner, EnumChildProc, (LPARAM)&numChildren ), 628 "EnumChildWindows should have returned TRUE\n" ); 629 ok( numChildren == 1, "numChildren should be 1 got %d\n", numChildren ); 630 631 /* even GW_OWNER == owner it's still a desktop's child */ 632 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ), 633 "EnumChildWindows should have found %p and returned FALSE\n", child ); 634 635 DestroyWindow( child ); 636 child = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, NULL ); 637 638 ok( !EnumChildWindows( desktop, EnumChildProc1, (LPARAM)child ), 639 "EnumChildWindows should have found %p and returned FALSE\n", child ); 640 641 DestroyWindow( child ); 642 DestroyWindow( test ); 643 DestroyWindow( owner ); 644 645 /* Test that owner window takes into account WS_CHILD flag even if parent is set by SetParent. */ 646 owner = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, desktop ); 647 SetParent(owner, hwndMain); 648 check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner ); 649 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner ); 650 check_parents( test, desktop, owner, NULL, owner, test, test ); 651 DestroyWindow( owner ); 652 DestroyWindow( test ); 653 654 owner = create_tool_window( WS_VISIBLE | WS_CHILD, desktop ); 655 SetParent(owner, hwndMain); 656 check_parents( owner, hwndMain, hwndMain, hwndMain, NULL, hwndMain, hwndMain ); 657 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner ); 658 check_parents( test, desktop, hwndMain, NULL, hwndMain, test, test ); 659 DestroyWindow( owner ); 660 DestroyWindow( test ); 661 662 owner = create_tool_window( WS_VISIBLE | WS_POPUP | WS_CHILD, desktop ); 663 SetParent(owner, hwndMain); 664 check_parents( owner, hwndMain, hwndMain, NULL, NULL, hwndMain, owner ); 665 test = create_tool_window( WS_VISIBLE | WS_OVERLAPPEDWINDOW, owner ); 666 check_parents( test, desktop, owner, NULL, owner, test, test ); 667 DestroyWindow( owner ); 668 DestroyWindow( test ); 669 } 670 671 static BOOL CALLBACK enum_proc( HWND hwnd, LPARAM lParam) 672 { 673 (*(LPINT)lParam)++; 674 if (*(LPINT)lParam > 2) return FALSE; 675 return TRUE; 676 } 677 static DWORD CALLBACK enum_thread( void *arg ) 678 { 679 INT count; 680 HWND hwnd[3]; 681 BOOL ret; 682 MSG msg; 683 684 if (pGetGUIThreadInfo) 685 { 686 GUITHREADINFO info; 687 info.cbSize = sizeof(info); 688 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info ); 689 ok( ret || broken(!ret), /* win9x */ 690 "GetGUIThreadInfo failed without message queue\n" ); 691 SetLastError( 0xdeadbeef ); 692 info.cbSize = sizeof(info) + 1; 693 ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info ); 694 ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" ); 695 ok( GetLastError() == ERROR_INVALID_PARAMETER || 696 broken(GetLastError() == 0xdeadbeef), /* win9x */ 697 "wrong error %u\n", GetLastError() ); 698 } 699 700 PeekMessageA( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */ 701 702 count = 0; 703 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count ); 704 ok( ret, "EnumThreadWindows should have returned TRUE\n" ); 705 ok( count == 0, "count should be 0 got %d\n", count ); 706 707 hwnd[0] = CreateWindowExA(0, "ToolWindowClass", "Tool window 1", WS_POPUP, 708 0, 0, 100, 100, 0, 0, 0, NULL ); 709 count = 0; 710 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count ); 711 ok( ret, "EnumThreadWindows should have returned TRUE\n" ); 712 if (count != 2) /* Vista gives us two windows for the price of one */ 713 { 714 ok( count == 1, "count should be 1 got %d\n", count ); 715 hwnd[2] = CreateWindowExA(0, "ToolWindowClass", "Tool window 2", WS_POPUP, 716 0, 0, 100, 100, 0, 0, 0, NULL ); 717 } 718 else hwnd[2] = 0; 719 720 hwnd[1] = CreateWindowExA(0, "ToolWindowClass", "Tool window 3", WS_POPUP, 721 0, 0, 100, 100, 0, 0, 0, NULL ); 722 count = 0; 723 ret = EnumThreadWindows( GetCurrentThreadId(), enum_proc, (LPARAM)&count ); 724 ok( !ret, "EnumThreadWindows should have returned FALSE\n" ); 725 ok( count == 3, "count should be 3 got %d\n", count ); 726 727 if (hwnd[2]) DestroyWindow(hwnd[2]); 728 DestroyWindow(hwnd[1]); 729 DestroyWindow(hwnd[0]); 730 return 0; 731 } 732 733 /* test EnumThreadWindows in a separate thread */ 734 static void test_enum_thread_windows(void) 735 { 736 DWORD id; 737 HANDLE handle = CreateThread( NULL, 0, enum_thread, 0, 0, &id ); 738 ok( !WaitForSingleObject( handle, 10000 ), "wait failed\n" ); 739 CloseHandle( handle ); 740 } 741 742 static struct wm_gettext_override_data 743 { 744 BOOL enabled; /* when 1 bypasses default procedure */ 745 char *buff; /* expected text buffer pointer */ 746 WCHAR *buffW; /* same, for W test */ 747 } g_wm_gettext_override; 748 749 static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 750 { 751 switch (msg) 752 { 753 case WM_GETMINMAXINFO: 754 { 755 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021); 756 break; 757 } 758 case WM_WINDOWPOSCHANGING: 759 { 760 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 761 if (!(winpos->flags & SWP_NOMOVE)) 762 { 763 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x); 764 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y); 765 } 766 /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */ 767 if (!(winpos->flags & SWP_NOSIZE) && !is_win9x) 768 { 769 ok((winpos->cx >= 0 && winpos->cx <= 32767) || 770 winpos->cx == 32768, /* win7 doesn't truncate */ 771 "bad winpos->cx %d\n", winpos->cx); 772 ok((winpos->cy >= 0 && winpos->cy <= 32767) || 773 winpos->cy == 40000, /* win7 doesn't truncate */ 774 "bad winpos->cy %d\n", winpos->cy); 775 } 776 break; 777 } 778 case WM_WINDOWPOSCHANGED: 779 disable_success_count 780 { 781 RECT rc1, rc2; 782 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 783 ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x); 784 ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y); 785 786 ok((winpos->cx >= 0 && winpos->cx <= 32767) || 787 winpos->cx == 32768, /* win7 doesn't truncate */ 788 "bad winpos->cx %d\n", winpos->cx); 789 ok((winpos->cy >= 0 && winpos->cy <= 32767) || 790 winpos->cy == 40000, /* win7 doesn't truncate */ 791 "bad winpos->cy %d\n", winpos->cy); 792 793 GetWindowRect(hwnd, &rc1); 794 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy); 795 /* note: winpos coordinates are relative to parent */ 796 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2); 797 if (0) 798 { 799 /* Uncomment this once the test succeeds in all cases */ 800 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 801 wine_dbgstr_rect(&rc2)); 802 803 GetClientRect(hwnd, &rc2); 804 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1); 805 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2); 806 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 807 wine_dbgstr_rect(&rc2)); 808 } 809 break; 810 } 811 case WM_NCCREATE: 812 { 813 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021; 814 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; 815 816 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) 817 ok(got_getminmaxinfo, "main: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n"); 818 else 819 ok(!got_getminmaxinfo, "main: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n"); 820 break; 821 } 822 case WM_COMMAND: 823 if (test_lbuttondown_flag) 824 { 825 ShowWindow((HWND)wparam, SW_SHOW); 826 flush_events( FALSE ); 827 } 828 break; 829 case WM_GETTEXT: 830 num_gettext_msgs++; 831 if (g_wm_gettext_override.enabled) 832 { 833 char *text = (char*)lparam; 834 ok(g_wm_gettext_override.buff == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buff, text); 835 ok(*text == 0, "expected empty string buffer %x\n", *text); 836 return 0; 837 } 838 break; 839 case WM_SETTEXT: 840 num_settext_msgs++; 841 break; 842 case WM_ACTIVATEAPP: 843 if (wparam) app_activated = TRUE; 844 else app_deactivated = TRUE; 845 break; 846 } 847 848 return DefWindowProcA(hwnd, msg, wparam, lparam); 849 } 850 851 static LRESULT WINAPI main_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 852 { 853 switch (msg) 854 { 855 case WM_GETTEXT: 856 num_gettext_msgs++; 857 if (g_wm_gettext_override.enabled) 858 { 859 WCHAR *text = (WCHAR*)lparam; 860 ok(g_wm_gettext_override.buffW == text, "expected buffer %p, got %p\n", g_wm_gettext_override.buffW, text); 861 ok(*text == 0, "expected empty string buffer %x\n", *text); 862 return 0; 863 } 864 break; 865 } 866 867 return DefWindowProcA(hwnd, msg, wparam, lparam); 868 } 869 870 static LRESULT WINAPI tool_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 871 { 872 switch (msg) 873 { 874 case WM_GETMINMAXINFO: 875 { 876 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0x20031021); 877 break; 878 } 879 case WM_NCCREATE: 880 { 881 BOOL got_getminmaxinfo = GetWindowLongPtrA(hwnd, GWLP_USERDATA) == 0x20031021; 882 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; 883 884 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD))) 885 ok(got_getminmaxinfo, "tool: WM_GETMINMAXINFO should have been received before WM_NCCREATE\n"); 886 else 887 ok(!got_getminmaxinfo, "tool: WM_GETMINMAXINFO should NOT have been received before WM_NCCREATE\n"); 888 break; 889 } 890 } 891 892 return DefWindowProcA(hwnd, msg, wparam, lparam); 893 } 894 895 static const WCHAR mainclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s','W',0}; 896 897 static BOOL RegisterWindowClasses(void) 898 { 899 WNDCLASSW clsW; 900 WNDCLASSA cls; 901 902 cls.style = CS_DBLCLKS; 903 cls.lpfnWndProc = main_window_procA; 904 cls.cbClsExtra = 0; 905 cls.cbWndExtra = 0; 906 cls.hInstance = GetModuleHandleA(0); 907 cls.hIcon = 0; 908 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 909 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 910 cls.lpszMenuName = NULL; 911 cls.lpszClassName = "MainWindowClass"; 912 913 if(!RegisterClassA(&cls)) return FALSE; 914 915 clsW.style = CS_DBLCLKS; 916 clsW.lpfnWndProc = main_window_procW; 917 clsW.cbClsExtra = 0; 918 clsW.cbWndExtra = 0; 919 clsW.hInstance = GetModuleHandleA(0); 920 clsW.hIcon = 0; 921 clsW.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 922 clsW.hbrBackground = GetStockObject(WHITE_BRUSH); 923 clsW.lpszMenuName = NULL; 924 clsW.lpszClassName = mainclassW; 925 926 if(!RegisterClassW(&clsW)) return FALSE; 927 928 cls.style = 0; 929 cls.lpfnWndProc = tool_window_procA; 930 cls.cbClsExtra = 0; 931 cls.cbWndExtra = 0; 932 cls.hInstance = GetModuleHandleA(0); 933 cls.hIcon = 0; 934 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 935 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 936 cls.lpszMenuName = NULL; 937 cls.lpszClassName = "ToolWindowClass"; 938 939 if(!RegisterClassA(&cls)) return FALSE; 940 941 return TRUE; 942 } 943 944 static void verify_window_info(const char *hook, HWND hwnd, const WINDOWINFO *info) 945 { 946 RECT rcWindow, rcClient; 947 DWORD status; 948 949 ok(IsWindow(hwnd), "bad window handle %p in hook %s\n", hwnd, hook); 950 951 GetWindowRect(hwnd, &rcWindow); 952 ok(EqualRect(&rcWindow, &info->rcWindow), "wrong rcWindow for %p in hook %s\n", hwnd, hook); 953 954 GetClientRect(hwnd, &rcClient); 955 /* translate to screen coordinates */ 956 MapWindowPoints(hwnd, 0, (LPPOINT)&rcClient, 2); 957 ok(EqualRect(&rcClient, &info->rcClient), "wrong rcClient for %p in hook %s\n", hwnd, hook); 958 959 ok(info->dwStyle == (DWORD)GetWindowLongA(hwnd, GWL_STYLE), 960 "wrong dwStyle: %08x != %08x for %p in hook %s\n", 961 info->dwStyle, GetWindowLongA(hwnd, GWL_STYLE), hwnd, hook); 962 /* Windows reports some undocumented exstyles in WINDOWINFO, but 963 * doesn't return them in GetWindowLong(hwnd, GWL_EXSTYLE). 964 */ 965 ok((info->dwExStyle & ~0xe0000800) == (DWORD)GetWindowLongA(hwnd, GWL_EXSTYLE), 966 "wrong dwExStyle: %08x != %08x for %p in hook %s\n", 967 info->dwExStyle, GetWindowLongA(hwnd, GWL_EXSTYLE), hwnd, hook); 968 status = (GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0; 969 if (GetForegroundWindow()) 970 ok(info->dwWindowStatus == status, "wrong dwWindowStatus: %04x != %04x active %p fg %p in hook %s\n", 971 info->dwWindowStatus, status, GetActiveWindow(), GetForegroundWindow(), hook); 972 else 973 ok(1, "Just counting"); 974 975 /* win2k and XP return broken border info in GetWindowInfo most of 976 * the time, so there is no point in testing it. 977 */ 978 if (0) 979 { 980 UINT border; 981 ok(info->cxWindowBorders == (unsigned)(rcClient.left - rcWindow.left), 982 "wrong cxWindowBorders %d != %d\n", info->cxWindowBorders, rcClient.left - rcWindow.left); 983 border = min(rcWindow.bottom - rcClient.bottom, rcClient.top - rcWindow.top); 984 ok(info->cyWindowBorders == border, 985 "wrong cyWindowBorders %d != %d\n", info->cyWindowBorders, border); 986 } 987 ok(info->atomWindowType == GetClassLongA(hwnd, GCW_ATOM), "wrong atomWindowType for %p in hook %s\n", 988 hwnd, hook); 989 todo_ros 990 ok(info->wCreatorVersion == 0x0400 /* NT4, Win2000, XP, Win2003 */ || 991 info->wCreatorVersion == 0x0500 /* Vista */, 992 "wrong wCreatorVersion %04x for %p in hook %s\n", info->wCreatorVersion, hwnd, hook); 993 } 994 995 static void FixedAdjustWindowRectEx(RECT* rc, LONG style, BOOL menu, LONG exstyle) 996 { 997 AdjustWindowRectEx(rc, style, menu, exstyle); 998 /* AdjustWindowRectEx does not include scroll bars */ 999 if (style & WS_VSCROLL) 1000 { 1001 if(exstyle & WS_EX_LEFTSCROLLBAR) 1002 rc->left -= GetSystemMetrics(SM_CXVSCROLL); 1003 else 1004 rc->right += GetSystemMetrics(SM_CXVSCROLL); 1005 } 1006 if (style & WS_HSCROLL) 1007 rc->bottom += GetSystemMetrics(SM_CYHSCROLL); 1008 } 1009 1010 /* reimplement it to check that the Wine algorithm gives the correct result */ 1011 static void wine_AdjustWindowRectEx( RECT *rect, LONG style, BOOL menu, LONG exStyle ) 1012 { 1013 int adjust; 1014 1015 if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == 1016 WS_EX_STATICEDGE) 1017 { 1018 adjust = 1; /* for the outer frame always present */ 1019 } 1020 else 1021 { 1022 adjust = 0; 1023 if ((exStyle & WS_EX_DLGMODALFRAME) || 1024 (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */ 1025 } 1026 if (style & WS_THICKFRAME) 1027 adjust += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME); /* The resize border */ 1028 if ((style & (WS_BORDER|WS_DLGFRAME)) || 1029 (exStyle & WS_EX_DLGMODALFRAME)) 1030 adjust++; /* The other border */ 1031 1032 InflateRect (rect, adjust, adjust); 1033 1034 if ((style & WS_CAPTION) == WS_CAPTION) 1035 { 1036 if (exStyle & WS_EX_TOOLWINDOW) 1037 rect->top -= GetSystemMetrics(SM_CYSMCAPTION); 1038 else 1039 rect->top -= GetSystemMetrics(SM_CYCAPTION); 1040 } 1041 if (menu) rect->top -= GetSystemMetrics(SM_CYMENU); 1042 1043 if (exStyle & WS_EX_CLIENTEDGE) 1044 InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)); 1045 1046 if (style & WS_VSCROLL) 1047 { 1048 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0) 1049 rect->left -= GetSystemMetrics(SM_CXVSCROLL); 1050 else 1051 rect->right += GetSystemMetrics(SM_CXVSCROLL); 1052 } 1053 if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL); 1054 } 1055 1056 static void test_nonclient_area(HWND hwnd) 1057 { 1058 DWORD style, exstyle; 1059 RECT rc_window, rc_client, rc; 1060 BOOL menu; 1061 LRESULT ret; 1062 1063 style = GetWindowLongA(hwnd, GWL_STYLE); 1064 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 1065 menu = !(style & WS_CHILD) && GetMenu(hwnd) != 0; 1066 1067 GetWindowRect(hwnd, &rc_window); 1068 GetClientRect(hwnd, &rc_client); 1069 1070 /* avoid some cases when things go wrong */ 1071 if (IsRectEmpty(&rc_window) || IsRectEmpty(&rc_client) || 1072 rc_window.right > 32768 || rc_window.bottom > 32768) return; 1073 1074 rc = rc_client; 1075 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); 1076 FixedAdjustWindowRectEx(&rc, style, menu, exstyle); 1077 1078 ok(EqualRect(&rc, &rc_window), 1079 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n", 1080 style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc)); 1081 1082 rc = rc_client; 1083 MapWindowPoints(hwnd, 0, (LPPOINT)&rc, 2); 1084 wine_AdjustWindowRectEx(&rc, style, menu, exstyle); 1085 ok(EqualRect(&rc, &rc_window), 1086 "window rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, win=%s, calc=%s\n", 1087 style, exstyle, menu, wine_dbgstr_rect(&rc_window), wine_dbgstr_rect(&rc)); 1088 1089 1090 rc = rc_window; 1091 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc); 1092 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2); 1093 ok(EqualRect(&rc, &rc_client), 1094 "client rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d client=%s, calc=%s\n", 1095 style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc)); 1096 1097 /* NULL rectangle shouldn't crash */ 1098 ret = DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, 0); 1099 ok(ret == 0, "NULL rectangle returned %ld instead of 0\n", ret); 1100 1101 /* Win9x doesn't like WM_NCCALCSIZE with synthetic data and crashes */; 1102 if (is_win9x) 1103 return; 1104 1105 /* and now test AdjustWindowRectEx and WM_NCCALCSIZE on synthetic data */ 1106 SetRect(&rc_client, 0, 0, 250, 150); 1107 rc_window = rc_client; 1108 MapWindowPoints(hwnd, 0, (LPPOINT)&rc_window, 2); 1109 FixedAdjustWindowRectEx(&rc_window, style, menu, exstyle); 1110 1111 rc = rc_window; 1112 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc); 1113 MapWindowPoints(0, hwnd, (LPPOINT)&rc, 2); 1114 ok(EqualRect(&rc, &rc_client), 1115 "synthetic rect does not match: style:exstyle=0x%08x:0x%08x, menu=%d, client=%s, calc=%s\n", 1116 style, exstyle, menu, wine_dbgstr_rect(&rc_client), wine_dbgstr_rect(&rc)); 1117 } 1118 1119 static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) 1120 { 1121 static const char *CBT_code_name[10] = { 1122 "HCBT_MOVESIZE", 1123 "HCBT_MINMAX", 1124 "HCBT_QS", 1125 "HCBT_CREATEWND", 1126 "HCBT_DESTROYWND", 1127 "HCBT_ACTIVATE", 1128 "HCBT_CLICKSKIPPED", 1129 "HCBT_KEYSKIPPED", 1130 "HCBT_SYSCOMMAND", 1131 "HCBT_SETFOCUS" }; 1132 const char *code_name = (nCode >= 0 && nCode <= HCBT_SETFOCUS) ? CBT_code_name[nCode] : "Unknown"; 1133 HWND hwnd = (HWND)wParam; 1134 1135 switch (nCode) 1136 { 1137 case HCBT_CREATEWND: 1138 { 1139 static const RECT rc_null; 1140 RECT rc; 1141 LONG style; 1142 CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam; 1143 ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n"); 1144 1145 if (pGetWindowInfo) 1146 { 1147 WINDOWINFO info; 1148 info.cbSize = sizeof(WINDOWINFO); 1149 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n"); 1150 verify_window_info(code_name, hwnd, &info); 1151 } 1152 1153 /* WS_VISIBLE should be turned off yet */ 1154 style = createwnd->lpcs->style & ~WS_VISIBLE; 1155 ok(style == GetWindowLongA(hwnd, GWL_STYLE), 1156 "style of hwnd and style in the CREATESTRUCT do not match: %08x != %08x\n", 1157 GetWindowLongA(hwnd, GWL_STYLE), style); 1158 1159 if (0) 1160 { 1161 /* Uncomment this once the test succeeds in all cases */ 1162 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) 1163 { 1164 ok(GetParent(hwnd) == hwndMessage, 1165 "wrong result from GetParent %p: message window %p\n", 1166 GetParent(hwnd), hwndMessage); 1167 } 1168 else 1169 ok(!GetParent(hwnd), "GetParent should return 0 at this point\n"); 1170 1171 ok(!GetWindow(hwnd, GW_OWNER), "GW_OWNER should be set to 0 at this point\n"); 1172 } 1173 if (0) 1174 { 1175 /* while NT assigns GW_HWNDFIRST/LAST some values at this point, 1176 * Win9x still has them set to 0. 1177 */ 1178 ok(GetWindow(hwnd, GW_HWNDFIRST) != 0, "GW_HWNDFIRST should not be set to 0 at this point\n"); 1179 ok(GetWindow(hwnd, GW_HWNDLAST) != 0, "GW_HWNDLAST should not be set to 0 at this point\n"); 1180 } 1181 ok(!GetWindow(hwnd, GW_HWNDPREV), "GW_HWNDPREV should be set to 0 at this point\n"); 1182 ok(!GetWindow(hwnd, GW_HWNDNEXT), "GW_HWNDNEXT should be set to 0 at this point\n"); 1183 1184 if (0) 1185 { 1186 /* Uncomment this once the test succeeds in all cases */ 1187 if (pGetAncestor) 1188 { 1189 ok(pGetAncestor(hwnd, GA_PARENT) == hwndMessage, "GA_PARENT should be set to hwndMessage at this point\n"); 1190 ok(pGetAncestor(hwnd, GA_ROOT) == hwnd, 1191 "GA_ROOT is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOT), hwnd); 1192 1193 if ((style & (WS_CHILD|WS_POPUP)) == WS_CHILD) 1194 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwndMessage, 1195 "GA_ROOTOWNER should be set to hwndMessage at this point\n"); 1196 else 1197 ok(pGetAncestor(hwnd, GA_ROOTOWNER) == hwnd, 1198 "GA_ROOTOWNER is set to %p, expected %p\n", pGetAncestor(hwnd, GA_ROOTOWNER), hwnd); 1199 } 1200 1201 ok(GetWindowRect(hwnd, &rc), "GetWindowRect failed\n"); 1202 ok(EqualRect(&rc, &rc_null), "window rect should be set to 0 HCBT_CREATEWND\n"); 1203 ok(GetClientRect(hwnd, &rc), "GetClientRect failed\n"); 1204 ok(EqualRect(&rc, &rc_null), "client rect should be set to 0 on HCBT_CREATEWND\n"); 1205 } 1206 break; 1207 } 1208 case HCBT_MOVESIZE: 1209 case HCBT_MINMAX: 1210 case HCBT_ACTIVATE: 1211 if (pGetWindowInfo && IsWindow(hwnd)) 1212 { 1213 WINDOWINFO info; 1214 1215 /* Win98 actually does check the info.cbSize and doesn't allow 1216 * it to be anything except sizeof(WINDOWINFO), while Win95, Win2k, 1217 * WinXP do not check it at all. 1218 */ 1219 info.cbSize = sizeof(WINDOWINFO); 1220 ok(pGetWindowInfo(hwnd, &info), "GetWindowInfo should not fail\n"); 1221 verify_window_info(code_name, hwnd, &info); 1222 } 1223 break; 1224 /* window state is undefined */ 1225 case HCBT_SETFOCUS: 1226 case HCBT_DESTROYWND: 1227 break; 1228 default: 1229 break; 1230 } 1231 1232 return CallNextHookEx(hhook, nCode, wParam, lParam); 1233 } 1234 1235 static void test_shell_window(void) 1236 { 1237 BOOL ret; 1238 DWORD error; 1239 HMODULE hinst, hUser32; 1240 BOOL (WINAPI*SetShellWindow)(HWND); 1241 HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5; 1242 HWND shellWindow, nextWnd; 1243 1244 if (is_win9x) 1245 { 1246 win_skip("Skipping shell window test on Win9x\n"); 1247 return; 1248 } 1249 1250 shellWindow = GetShellWindow(); 1251 hinst = GetModuleHandleA(NULL); 1252 hUser32 = GetModuleHandleA("user32"); 1253 1254 SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow"); 1255 1256 trace("previous shell window: %p\n", shellWindow); 1257 1258 if (shellWindow) { 1259 DWORD pid; 1260 HANDLE hProcess; 1261 1262 GetWindowThreadProcessId(shellWindow, &pid); 1263 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 1264 if (!hProcess) 1265 { 1266 skip( "cannot get access to shell process\n" ); 1267 return; 1268 } 1269 1270 SetLastError(0xdeadbeef); 1271 ret = DestroyWindow(shellWindow); 1272 error = GetLastError(); 1273 1274 ok(!ret, "DestroyWindow(shellWindow)\n"); 1275 /* passes on Win XP, but not on Win98 */ 1276 ok(error==ERROR_ACCESS_DENIED || error == 0xdeadbeef, 1277 "got %u after DestroyWindow(shellWindow)\n", error); 1278 1279 /* close old shell instance */ 1280 ret = TerminateProcess(hProcess, 0); 1281 ok(ret, "termination of previous shell process failed: GetLastError()=%d\n", GetLastError()); 1282 WaitForSingleObject(hProcess, INFINITE); /* wait for termination */ 1283 CloseHandle(hProcess); 1284 } 1285 1286 hwnd1 = CreateWindowExA(0, "#32770", "TEST1", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0); 1287 trace("created window 1: %p\n", hwnd1); 1288 1289 ret = SetShellWindow(hwnd1); 1290 ok(ret, "first call to SetShellWindow(hwnd1)\n"); 1291 shellWindow = GetShellWindow(); 1292 ok(shellWindow==hwnd1, "wrong shell window: %p\n", shellWindow); 1293 1294 ret = SetShellWindow(hwnd1); 1295 ok(!ret, "second call to SetShellWindow(hwnd1)\n"); 1296 1297 ret = SetShellWindow(0); 1298 error = GetLastError(); 1299 /* passes on Win XP, but not on Win98 1300 ok(!ret, "reset shell window by SetShellWindow(0)\n"); 1301 ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */ 1302 1303 ret = SetShellWindow(hwnd1); 1304 /* passes on Win XP, but not on Win98 1305 ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */ 1306 1307 SetWindowLongA(hwnd1, GWL_EXSTYLE, GetWindowLongA(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST); 1308 ret = (GetWindowLongA(hwnd1,GWL_EXSTYLE) & WS_EX_TOPMOST) != 0; 1309 ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n"); 1310 1311 ret = DestroyWindow(hwnd1); 1312 ok(ret, "DestroyWindow(hwnd1)\n"); 1313 1314 hwnd2 = CreateWindowExA(WS_EX_TOPMOST, "#32770", "TEST2", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0); 1315 trace("created window 2: %p\n", hwnd2); 1316 ret = SetShellWindow(hwnd2); 1317 ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST\n"); 1318 1319 hwnd3 = CreateWindowExA(0, "#32770", "TEST3", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0); 1320 trace("created window 3: %p\n", hwnd3); 1321 1322 hwnd4 = CreateWindowExA(0, "#32770", "TEST4", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0); 1323 trace("created window 4: %p\n", hwnd4); 1324 1325 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); 1326 ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd); 1327 1328 ret = SetShellWindow(hwnd4); 1329 ok(ret, "SetShellWindow(hwnd4)\n"); 1330 shellWindow = GetShellWindow(); 1331 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow); 1332 1333 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); 1334 ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd); 1335 1336 ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 1337 ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n"); 1338 1339 ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 1340 ok(ret, "SetWindowPos(hwnd4, hwnd3\n"); 1341 1342 ret = SetShellWindow(hwnd3); 1343 ok(!ret, "SetShellWindow(hwnd3)\n"); 1344 shellWindow = GetShellWindow(); 1345 ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4\n", shellWindow); 1346 1347 hwnd5 = CreateWindowExA(0, "#32770", "TEST5", WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0); 1348 trace("created window 5: %p\n", hwnd5); 1349 ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 1350 ok(ret, "SetWindowPos(hwnd4, hwnd5)\n"); 1351 1352 todo_wine 1353 { 1354 nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); 1355 ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd); 1356 } 1357 1358 /* destroy test windows */ 1359 DestroyWindow(hwnd2); 1360 DestroyWindow(hwnd3); 1361 DestroyWindow(hwnd4); 1362 DestroyWindow(hwnd5); 1363 } 1364 1365 /************** MDI test ****************/ 1366 1367 static char mdi_lParam_test_message[] = "just a test string"; 1368 1369 static void test_MDI_create(HWND parent, HWND mdi_client, INT_PTR first_id) 1370 { 1371 MDICREATESTRUCTA mdi_cs; 1372 HWND mdi_child, hwnd, exp_hwnd; 1373 INT_PTR id; 1374 static const WCHAR classW[] = {'M','D','I','_','c','h','i','l','d','_','C','l','a','s','s','_','1',0}; 1375 static const WCHAR titleW[] = {'M','D','I',' ','c','h','i','l','d',0}; 1376 BOOL isWin9x = FALSE; 1377 HMENU frame_menu = GetMenu(parent); 1378 1379 ok(frame_menu != NULL, "Frame window didn't have a menu\n"); 1380 1381 mdi_cs.szClass = "MDI_child_Class_1"; 1382 mdi_cs.szTitle = "MDI child"; 1383 mdi_cs.hOwner = GetModuleHandleA(NULL); 1384 mdi_cs.x = CW_USEDEFAULT; 1385 mdi_cs.y = CW_USEDEFAULT; 1386 mdi_cs.cx = CW_USEDEFAULT; 1387 mdi_cs.cy = CW_USEDEFAULT; 1388 mdi_cs.style = 0; 1389 mdi_cs.lParam = (LPARAM)mdi_lParam_test_message; 1390 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 1391 ok(mdi_child != 0, "MDI child creation failed\n"); 1392 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1393 ok(id == first_id, "wrong child id %ld\n", id); 1394 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1395 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1396 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1397 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1398 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1399 1400 mdi_cs.style = 0x7fffffff; /* without WS_POPUP */ 1401 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 1402 ok(mdi_child != 0, "MDI child creation failed\n"); 1403 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1404 ok(id == first_id, "wrong child id %ld\n", id); 1405 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1406 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1407 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1408 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1409 1410 mdi_cs.style = 0xffffffff; /* with WS_POPUP */ 1411 mdi_child = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 1412 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES) 1413 { 1414 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n"); 1415 } 1416 else 1417 { 1418 ok(mdi_child != 0, "MDI child creation failed\n"); 1419 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1420 ok(id == first_id, "wrong child id %ld\n", id); 1421 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1422 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1423 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1424 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1425 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1426 } 1427 1428 /* test MDICREATESTRUCT A<->W mapping */ 1429 /* MDICREATESTRUCTA and MDICREATESTRUCTW have the same layout */ 1430 mdi_cs.style = 0; 1431 mdi_cs.szClass = (LPCSTR)classW; 1432 mdi_cs.szTitle = (LPCSTR)titleW; 1433 SetLastError(0xdeadbeef); 1434 mdi_child = (HWND)SendMessageW(mdi_client, WM_MDICREATE, 0, (LPARAM)&mdi_cs); 1435 if (!mdi_child) 1436 { 1437 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1438 isWin9x = TRUE; 1439 else 1440 ok(mdi_child != 0, "MDI child creation failed\n"); 1441 } 1442 else 1443 { 1444 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1445 ok(id == first_id, "wrong child id %ld\n", id); 1446 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1447 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1448 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1449 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1450 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1451 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1452 } 1453 1454 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child", 1455 0, 1456 CW_USEDEFAULT, CW_USEDEFAULT, 1457 CW_USEDEFAULT, CW_USEDEFAULT, 1458 mdi_client, GetModuleHandleA(NULL), 1459 (LPARAM)mdi_lParam_test_message); 1460 ok(mdi_child != 0, "MDI child creation failed\n"); 1461 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1462 ok(id == first_id, "wrong child id %ld\n", id); 1463 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1464 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1465 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1466 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1467 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1468 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1469 1470 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child", 1471 0x7fffffff, /* without WS_POPUP */ 1472 CW_USEDEFAULT, CW_USEDEFAULT, 1473 CW_USEDEFAULT, CW_USEDEFAULT, 1474 mdi_client, GetModuleHandleA(NULL), 1475 (LPARAM)mdi_lParam_test_message); 1476 ok(mdi_child != 0, "MDI child creation failed\n"); 1477 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1478 ok(id == first_id, "wrong child id %ld\n", id); 1479 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1480 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1481 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1482 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1483 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1484 1485 mdi_child = CreateMDIWindowA("MDI_child_Class_1", "MDI child", 1486 0xffffffff, /* with WS_POPUP */ 1487 CW_USEDEFAULT, CW_USEDEFAULT, 1488 CW_USEDEFAULT, CW_USEDEFAULT, 1489 mdi_client, GetModuleHandleA(NULL), 1490 (LPARAM)mdi_lParam_test_message); 1491 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES) 1492 { 1493 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n"); 1494 } 1495 else 1496 { 1497 ok(mdi_child != 0, "MDI child creation failed\n"); 1498 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1499 ok(id == first_id, "wrong child id %ld\n", id); 1500 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1501 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1502 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1503 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1504 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1505 } 1506 1507 /* test MDICREATESTRUCT A<->W mapping */ 1508 SetLastError(0xdeadbeef); 1509 mdi_child = CreateMDIWindowW(classW, titleW, 1510 0, 1511 CW_USEDEFAULT, CW_USEDEFAULT, 1512 CW_USEDEFAULT, CW_USEDEFAULT, 1513 mdi_client, GetModuleHandleA(NULL), 1514 (LPARAM)mdi_lParam_test_message); 1515 if (!mdi_child) 1516 { 1517 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1518 isWin9x = TRUE; 1519 else 1520 ok(mdi_child != 0, "MDI child creation failed\n"); 1521 } 1522 else 1523 { 1524 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1525 ok(id == first_id, "wrong child id %ld\n", id); 1526 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1527 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1528 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1529 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1530 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1531 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1532 } 1533 1534 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 1535 0, 1536 CW_USEDEFAULT, CW_USEDEFAULT, 1537 CW_USEDEFAULT, CW_USEDEFAULT, 1538 mdi_client, 0, GetModuleHandleA(NULL), 1539 mdi_lParam_test_message); 1540 ok(mdi_child != 0, "MDI child creation failed\n"); 1541 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1542 ok(id == first_id, "wrong child id %ld\n", id); 1543 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1544 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1545 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1546 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1547 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1548 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1549 1550 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 1551 WS_MAXIMIZE, 1552 CW_USEDEFAULT, CW_USEDEFAULT, 1553 CW_USEDEFAULT, CW_USEDEFAULT, 1554 mdi_client, 0, GetModuleHandleA(NULL), 1555 mdi_lParam_test_message); 1556 ok(mdi_child != 0, "MDI child creation failed\n"); 1557 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1558 ok(id == first_id, "wrong child id %ld\n", id); 1559 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1560 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1561 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1562 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES) 1563 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1564 else 1565 ok(GetMenuItemCount(frame_menu) == 4, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1566 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1567 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1568 1569 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 1570 0x7fffffff, /* without WS_POPUP */ 1571 CW_USEDEFAULT, CW_USEDEFAULT, 1572 CW_USEDEFAULT, CW_USEDEFAULT, 1573 mdi_client, 0, GetModuleHandleA(NULL), 1574 mdi_lParam_test_message); 1575 ok(mdi_child != 0, "MDI child creation failed\n"); 1576 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1577 ok(id == first_id, "wrong child id %ld\n", id); 1578 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1579 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1580 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1581 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1582 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1583 1584 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 1585 0xffffffff, /* with WS_POPUP */ 1586 CW_USEDEFAULT, CW_USEDEFAULT, 1587 CW_USEDEFAULT, CW_USEDEFAULT, 1588 mdi_client, 0, GetModuleHandleA(NULL), 1589 mdi_lParam_test_message); 1590 if (GetWindowLongA(mdi_client, GWL_STYLE) & MDIS_ALLCHILDSTYLES) 1591 { 1592 ok(!mdi_child, "MDI child with WS_POPUP and with MDIS_ALLCHILDSTYLES should fail\n"); 1593 } 1594 else 1595 { 1596 ok(mdi_child != 0, "MDI child creation failed\n"); 1597 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1598 ok(id == first_id, "wrong child id %ld\n", id); 1599 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1600 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1601 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1602 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1603 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1604 } 1605 1606 /* test MDICREATESTRUCT A<->W mapping */ 1607 SetLastError(0xdeadbeef); 1608 mdi_child = CreateWindowExW(WS_EX_MDICHILD, classW, titleW, 1609 0, 1610 CW_USEDEFAULT, CW_USEDEFAULT, 1611 CW_USEDEFAULT, CW_USEDEFAULT, 1612 mdi_client, 0, GetModuleHandleA(NULL), 1613 mdi_lParam_test_message); 1614 if (!mdi_child) 1615 { 1616 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1617 isWin9x = TRUE; 1618 else 1619 ok(mdi_child != 0, "MDI child creation failed\n"); 1620 } 1621 else 1622 { 1623 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1624 ok(id == first_id, "wrong child id %ld\n", id); 1625 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1626 exp_hwnd = (GetWindowLongW(mdi_child, GWL_STYLE) & WS_VISIBLE) ? mdi_child : 0; 1627 ok(hwnd == exp_hwnd, "WM_MDIGETACTIVE should return %p, got %p\n", exp_hwnd, hwnd); 1628 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1629 SendMessageA(mdi_client, WM_MDIDESTROY, (WPARAM)mdi_child, 0); 1630 ok(!IsWindow(mdi_child), "WM_MDIDESTROY failed\n"); 1631 } 1632 1633 /* This test fails on Win9x */ 1634 if (!isWin9x) 1635 { 1636 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_2", "MDI child", 1637 WS_CHILD, 1638 CW_USEDEFAULT, CW_USEDEFAULT, 1639 CW_USEDEFAULT, CW_USEDEFAULT, 1640 parent, 0, GetModuleHandleA(NULL), 1641 mdi_lParam_test_message); 1642 ok(!mdi_child, "WS_EX_MDICHILD with a not MDIClient parent should fail\n"); 1643 } 1644 1645 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", 1646 WS_CHILD, /* without WS_POPUP */ 1647 CW_USEDEFAULT, CW_USEDEFAULT, 1648 CW_USEDEFAULT, CW_USEDEFAULT, 1649 mdi_client, 0, GetModuleHandleA(NULL), 1650 mdi_lParam_test_message); 1651 ok(mdi_child != 0, "MDI child creation failed\n"); 1652 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1653 ok(id == 0, "wrong child id %ld\n", id); 1654 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1655 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1656 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1657 DestroyWindow(mdi_child); 1658 1659 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", 1660 WS_CHILD | WS_POPUP, /* with WS_POPUP */ 1661 CW_USEDEFAULT, CW_USEDEFAULT, 1662 CW_USEDEFAULT, CW_USEDEFAULT, 1663 mdi_client, 0, GetModuleHandleA(NULL), 1664 mdi_lParam_test_message); 1665 ok(mdi_child != 0, "MDI child creation failed\n"); 1666 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1667 ok(id == 0, "wrong child id %ld\n", id); 1668 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1669 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1670 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1671 DestroyWindow(mdi_child); 1672 1673 /* maximized child */ 1674 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", 1675 WS_CHILD | WS_MAXIMIZE, 1676 CW_USEDEFAULT, CW_USEDEFAULT, 1677 CW_USEDEFAULT, CW_USEDEFAULT, 1678 mdi_client, 0, GetModuleHandleA(NULL), 1679 mdi_lParam_test_message); 1680 ok(mdi_child != 0, "MDI child creation failed\n"); 1681 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1682 ok(id == 0, "wrong child id %ld\n", id); 1683 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1684 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1685 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1686 DestroyWindow(mdi_child); 1687 1688 trace("Creating maximized child with a caption\n"); 1689 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", 1690 WS_CHILD | WS_MAXIMIZE | WS_CAPTION, 1691 CW_USEDEFAULT, CW_USEDEFAULT, 1692 CW_USEDEFAULT, CW_USEDEFAULT, 1693 mdi_client, 0, GetModuleHandleA(NULL), 1694 mdi_lParam_test_message); 1695 ok(mdi_child != 0, "MDI child creation failed\n"); 1696 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1697 ok(id == 0, "wrong child id %ld\n", id); 1698 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1699 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1700 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1701 DestroyWindow(mdi_child); 1702 1703 trace("Creating maximized child with a caption and a thick frame\n"); 1704 mdi_child = CreateWindowExA(0, "MDI_child_Class_2", "MDI child", 1705 WS_CHILD | WS_MAXIMIZE | WS_CAPTION | WS_THICKFRAME, 1706 CW_USEDEFAULT, CW_USEDEFAULT, 1707 CW_USEDEFAULT, CW_USEDEFAULT, 1708 mdi_client, 0, GetModuleHandleA(NULL), 1709 mdi_lParam_test_message); 1710 ok(mdi_child != 0, "MDI child creation failed\n"); 1711 id = GetWindowLongPtrA(mdi_child, GWLP_ID); 1712 ok(id == 0, "wrong child id %ld\n", id); 1713 hwnd = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1714 ok(!hwnd, "WM_MDIGETACTIVE should return 0, got %p\n", hwnd); 1715 ok(GetMenuItemCount(frame_menu) == 0, "Got wrong frame menu item count: %u\n", GetMenuItemCount(frame_menu)); 1716 DestroyWindow(mdi_child); 1717 } 1718 1719 static void test_MDI_child_stack(HWND mdi_client) 1720 { 1721 HWND child_1, child_2, child_3, child_4; 1722 HWND stack[4]; 1723 MDICREATESTRUCTA cs; 1724 1725 cs.szClass = "MDI_child_Class_1"; 1726 cs.szTitle = "MDI child"; 1727 cs.hOwner = GetModuleHandleA(0); 1728 cs.x = CW_USEDEFAULT; 1729 cs.y = CW_USEDEFAULT; 1730 cs.cx = CW_USEDEFAULT; 1731 cs.cy = CW_USEDEFAULT; 1732 cs.style = 0; 1733 cs.lParam = (LPARAM)mdi_lParam_test_message; 1734 1735 child_1 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs); 1736 ok(child_1 != 0, "expected child_1 to be non NULL\n"); 1737 child_2 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs); 1738 ok(child_2 != 0, "expected child_2 to be non NULL\n"); 1739 child_3 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs); 1740 ok(child_3 != 0, "expected child_3 to be non NULL\n"); 1741 child_4 = (HWND)SendMessageA(mdi_client, WM_MDICREATE, 0, (LPARAM)&cs); 1742 ok(child_4 != 0, "expected child_4 to be non NULL\n"); 1743 1744 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1745 stack[1] = GetWindow(stack[0], GW_HWNDNEXT); 1746 stack[2] = GetWindow(stack[1], GW_HWNDNEXT); 1747 stack[3] = GetWindow(stack[2], GW_HWNDNEXT); 1748 trace("Initial MDI child stack: %p->%p->%p->%p\n", stack[0], stack[1], stack[2], stack[3]); 1749 ok(stack[0] == child_4 && stack[1] == child_3 && 1750 stack[2] == child_2 && stack[3] == child_1, 1751 "Unexpected initial order, should be: %p->%p->%p->%p\n", 1752 child_4, child_3, child_2, child_1); 1753 1754 trace("Activate child next to %p\n", child_3); 1755 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_3, 0); 1756 1757 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1758 stack[1] = GetWindow(stack[0], GW_HWNDNEXT); 1759 stack[2] = GetWindow(stack[1], GW_HWNDNEXT); 1760 stack[3] = GetWindow(stack[2], GW_HWNDNEXT); 1761 ok(stack[0] == child_2 && stack[1] == child_4 && 1762 stack[2] == child_1 && stack[3] == child_3, 1763 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n", 1764 child_2, child_4, child_1, child_3, stack[0], stack[1], stack[2], stack[3]); 1765 1766 trace("Activate child previous to %p\n", child_1); 1767 SendMessageA(mdi_client, WM_MDINEXT, (WPARAM)child_1, 1); 1768 1769 stack[0] = (HWND)SendMessageA(mdi_client, WM_MDIGETACTIVE, 0, 0); 1770 stack[1] = GetWindow(stack[0], GW_HWNDNEXT); 1771 stack[2] = GetWindow(stack[1], GW_HWNDNEXT); 1772 stack[3] = GetWindow(stack[2], GW_HWNDNEXT); 1773 ok(stack[0] == child_4 && stack[1] == child_2 && 1774 stack[2] == child_1 && stack[3] == child_3, 1775 "Broken MDI child stack:\nexpected: %p->%p->%p->%p, but got: %p->%p->%p->%p\n", 1776 child_4, child_2, child_1, child_3, stack[0], stack[1], stack[2], stack[3]); 1777 1778 DestroyWindow(child_1); 1779 DestroyWindow(child_2); 1780 DestroyWindow(child_3); 1781 DestroyWindow(child_4); 1782 } 1783 1784 /********************************************************************** 1785 * MDI_ChildGetMinMaxInfo (copied from windows/mdi.c) 1786 * 1787 * Note: The rule here is that client rect of the maximized MDI child 1788 * is equal to the client rect of the MDI client window. 1789 */ 1790 static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax ) 1791 { 1792 RECT rect; 1793 1794 GetClientRect( client, &rect ); 1795 AdjustWindowRectEx( &rect, GetWindowLongA( hwnd, GWL_STYLE ), 1796 0, GetWindowLongA( hwnd, GWL_EXSTYLE )); 1797 1798 rect.right -= rect.left; 1799 rect.bottom -= rect.top; 1800 lpMinMax->ptMaxSize.x = rect.right; 1801 lpMinMax->ptMaxSize.y = rect.bottom; 1802 1803 lpMinMax->ptMaxPosition.x = rect.left; 1804 lpMinMax->ptMaxPosition.y = rect.top; 1805 1806 trace("max rect %s\n", wine_dbgstr_rect(&rect)); 1807 } 1808 1809 static LRESULT WINAPI mdi_child_wnd_proc_1(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 1810 { 1811 switch (msg) 1812 { 1813 case WM_NCCREATE: 1814 case WM_CREATE: 1815 { 1816 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; 1817 MDICREATESTRUCTA *mdi_cs = cs->lpCreateParams; 1818 1819 ok(cs->dwExStyle & WS_EX_MDICHILD, "WS_EX_MDICHILD should be set\n"); 1820 ok(mdi_cs->lParam == (LPARAM)mdi_lParam_test_message, "wrong mdi_cs->lParam\n"); 1821 1822 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_1"), "wrong class name\n"); 1823 ok(!lstrcmpA(cs->lpszClass, mdi_cs->szClass), "class name does not match\n"); 1824 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n"); 1825 ok(!lstrcmpA(cs->lpszName, mdi_cs->szTitle), "title does not match\n"); 1826 ok(cs->hInstance == mdi_cs->hOwner, "%p != %p\n", cs->hInstance, mdi_cs->hOwner); 1827 1828 /* MDICREATESTRUCT should have original values */ 1829 ok(mdi_cs->style == 0 || mdi_cs->style == 0x7fffffff || mdi_cs->style == 0xffffffff || mdi_cs->style == WS_MAXIMIZE, 1830 "mdi_cs->style does not match (%08x)\n", mdi_cs->style); 1831 ok(mdi_cs->x == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->x); 1832 ok(mdi_cs->y == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->y); 1833 ok(mdi_cs->cx == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cx); 1834 ok(mdi_cs->cy == CW_USEDEFAULT, "%d != CW_USEDEFAULT\n", mdi_cs->cy); 1835 1836 /* CREATESTRUCT should have fixed values */ 1837 ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x); 1838 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y); 1839 1840 /* cx/cy == CW_USEDEFAULT are translated to NOT zero values */ 1841 ok(cs->cx != CW_USEDEFAULT && cs->cx != 0, "%d == CW_USEDEFAULT\n", cs->cx); 1842 ok(cs->cy != CW_USEDEFAULT && cs->cy != 0, "%d == CW_USEDEFAULT\n", cs->cy); 1843 1844 ok(!(cs->style & WS_POPUP), "WS_POPUP is not allowed\n"); 1845 1846 if (GetWindowLongA(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES) 1847 { 1848 LONG style = mdi_cs->style | WS_CHILD | WS_CLIPSIBLINGS; 1849 ok(cs->style == style, 1850 "cs->style does not match (%08x)\n", cs->style); 1851 } 1852 else 1853 { 1854 LONG style = mdi_cs->style; 1855 style &= ~WS_POPUP; 1856 style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | 1857 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX; 1858 ok(cs->style == style, 1859 "cs->style does not match (%08x)\n", cs->style); 1860 } 1861 break; 1862 } 1863 1864 case WM_GETMINMAXINFO: 1865 { 1866 HWND client = GetParent(hwnd); 1867 RECT rc; 1868 MINMAXINFO *minmax = (MINMAXINFO *)lparam; 1869 MINMAXINFO my_minmax; 1870 LONG style, exstyle; 1871 1872 style = GetWindowLongA(hwnd, GWL_STYLE); 1873 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 1874 1875 GetClientRect(client, &rc); 1876 1877 GetClientRect(client, &rc); 1878 if ((style & WS_CAPTION) == WS_CAPTION) 1879 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ 1880 AdjustWindowRectEx(&rc, style, 0, exstyle); 1881 trace("MDI child: calculated max window size = (%d x %d)\n", rc.right-rc.left, rc.bottom-rc.top); 1882 dump_minmax_info( minmax ); 1883 1884 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n", 1885 minmax->ptMaxSize.x, rc.right - rc.left); 1886 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n", 1887 minmax->ptMaxSize.y, rc.bottom - rc.top); 1888 1889 DefMDIChildProcA(hwnd, msg, wparam, lparam); 1890 1891 trace("DefMDIChildProc returned:\n"); 1892 dump_minmax_info( minmax ); 1893 1894 MDI_ChildGetMinMaxInfo(client, hwnd, &my_minmax); 1895 ok(minmax->ptMaxSize.x == my_minmax.ptMaxSize.x, "default width of maximized child %d != %d\n", 1896 minmax->ptMaxSize.x, my_minmax.ptMaxSize.x); 1897 ok(minmax->ptMaxSize.y == my_minmax.ptMaxSize.y, "default height of maximized child %d != %d\n", 1898 minmax->ptMaxSize.y, my_minmax.ptMaxSize.y); 1899 1900 return 1; 1901 } 1902 1903 case WM_MDIACTIVATE: 1904 { 1905 HWND active, client = GetParent(hwnd); 1906 /*trace("%p WM_MDIACTIVATE %08x %08lx\n", hwnd, wparam, lparam);*/ 1907 active = (HWND)SendMessageA(client, WM_MDIGETACTIVE, 0, 0); 1908 if (hwnd == (HWND)lparam) /* if we are being activated */ 1909 ok (active == (HWND)lparam, "new active %p != active %p\n", (HWND)lparam, active); 1910 else 1911 ok (active == (HWND)wparam, "old active %p != active %p\n", (HWND)wparam, active); 1912 break; 1913 } 1914 } 1915 return DefMDIChildProcA(hwnd, msg, wparam, lparam); 1916 } 1917 1918 static LRESULT WINAPI mdi_child_wnd_proc_2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 1919 { 1920 switch (msg) 1921 { 1922 case WM_NCCREATE: 1923 case WM_CREATE: 1924 { 1925 CREATESTRUCTA *cs = (CREATESTRUCTA *)lparam; 1926 1927 trace("%s: x %d, y %d, cx %d, cy %d\n", (msg == WM_NCCREATE) ? "WM_NCCREATE" : "WM_CREATE", 1928 cs->x, cs->y, cs->cx, cs->cy); 1929 1930 ok(!(cs->dwExStyle & WS_EX_MDICHILD), "WS_EX_MDICHILD should not be set\n"); 1931 ok(cs->lpCreateParams == mdi_lParam_test_message, "wrong cs->lpCreateParams\n"); 1932 1933 ok(!lstrcmpA(cs->lpszClass, "MDI_child_Class_2"), "wrong class name\n"); 1934 ok(!lstrcmpA(cs->lpszName, "MDI child"), "wrong title\n"); 1935 1936 /* CREATESTRUCT should have fixed values */ 1937 /* For some reason Win9x doesn't translate cs->x from CW_USEDEFAULT, 1938 while NT does. */ 1939 /*ok(cs->x != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->x);*/ 1940 ok(cs->y != CW_USEDEFAULT, "%d == CW_USEDEFAULT\n", cs->y); 1941 1942 /* cx/cy == CW_USEDEFAULT are translated to 0 */ 1943 /* For some reason Win98 doesn't translate cs->cx from CW_USEDEFAULT, 1944 while Win95, Win2k, WinXP do. */ 1945 /*ok(cs->cx == 0, "%d != 0\n", cs->cx);*/ 1946 ok(cs->cy == 0, "%d != 0\n", cs->cy); 1947 break; 1948 } 1949 1950 case WM_GETMINMAXINFO: 1951 { 1952 HWND parent = GetParent(hwnd); 1953 RECT rc; 1954 MINMAXINFO *minmax = (MINMAXINFO *)lparam; 1955 LONG style, exstyle; 1956 1957 style = GetWindowLongA(hwnd, GWL_STYLE); 1958 exstyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 1959 1960 GetClientRect(parent, &rc); 1961 trace("WM_GETMINMAXINFO: parent %p client size = (%d x %d)\n", parent, rc.right, rc.bottom); 1962 1963 GetClientRect(parent, &rc); 1964 if ((style & WS_CAPTION) == WS_CAPTION) 1965 style &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ 1966 AdjustWindowRectEx(&rc, style, 0, exstyle); 1967 dump_minmax_info( minmax ); 1968 1969 ok(minmax->ptMaxSize.x == rc.right - rc.left, "default width of maximized child %d != %d\n", 1970 minmax->ptMaxSize.x, rc.right - rc.left); 1971 ok(minmax->ptMaxSize.y == rc.bottom - rc.top, "default height of maximized child %d != %d\n", 1972 minmax->ptMaxSize.y, rc.bottom - rc.top); 1973 break; 1974 } 1975 1976 case WM_WINDOWPOSCHANGED: 1977 { 1978 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 1979 RECT rc1, rc2; 1980 1981 GetWindowRect(hwnd, &rc1); 1982 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy); 1983 /* note: winpos coordinates are relative to parent */ 1984 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2); 1985 ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s pos=%s\n", 1986 wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 1987 GetWindowRect(hwnd, &rc1); 1988 GetClientRect(hwnd, &rc2); 1989 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1); 1990 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2); 1991 ok(EqualRect(&rc1, &rc2), "rects do not match, window=%s client=%s\n", 1992 wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 1993 } 1994 /* fall through */ 1995 case WM_WINDOWPOSCHANGING: 1996 { 1997 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 1998 WINDOWPOS my_winpos = *winpos; 1999 2000 trace("%s: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", 2001 (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED", 2002 winpos->hwnd, winpos->hwndInsertAfter, 2003 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); 2004 2005 DefWindowProcA(hwnd, msg, wparam, lparam); 2006 2007 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)), 2008 "DefWindowProc should not change WINDOWPOS: %p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", 2009 winpos->hwnd, winpos->hwndInsertAfter, 2010 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); 2011 2012 return 1; 2013 } 2014 } 2015 return DefWindowProcA(hwnd, msg, wparam, lparam); 2016 } 2017 2018 static LRESULT WINAPI mdi_main_wnd_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 2019 { 2020 static HWND mdi_client; 2021 2022 switch (msg) 2023 { 2024 case WM_CREATE: 2025 return 1; 2026 2027 case WM_WINDOWPOSCHANGED: 2028 { 2029 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 2030 RECT rc1, rc2; 2031 2032 GetWindowRect(hwnd, &rc1); 2033 trace("window: %s\n", wine_dbgstr_rect(&rc1)); 2034 SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy); 2035 /* note: winpos coordinates are relative to parent */ 2036 MapWindowPoints(GetParent(hwnd), 0, (LPPOINT)&rc2, 2); 2037 trace("pos: %s\n", wine_dbgstr_rect(&rc2)); 2038 ok(EqualRect(&rc1, &rc2), "rects do not match\n"); 2039 2040 GetWindowRect(hwnd, &rc1); 2041 GetClientRect(hwnd, &rc2); 2042 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)&rc1); 2043 MapWindowPoints(0, hwnd, (LPPOINT)&rc1, 2); 2044 ok(EqualRect(&rc1, &rc2), "rects do not match\n"); 2045 } 2046 /* fall through */ 2047 case WM_WINDOWPOSCHANGING: 2048 { 2049 WINDOWPOS *winpos = (WINDOWPOS *)lparam; 2050 WINDOWPOS my_winpos = *winpos; 2051 2052 trace("%s\n", (msg == WM_WINDOWPOSCHANGING) ? "WM_WINDOWPOSCHANGING" : "WM_WINDOWPOSCHANGED"); 2053 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", 2054 winpos->hwnd, winpos->hwndInsertAfter, 2055 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); 2056 2057 DefWindowProcA(hwnd, msg, wparam, lparam); 2058 2059 trace("%p after %p, x %d, y %d, cx %d, cy %d flags %08x\n", 2060 winpos->hwnd, winpos->hwndInsertAfter, 2061 winpos->x, winpos->y, winpos->cx, winpos->cy, winpos->flags); 2062 2063 ok(!memcmp(&my_winpos, winpos, sizeof(WINDOWPOS)), 2064 "DefWindowProc should not change WINDOWPOS values\n"); 2065 2066 return 1; 2067 } 2068 2069 case WM_CLOSE: 2070 PostQuitMessage(0); 2071 break; 2072 } 2073 return DefFrameProcA(hwnd, mdi_client, msg, wparam, lparam); 2074 } 2075 2076 static BOOL mdi_RegisterWindowClasses(void) 2077 { 2078 WNDCLASSA cls; 2079 2080 cls.style = 0; 2081 cls.lpfnWndProc = mdi_main_wnd_procA; 2082 cls.cbClsExtra = 0; 2083 cls.cbWndExtra = 0; 2084 cls.hInstance = GetModuleHandleA(0); 2085 cls.hIcon = 0; 2086 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 2087 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 2088 cls.lpszMenuName = NULL; 2089 cls.lpszClassName = "MDI_parent_Class"; 2090 if(!RegisterClassA(&cls)) return FALSE; 2091 2092 cls.lpfnWndProc = mdi_child_wnd_proc_1; 2093 cls.lpszClassName = "MDI_child_Class_1"; 2094 if(!RegisterClassA(&cls)) return FALSE; 2095 2096 cls.lpfnWndProc = mdi_child_wnd_proc_2; 2097 cls.lpszClassName = "MDI_child_Class_2"; 2098 if(!RegisterClassA(&cls)) return FALSE; 2099 2100 return TRUE; 2101 } 2102 2103 static void test_mdi(void) 2104 { 2105 static const DWORD style[] = { 0, WS_HSCROLL, WS_VSCROLL, WS_HSCROLL | WS_VSCROLL }; 2106 HWND mdi_hwndMain, mdi_client, mdi_child; 2107 CLIENTCREATESTRUCT client_cs; 2108 RECT rc; 2109 DWORD i; 2110 MSG msg; 2111 HMENU frame_menu, child_menu; 2112 2113 if (!mdi_RegisterWindowClasses()) assert(0); 2114 2115 mdi_hwndMain = CreateWindowExA(0, "MDI_parent_Class", "MDI parent window", 2116 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 2117 WS_MAXIMIZEBOX /*| WS_VISIBLE*/, 2118 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 2119 GetDesktopWindow(), 0, 2120 GetModuleHandleA(NULL), NULL); 2121 assert(mdi_hwndMain); 2122 2123 frame_menu = CreateMenu(); 2124 2125 GetClientRect(mdi_hwndMain, &rc); 2126 2127 client_cs.hWindowMenu = 0; 2128 client_cs.idFirstChild = 1; 2129 2130 for (i = 0; i < sizeof(style)/sizeof(style[0]); i++) 2131 { 2132 SCROLLINFO si; 2133 BOOL ret, gotit; 2134 2135 mdi_client = CreateWindowExA(0, "mdiclient", NULL, 2136 WS_CHILD | style[i], 2137 0, 0, rc.right, rc.bottom, 2138 mdi_hwndMain, 0, 0, &client_cs); 2139 ok(mdi_client != 0, "MDI client creation failed\n"); 2140 2141 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 2142 0, 2143 CW_USEDEFAULT, CW_USEDEFAULT, 2144 CW_USEDEFAULT, CW_USEDEFAULT, 2145 mdi_client, 0, 0, 2146 mdi_lParam_test_message); 2147 ok(mdi_child != 0, "MDI child creation failed\n"); 2148 2149 SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0); 2150 SetMenu(mdi_hwndMain, frame_menu); 2151 2152 ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child maximize, but has %u\n", 2153 GetMenuItemCount(frame_menu)); 2154 2155 child_menu = CreateMenu(); 2156 SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu); 2157 2158 ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after WM_MDISETMENU, but has %u\n", 2159 GetMenuItemCount(frame_menu)); 2160 2161 SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0); 2162 2163 ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n", 2164 GetMenuItemCount(frame_menu)); 2165 2166 SetMenu(mdi_hwndMain, NULL); 2167 2168 si.cbSize = sizeof(si); 2169 si.fMask = SIF_ALL; 2170 ret = GetScrollInfo(mdi_client, SB_HORZ, &si); 2171 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2172 { 2173 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]); 2174 ok(si.nPage == 0, "expected 0\n"); 2175 ok(si.nPos == 0, "expected 0\n"); 2176 ok(si.nTrackPos == 0, "expected 0\n"); 2177 ok(si.nMin == 0, "expected 0\n"); 2178 ok(si.nMax == 100, "expected 100\n"); 2179 } 2180 else 2181 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]); 2182 2183 ret = GetScrollInfo(mdi_client, SB_VERT, &si); 2184 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2185 { 2186 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]); 2187 ok(si.nPage == 0, "expected 0\n"); 2188 ok(si.nPos == 0, "expected 0\n"); 2189 ok(si.nTrackPos == 0, "expected 0\n"); 2190 ok(si.nMin == 0, "expected 0\n"); 2191 ok(si.nMax == 100, "expected 100\n"); 2192 } 2193 else 2194 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]); 2195 2196 SetWindowPos(mdi_child, 0, -100, -100, 0, 0, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); 2197 2198 si.cbSize = sizeof(si); 2199 si.fMask = SIF_ALL; 2200 ret = GetScrollInfo(mdi_client, SB_HORZ, &si); 2201 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2202 { 2203 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]); 2204 ok(si.nPage == 0, "expected 0\n"); 2205 ok(si.nPos == 0, "expected 0\n"); 2206 ok(si.nTrackPos == 0, "expected 0\n"); 2207 ok(si.nMin == 0, "expected 0\n"); 2208 ok(si.nMax == 100, "expected 100\n"); 2209 } 2210 else 2211 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]); 2212 2213 ret = GetScrollInfo(mdi_client, SB_VERT, &si); 2214 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2215 { 2216 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]); 2217 ok(si.nPage == 0, "expected 0\n"); 2218 ok(si.nPos == 0, "expected 0\n"); 2219 ok(si.nTrackPos == 0, "expected 0\n"); 2220 ok(si.nMin == 0, "expected 0\n"); 2221 ok(si.nMax == 100, "expected 100\n"); 2222 } 2223 else 2224 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]); 2225 2226 gotit = FALSE; 2227 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 2228 { 2229 if (msg.message == WM_MOUSEMOVE || msg.message == WM_PAINT) 2230 { 2231 DispatchMessageA(&msg); 2232 continue; 2233 } 2234 2235 if (msg.message == 0x003f) /* WM_MDICALCCHILDSCROLL ??? */ 2236 { 2237 ok(msg.hwnd == mdi_client, "message 0x003f should be posted to mdiclient\n"); 2238 gotit = TRUE; 2239 } 2240 else 2241 ok(msg.hwnd != mdi_client, "message %04x should not be posted to mdiclient\n", msg.message); 2242 DispatchMessageA(&msg); 2243 } 2244 ok(gotit, "message 0x003f should appear after SetWindowPos\n"); 2245 2246 si.cbSize = sizeof(si); 2247 si.fMask = SIF_ALL; 2248 ret = GetScrollInfo(mdi_client, SB_HORZ, &si); 2249 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2250 { 2251 ok(ret, "style %#x: GetScrollInfo(SB_HORZ) failed\n", style[i]); 2252 todo_wine 2253 ok(si.nPage != 0, "expected !0\n"); 2254 ok(si.nPos == 0, "expected 0\n"); 2255 ok(si.nTrackPos == 0, "expected 0\n"); 2256 ok(si.nMin != 0, "expected !0\n"); 2257 ok(si.nMax != 100, "expected !100\n"); 2258 } 2259 else 2260 ok(!ret, "style %#x: GetScrollInfo(SB_HORZ) should fail\n", style[i]); 2261 2262 ret = GetScrollInfo(mdi_client, SB_VERT, &si); 2263 if (style[i] & (WS_HSCROLL | WS_VSCROLL)) 2264 { 2265 ok(ret, "style %#x: GetScrollInfo(SB_VERT) failed\n", style[i]); 2266 todo_wine 2267 ok(si.nPage != 0, "expected !0\n"); 2268 ok(si.nPos == 0, "expected 0\n"); 2269 ok(si.nTrackPos == 0, "expected 0\n"); 2270 ok(si.nMin != 0, "expected !0\n"); 2271 ok(si.nMax != 100, "expected !100\n"); 2272 } 2273 else 2274 ok(!ret, "style %#x: GetScrollInfo(SB_VERT) should fail\n", style[i]); 2275 2276 DestroyMenu(child_menu); 2277 DestroyWindow(mdi_child); 2278 DestroyWindow(mdi_client); 2279 } 2280 2281 SetMenu(mdi_hwndMain, frame_menu); 2282 2283 mdi_client = CreateWindowExA(0, "mdiclient", NULL, 2284 WS_CHILD, 2285 0, 0, rc.right, rc.bottom, 2286 mdi_hwndMain, 0, 0, &client_cs); 2287 ok(mdi_client != 0, "MDI client creation failed\n"); 2288 2289 mdi_child = CreateWindowExA(WS_EX_MDICHILD, "MDI_child_Class_1", "MDI child", 2290 0, 2291 CW_USEDEFAULT, CW_USEDEFAULT, 2292 CW_USEDEFAULT, CW_USEDEFAULT, 2293 mdi_client, 0, 0, 2294 mdi_lParam_test_message); 2295 ok(mdi_child != 0, "MDI child creation failed\n"); 2296 2297 SendMessageW(mdi_child, WM_SIZE, SIZE_MAXIMIZED, 0); 2298 ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after child maximize, but has %u\n", 2299 GetMenuItemCount(frame_menu)); 2300 2301 child_menu = CreateMenu(); 2302 SendMessageW(mdi_client, WM_MDISETMENU, 0, (LPARAM)child_menu); 2303 2304 ok(GetMenuItemCount(frame_menu) == 4, "Frame menu should have 4 items after WM_MDISETMENU, but has %u\n", 2305 GetMenuItemCount(frame_menu)); 2306 2307 SendMessageW(mdi_child, WM_SIZE, SIZE_RESTORED, 0); 2308 2309 ok(GetMenuItemCount(frame_menu) == 0, "Frame menu should be empty after child restored, but has %u items\n", 2310 GetMenuItemCount(frame_menu)); 2311 2312 DestroyMenu(child_menu); 2313 DestroyWindow(mdi_child); 2314 DestroyWindow(mdi_client); 2315 2316 /* MDIClient without MDIS_ALLCHILDSTYLES */ 2317 mdi_client = CreateWindowExA(0, "mdiclient", 2318 NULL, 2319 WS_CHILD /*| WS_VISIBLE*/, 2320 /* tests depend on a not zero MDIClient size */ 2321 0, 0, rc.right, rc.bottom, 2322 mdi_hwndMain, 0, GetModuleHandleA(NULL), 2323 &client_cs); 2324 assert(mdi_client); 2325 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild); 2326 DestroyWindow(mdi_client); 2327 2328 /* MDIClient with MDIS_ALLCHILDSTYLES */ 2329 mdi_client = CreateWindowExA(0, "mdiclient", 2330 NULL, 2331 WS_CHILD | MDIS_ALLCHILDSTYLES /*| WS_VISIBLE*/, 2332 /* tests depend on a not zero MDIClient size */ 2333 0, 0, rc.right, rc.bottom, 2334 mdi_hwndMain, 0, GetModuleHandleA(NULL), 2335 &client_cs); 2336 assert(mdi_client); 2337 test_MDI_create(mdi_hwndMain, mdi_client, client_cs.idFirstChild); 2338 DestroyWindow(mdi_client); 2339 2340 /* Test child window stack management */ 2341 mdi_client = CreateWindowExA(0, "mdiclient", 2342 NULL, 2343 WS_CHILD, 2344 0, 0, rc.right, rc.bottom, 2345 mdi_hwndMain, 0, GetModuleHandleA(NULL), 2346 &client_cs); 2347 assert(mdi_client); 2348 test_MDI_child_stack(mdi_client); 2349 DestroyWindow(mdi_client); 2350 /* 2351 while(GetMessage(&msg, 0, 0, 0)) 2352 { 2353 TranslateMessage(&msg); 2354 DispatchMessage(&msg); 2355 } 2356 */ 2357 DestroyWindow(mdi_hwndMain); 2358 } 2359 2360 static void test_icons(void) 2361 { 2362 WNDCLASSEXA cls; 2363 HWND hwnd; 2364 HICON icon = LoadIconA(0, (LPCSTR)IDI_APPLICATION); 2365 HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION); 2366 HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON, 2367 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED ); 2368 HICON res; 2369 2370 cls.cbSize = sizeof(cls); 2371 cls.style = 0; 2372 cls.lpfnWndProc = DefWindowProcA; 2373 cls.cbClsExtra = 0; 2374 cls.cbWndExtra = 0; 2375 cls.hInstance = 0; 2376 cls.hIcon = LoadIconA(0, (LPCSTR)IDI_HAND); 2377 cls.hIconSm = small_icon; 2378 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 2379 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 2380 cls.lpszMenuName = NULL; 2381 cls.lpszClassName = "IconWindowClass"; 2382 2383 RegisterClassExA(&cls); 2384 2385 hwnd = CreateWindowExA(0, "IconWindowClass", "icon test", 0, 2386 100, 100, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL); 2387 assert( hwnd ); 2388 2389 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 ); 2390 ok( res == 0, "wrong big icon %p/0\n", res ); 2391 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon ); 2392 ok( res == 0, "wrong previous big icon %p/0\n", res ); 2393 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 ); 2394 ok( res == icon, "wrong big icon after set %p/%p\n", res, icon ); 2395 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 ); 2396 ok( res == icon, "wrong previous big icon %p/%p\n", res, icon ); 2397 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 ); 2398 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 ); 2399 2400 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 ); 2401 ok( res == 0, "wrong small icon %p/0\n", res ); 2402 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 ); 2403 ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res ); 2404 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon ); 2405 ok( res == 0, "wrong previous small icon %p/0\n", res ); 2406 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 ); 2407 ok( res == icon, "wrong small icon after set %p/%p\n", res, icon ); 2408 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 ); 2409 ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon ); 2410 res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon ); 2411 ok( res == icon, "wrong previous small icon %p/%p\n", res, icon ); 2412 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 ); 2413 ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon ); 2414 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 ); 2415 ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon ); 2416 2417 /* make sure the big icon hasn't changed */ 2418 res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 ); 2419 ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 ); 2420 2421 DestroyWindow( hwnd ); 2422 } 2423 2424 static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 2425 { 2426 if (msg == WM_NCCALCSIZE) 2427 { 2428 RECT *rect = (RECT *)lparam; 2429 /* first time around increase the rectangle, next time decrease it */ 2430 if (rect->left == 100) InflateRect( rect, 10, 10 ); 2431 else InflateRect( rect, -10, -10 ); 2432 return 0; 2433 } 2434 return DefWindowProcA( hwnd, msg, wparam, lparam ); 2435 } 2436 2437 static void test_SetWindowPos(HWND hwnd, HWND hwnd2) 2438 { 2439 RECT orig_win_rc, rect; 2440 LONG_PTR old_proc; 2441 HWND hwnd_grandchild, hwnd_child, hwnd_child2; 2442 HWND hwnd_desktop; 2443 RECT rc1, rc2; 2444 BOOL ret; 2445 2446 SetRect(&rect, 111, 222, 333, 444); 2447 ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n"); 2448 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444, 2449 "wrong window rect %s\n", wine_dbgstr_rect(&rect)); 2450 2451 SetRect(&rect, 111, 222, 333, 444); 2452 ok(!GetClientRect(0, &rect), "GetClientRect succeeded\n"); 2453 ok(rect.left == 111 && rect.top == 222 && rect.right == 333 && rect.bottom == 444, 2454 "wrong window rect %s\n", wine_dbgstr_rect(&rect)); 2455 2456 GetWindowRect(hwnd, &orig_win_rc); 2457 2458 old_proc = SetWindowLongPtrA( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc ); 2459 ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED); 2460 ok(ret, "Got %d\n", ret); 2461 GetWindowRect( hwnd, &rect ); 2462 ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100, 2463 "invalid window rect %s\n", wine_dbgstr_rect(&rect)); 2464 GetClientRect( hwnd, &rect ); 2465 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 ); 2466 ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110, 2467 "invalid client rect %s\n", wine_dbgstr_rect(&rect)); 2468 2469 ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED); 2470 ok(ret, "Got %d\n", ret); 2471 GetWindowRect( hwnd, &rect ); 2472 ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200, 2473 "invalid window rect %s\n", wine_dbgstr_rect(&rect)); 2474 GetClientRect( hwnd, &rect ); 2475 MapWindowPoints( hwnd, 0, (POINT *)&rect, 2 ); 2476 ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190, 2477 "invalid client rect %s\n", wine_dbgstr_rect(&rect)); 2478 2479 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top, 2480 orig_win_rc.right, orig_win_rc.bottom, 0); 2481 ok(ret, "Got %d\n", ret); 2482 SetWindowLongPtrA( hwnd, GWLP_WNDPROC, old_proc ); 2483 2484 /* Win9x truncates coordinates to 16-bit irrespectively */ 2485 if (!is_win9x) 2486 { 2487 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE); 2488 ok(ret, "Got %d\n", ret); 2489 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE); 2490 ok(ret, "Got %d\n", ret); 2491 2492 ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE); 2493 ok(ret, "Got %d\n", ret); 2494 ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE); 2495 ok(ret, "Got %d\n", ret); 2496 } 2497 2498 ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top, 2499 orig_win_rc.right, orig_win_rc.bottom, 0); 2500 ok(ret, "Got %d\n", ret); 2501 2502 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n"); 2503 ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 2504 ok(ret, "Got %d\n", ret); 2505 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n"); 2506 ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 2507 ok(ret, "Got %d\n", ret); 2508 ok(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n"); 2509 ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 2510 ok(ret, "Got %d\n", ret); 2511 ok(!(GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n"); 2512 2513 hwnd_desktop = GetDesktopWindow(); 2514 ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError()); 2515 hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd); 2516 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError()); 2517 hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd_child); 2518 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError()); 2519 hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd); 2520 ok(!!hwnd_child2, "Failed to create second child window (%d)\n", GetLastError()); 2521 2522 ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2523 ok(ret, "Got %d\n", ret); 2524 check_active_state(hwnd, hwnd, hwnd); 2525 2526 ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2527 ok(ret, "Got %d\n", ret); 2528 check_active_state(hwnd2, hwnd2, hwnd2); 2529 2530 /* Returns TRUE also for windows that are not siblings */ 2531 ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2532 ok(ret, "Got %d\n", ret); 2533 check_active_state(hwnd2, hwnd2, hwnd2); 2534 2535 ret = SetWindowPos(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2536 ok(ret, "Got %d\n", ret); 2537 check_active_state(hwnd2, hwnd2, hwnd2); 2538 2539 /* Does not seem to do anything even without passing flags, still returns TRUE */ 2540 GetWindowRect(hwnd_child, &rc1); 2541 ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0); 2542 ok(ret, "Got %d\n", ret); 2543 GetWindowRect(hwnd_child, &rc2); 2544 ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 2545 check_active_state(hwnd2, hwnd2, hwnd2); 2546 2547 /* Same thing the other way around. */ 2548 GetWindowRect(hwnd2, &rc1); 2549 ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0); 2550 ok(ret, "Got %d\n", ret); 2551 GetWindowRect(hwnd2, &rc2); 2552 ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 2553 check_active_state(hwnd2, hwnd2, hwnd2); 2554 2555 /* .. and with these windows. */ 2556 GetWindowRect(hwnd_grandchild, &rc1); 2557 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0); 2558 ok(ret, "Got %d\n", ret); 2559 GetWindowRect(hwnd_grandchild, &rc2); 2560 ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 2561 check_active_state(hwnd2, hwnd2, hwnd2); 2562 2563 /* Add SWP_NOZORDER and it will be properly resized. */ 2564 GetWindowRect(hwnd_grandchild, &rc1); 2565 ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER); 2566 ok(ret, "Got %d\n", ret); 2567 GetWindowRect(hwnd_grandchild, &rc2); 2568 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top && 2569 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom, 2570 "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, 2571 wine_dbgstr_rect(&rc2)); 2572 check_active_state(hwnd2, hwnd2, hwnd2); 2573 2574 /* Given a sibling window, the window is properly resized. */ 2575 GetWindowRect(hwnd_child, &rc1); 2576 ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0); 2577 ok(ret, "Got %d\n", ret); 2578 GetWindowRect(hwnd_child, &rc2); 2579 ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top && 2580 (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom, 2581 "(%d,%d)-(%d,%d) != %s\n", rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, 2582 wine_dbgstr_rect(&rc2)); 2583 check_active_state(hwnd2, hwnd2, hwnd2); 2584 2585 /* Involving the desktop window changes things. */ 2586 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2587 ok(!ret, "Got %d\n", ret); 2588 check_active_state(hwnd2, hwnd2, hwnd2); 2589 2590 GetWindowRect(hwnd_child, &rc1); 2591 ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0); 2592 ok(!ret, "Got %d\n", ret); 2593 GetWindowRect(hwnd_child, &rc2); 2594 ok(EqualRect(&rc1, &rc2), "%s != %s\n", wine_dbgstr_rect(&rc1), wine_dbgstr_rect(&rc2)); 2595 check_active_state(hwnd2, hwnd2, hwnd2); 2596 2597 ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2598 ok(!ret, "Got %d\n", ret); 2599 check_active_state(hwnd2, hwnd2, hwnd2); 2600 2601 ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2602 ok(!ret, "Got %d\n", ret); 2603 check_active_state(hwnd2, hwnd2, hwnd2); 2604 2605 ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); 2606 ok(!ret, "Got %d\n", ret); 2607 check_active_state(hwnd2, hwnd2, hwnd2); 2608 2609 DestroyWindow(hwnd_grandchild); 2610 DestroyWindow(hwnd_child); 2611 DestroyWindow(hwnd_child2); 2612 2613 hwnd_child = create_tool_window(WS_CHILD|WS_POPUP|WS_SYSMENU, hwnd2); 2614 ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError()); 2615 ret = SetWindowPos(hwnd_child, NULL, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE|SWP_SHOWWINDOW); 2616 ok(ret, "Got %d\n", ret); 2617 flush_events( TRUE ); 2618 todo_wine check_active_state(hwnd2, hwnd2, hwnd2); 2619 DestroyWindow(hwnd_child); 2620 } 2621 2622 static void test_SetMenu(HWND parent) 2623 { 2624 HWND child; 2625 HMENU hMenu, ret; 2626 BOOL retok; 2627 DWORD style; 2628 2629 hMenu = CreateMenu(); 2630 assert(hMenu); 2631 2632 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n"); 2633 if (0) 2634 { 2635 /* fails on (at least) Wine, NT4, XP SP2 */ 2636 test_nonclient_area(parent); 2637 } 2638 ret = GetMenu(parent); 2639 ok(ret == hMenu, "unexpected menu id %p\n", ret); 2640 /* test whether we can destroy a menu assigned to a window */ 2641 retok = DestroyMenu(hMenu); 2642 ok( retok, "DestroyMenu error %d\n", GetLastError()); 2643 retok = IsMenu(hMenu); 2644 ok(!retok || broken(retok) /* nt4 */, "menu handle should be not valid after DestroyMenu\n"); 2645 ret = GetMenu(parent); 2646 /* This test fails on Win9x */ 2647 if (!is_win9x) 2648 ok(ret == hMenu, "unexpected menu id %p\n", ret); 2649 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n"); 2650 test_nonclient_area(parent); 2651 2652 hMenu = CreateMenu(); 2653 assert(hMenu); 2654 2655 /* parent */ 2656 ret = GetMenu(parent); 2657 ok(ret == 0, "unexpected menu id %p\n", ret); 2658 2659 ok(!SetMenu(parent, (HMENU)20), "SetMenu with invalid menu handle should fail\n"); 2660 test_nonclient_area(parent); 2661 ret = GetMenu(parent); 2662 ok(ret == 0, "unexpected menu id %p\n", ret); 2663 2664 ok(SetMenu(parent, hMenu), "SetMenu on a top level window should not fail\n"); 2665 if (0) 2666 { 2667 /* fails on (at least) Wine, NT4, XP SP2 */ 2668 test_nonclient_area(parent); 2669 } 2670 ret = GetMenu(parent); 2671 ok(ret == hMenu, "unexpected menu id %p\n", ret); 2672 2673 ok(SetMenu(parent, 0), "SetMenu(0) on a top level window should not fail\n"); 2674 test_nonclient_area(parent); 2675 ret = GetMenu(parent); 2676 ok(ret == 0, "unexpected menu id %p\n", ret); 2677 2678 /* child */ 2679 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, parent, (HMENU)10, 0, NULL); 2680 assert(child); 2681 2682 ret = GetMenu(child); 2683 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); 2684 2685 ok(!SetMenu(child, (HMENU)20), "SetMenu with invalid menu handle should fail\n"); 2686 test_nonclient_area(child); 2687 ret = GetMenu(child); 2688 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); 2689 2690 ok(!SetMenu(child, hMenu), "SetMenu on a child window should fail\n"); 2691 test_nonclient_area(child); 2692 ret = GetMenu(child); 2693 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); 2694 2695 ok(!SetMenu(child, 0), "SetMenu(0) on a child window should fail\n"); 2696 test_nonclient_area(child); 2697 ret = GetMenu(child); 2698 ok(ret == (HMENU)10, "unexpected menu id %p\n", ret); 2699 2700 style = GetWindowLongA(child, GWL_STYLE); 2701 SetWindowLongA(child, GWL_STYLE, style | WS_POPUP); 2702 ok(SetMenu(child, hMenu), "SetMenu on a popup child window should not fail\n"); 2703 ok(SetMenu(child, 0), "SetMenu on a popup child window should not fail\n"); 2704 SetWindowLongA(child, GWL_STYLE, style); 2705 2706 SetWindowLongA(child, GWL_STYLE, style | WS_OVERLAPPED); 2707 ok(!SetMenu(child, hMenu), "SetMenu on an overlapped child window should fail\n"); 2708 SetWindowLongA(child, GWL_STYLE, style); 2709 2710 DestroyWindow(child); 2711 DestroyMenu(hMenu); 2712 } 2713 2714 static void test_window_tree(HWND parent, const DWORD *style, const int *order, int total) 2715 { 2716 HWND child[5], hwnd; 2717 INT_PTR i; 2718 2719 assert(total <= 5); 2720 2721 hwnd = GetWindow(parent, GW_CHILD); 2722 ok(!hwnd, "have to start without children to perform the test\n"); 2723 2724 for (i = 0; i < total; i++) 2725 { 2726 if (style[i] & DS_CONTROL) 2727 { 2728 child[i] = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(32770), "", style[i] & ~WS_VISIBLE, 2729 0,0,0,0, parent, (HMENU)i, 0, NULL); 2730 if (style[i] & WS_VISIBLE) 2731 ShowWindow(child[i], SW_SHOW); 2732 2733 SetWindowPos(child[i], HWND_BOTTOM, 0,0,10,10, SWP_NOACTIVATE); 2734 } 2735 else 2736 child[i] = CreateWindowExA(0, "static", "", style[i], 0,0,10,10, 2737 parent, (HMENU)i, 0, NULL); 2738 trace("child[%ld] = %p\n", i, child[i]); 2739 ok(child[i] != 0, "CreateWindowEx failed to create child window\n"); 2740 } 2741 2742 hwnd = GetWindow(parent, GW_CHILD); 2743 ok(hwnd != 0, "GetWindow(GW_CHILD) failed\n"); 2744 ok(hwnd == GetWindow(child[total - 1], GW_HWNDFIRST), "GW_HWNDFIRST is wrong\n"); 2745 ok(child[order[total - 1]] == GetWindow(child[0], GW_HWNDLAST), "GW_HWNDLAST is wrong\n"); 2746 2747 for (i = 0; i < total; i++) 2748 { 2749 trace("hwnd[%ld] = %p\n", i, hwnd); 2750 ok(child[order[i]] == hwnd, "Z order of child #%ld is wrong\n", i); 2751 2752 hwnd = GetWindow(hwnd, GW_HWNDNEXT); 2753 } 2754 2755 for (i = 0; i < total; i++) 2756 ok(DestroyWindow(child[i]), "DestroyWindow failed\n"); 2757 } 2758 2759 static void test_children_zorder(HWND parent) 2760 { 2761 const DWORD simple_style[5] = { WS_CHILD, WS_CHILD, WS_CHILD, WS_CHILD, 2762 WS_CHILD }; 2763 const int simple_order[5] = { 0, 1, 2, 3, 4 }; 2764 2765 const DWORD complex_style[5] = { WS_CHILD, WS_CHILD | WS_MAXIMIZE, 2766 WS_CHILD | WS_VISIBLE, WS_CHILD, 2767 WS_CHILD | WS_MAXIMIZE | WS_VISIBLE }; 2768 const int complex_order_1[1] = { 0 }; 2769 const int complex_order_2[2] = { 1, 0 }; 2770 const int complex_order_3[3] = { 1, 0, 2 }; 2771 const int complex_order_4[4] = { 1, 0, 2, 3 }; 2772 const int complex_order_5[5] = { 4, 1, 0, 2, 3 }; 2773 const DWORD complex_style_6[3] = { WS_CHILD | WS_VISIBLE, 2774 WS_CHILD | WS_CLIPSIBLINGS | DS_CONTROL | WS_VISIBLE, 2775 WS_CHILD | WS_VISIBLE }; 2776 const int complex_order_6[3] = { 0, 1, 2 }; 2777 2778 /* simple WS_CHILD */ 2779 test_window_tree(parent, simple_style, simple_order, 5); 2780 2781 /* complex children styles */ 2782 test_window_tree(parent, complex_style, complex_order_1, 1); 2783 test_window_tree(parent, complex_style, complex_order_2, 2); 2784 test_window_tree(parent, complex_style, complex_order_3, 3); 2785 test_window_tree(parent, complex_style, complex_order_4, 4); 2786 test_window_tree(parent, complex_style, complex_order_5, 5); 2787 2788 /* another set of complex children styles */ 2789 test_window_tree(parent, complex_style_6, complex_order_6, 3); 2790 } 2791 2792 #define check_z_order(hwnd, next, prev, owner, topmost) \ 2793 check_z_order_debug((hwnd), (next), (prev), (owner), (topmost), \ 2794 __FILE__, __LINE__) 2795 2796 static void check_z_order_debug(HWND hwnd, HWND next, HWND prev, HWND owner, 2797 BOOL topmost, const char *file, int line) 2798 { 2799 HWND test; 2800 DWORD ex_style; 2801 2802 test = GetWindow(hwnd, GW_HWNDNEXT); 2803 /* skip foreign windows */ 2804 while (test && test != next && 2805 (GetWindowThreadProcessId(test, NULL) != our_pid || 2806 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) || 2807 GetWindow(test, GW_OWNER) == next)) 2808 { 2809 /*trace("skipping next %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/ 2810 test = GetWindow(test, GW_HWNDNEXT); 2811 } 2812 ok_(file, line)(next == test, "%p: expected next %p, got %p\n", hwnd, next, test); 2813 2814 test = GetWindow(hwnd, GW_HWNDPREV); 2815 /* skip foreign windows */ 2816 while (test && test != prev && 2817 (GetWindowThreadProcessId(test, NULL) != our_pid || 2818 UlongToHandle(GetWindowLongPtrA(test, GWLP_HINSTANCE)) != GetModuleHandleA(NULL) || 2819 GetWindow(test, GW_OWNER) == hwnd)) 2820 { 2821 /*trace("skipping prev %p (%p)\n", test, UlongToHandle(GetWindowLongPtr(test, GWLP_HINSTANCE)));*/ 2822 test = GetWindow(test, GW_HWNDPREV); 2823 } 2824 ok_(file, line)(prev == test, "%p: expected prev %p, got %p\n", hwnd, prev, test); 2825 2826 test = GetWindow(hwnd, GW_OWNER); 2827 ok_(file, line)(owner == test, "%p: expected owner %p, got %p\n", hwnd, owner, test); 2828 2829 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 2830 ok_(file, line)(!(ex_style & WS_EX_TOPMOST) == !topmost, "%p: expected %stopmost\n", 2831 hwnd, topmost ? "" : "NOT "); 2832 } 2833 2834 static void test_popup_zorder(HWND hwnd_D, HWND hwnd_E, DWORD style) 2835 { 2836 HWND hwnd_A, hwnd_B, hwnd_C, hwnd_F; 2837 2838 trace("hwnd_D %p, hwnd_E %p\n", hwnd_D, hwnd_E); 2839 2840 SetWindowPos(hwnd_E, hwnd_D, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 2841 2842 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE); 2843 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE); 2844 2845 hwnd_F = CreateWindowExA(0, "MainWindowClass", "Owner window", 2846 WS_OVERLAPPED | WS_CAPTION, 2847 100, 100, 100, 100, 2848 0, 0, GetModuleHandleA(NULL), NULL); 2849 trace("hwnd_F %p\n", hwnd_F); 2850 check_z_order(hwnd_F, hwnd_D, 0, 0, FALSE); 2851 2852 SetWindowPos(hwnd_F, hwnd_E, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 2853 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE); 2854 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE); 2855 check_z_order(hwnd_D, hwnd_E, 0, 0, FALSE); 2856 2857 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL, 2858 style, 2859 100, 100, 100, 100, 2860 hwnd_F, 0, GetModuleHandleA(NULL), NULL); 2861 trace("hwnd_C %p\n", hwnd_C); 2862 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE); 2863 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE); 2864 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE); 2865 check_z_order(hwnd_C, hwnd_D, 0, hwnd_F, FALSE); 2866 2867 hwnd_B = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL, 2868 style, 2869 100, 100, 100, 100, 2870 hwnd_F, 0, GetModuleHandleA(NULL), NULL); 2871 trace("hwnd_B %p\n", hwnd_B); 2872 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE); 2873 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE); 2874 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE); 2875 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE); 2876 check_z_order(hwnd_B, hwnd_C, 0, hwnd_F, TRUE); 2877 2878 hwnd_A = CreateWindowExA(WS_EX_TOPMOST, "MainWindowClass", NULL, 2879 style, 2880 100, 100, 100, 100, 2881 0, 0, GetModuleHandleA(NULL), NULL); 2882 trace("hwnd_A %p\n", hwnd_A); 2883 check_z_order(hwnd_F, 0, hwnd_E, 0, FALSE); 2884 check_z_order(hwnd_E, hwnd_F, hwnd_D, 0, FALSE); 2885 check_z_order(hwnd_D, hwnd_E, hwnd_C, 0, FALSE); 2886 check_z_order(hwnd_C, hwnd_D, hwnd_B, hwnd_F, FALSE); 2887 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE); 2888 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE); 2889 2890 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); 2891 2892 /* move hwnd_F and its popups up */ 2893 SetWindowPos(hwnd_F, HWND_TOP, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 2894 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE); 2895 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE); 2896 check_z_order(hwnd_F, hwnd_D, hwnd_C, 0, FALSE); 2897 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE); 2898 check_z_order(hwnd_B, hwnd_C, hwnd_A, hwnd_F, TRUE); 2899 check_z_order(hwnd_A, hwnd_B, 0, 0, TRUE); 2900 2901 /* move hwnd_F and its popups down */ 2902 #if 0 /* enable once Wine is fixed to pass this test */ 2903 SetWindowPos(hwnd_F, HWND_BOTTOM, 0,0,0,0, SWP_NOSIZE|SWP_NOMOVE|SWP_NOACTIVATE); 2904 check_z_order(hwnd_F, 0, hwnd_C, 0, FALSE); 2905 check_z_order(hwnd_C, hwnd_F, hwnd_B, hwnd_F, FALSE); 2906 check_z_order(hwnd_B, hwnd_C, hwnd_E, hwnd_F, FALSE); 2907 check_z_order(hwnd_E, hwnd_B, hwnd_D, 0, FALSE); 2908 check_z_order(hwnd_D, hwnd_E, hwnd_A, 0, FALSE); 2909 check_z_order(hwnd_A, hwnd_D, 0, 0, TRUE); 2910 #endif 2911 2912 /* make hwnd_C owned by a topmost window */ 2913 DestroyWindow( hwnd_C ); 2914 hwnd_C = CreateWindowExA(0, "MainWindowClass", NULL, 2915 style, 2916 100, 100, 100, 100, 2917 hwnd_A, 0, GetModuleHandleA(NULL), NULL); 2918 trace("hwnd_C %p\n", hwnd_C); 2919 check_z_order(hwnd_E, 0, hwnd_D, 0, FALSE); 2920 check_z_order(hwnd_D, hwnd_E, hwnd_F, 0, FALSE); 2921 check_z_order(hwnd_F, hwnd_D, hwnd_B, 0, FALSE); 2922 check_z_order(hwnd_B, hwnd_F, hwnd_A, hwnd_F, TRUE); 2923 check_z_order(hwnd_A, hwnd_B, hwnd_C, 0, TRUE); 2924 check_z_order(hwnd_C, hwnd_A, 0, hwnd_A, TRUE); 2925 2926 DestroyWindow(hwnd_A); 2927 DestroyWindow(hwnd_B); 2928 DestroyWindow(hwnd_C); 2929 DestroyWindow(hwnd_F); 2930 } 2931 2932 static void test_vis_rgn( HWND hwnd ) 2933 { 2934 RECT win_rect, rgn_rect; 2935 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); 2936 HDC hdc; 2937 2938 ShowWindow(hwnd,SW_SHOW); 2939 hdc = GetDC( hwnd ); 2940 ok( GetRandomRgn( hdc, hrgn, SYSRGN ) != 0, "GetRandomRgn failed\n" ); 2941 GetWindowRect( hwnd, &win_rect ); 2942 GetRgnBox( hrgn, &rgn_rect ); 2943 if (is_win9x) 2944 { 2945 trace("win9x, mapping to screen coords\n"); 2946 MapWindowPoints( hwnd, 0, (POINT *)&rgn_rect, 2 ); 2947 } 2948 trace("win: %s\n", wine_dbgstr_rect(&win_rect)); 2949 trace("rgn: %s\n", wine_dbgstr_rect(&rgn_rect)); 2950 ok( win_rect.left <= rgn_rect.left, "rgn left %d not inside win rect %d\n", 2951 rgn_rect.left, win_rect.left ); 2952 ok( win_rect.top <= rgn_rect.top, "rgn top %d not inside win rect %d\n", 2953 rgn_rect.top, win_rect.top ); 2954 ok( win_rect.right >= rgn_rect.right, "rgn right %d not inside win rect %d\n", 2955 rgn_rect.right, win_rect.right ); 2956 ok( win_rect.bottom >= rgn_rect.bottom, "rgn bottom %d not inside win rect %d\n", 2957 rgn_rect.bottom, win_rect.bottom ); 2958 ReleaseDC( hwnd, hdc ); 2959 } 2960 2961 static LRESULT WINAPI set_focus_on_activate_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 2962 { 2963 if (msg == WM_ACTIVATE && LOWORD(wp) == WA_ACTIVE) 2964 { 2965 HWND child = GetWindow(hwnd, GW_CHILD); 2966 ok(child != 0, "couldn't find child window\n"); 2967 SetFocus(child); 2968 ok(GetFocus() == child, "Focus should be on child %p\n", child); 2969 return 0; 2970 } 2971 return DefWindowProcA(hwnd, msg, wp, lp); 2972 } 2973 2974 static void test_SetFocus(HWND hwnd) 2975 { 2976 HWND child, child2, ret; 2977 WNDPROC old_wnd_proc; 2978 2979 /* check if we can set focus to non-visible windows */ 2980 2981 ShowWindow(hwnd, SW_SHOW); 2982 SetFocus(0); 2983 SetFocus(hwnd); 2984 ok( GetFocus() == hwnd, "Failed to set focus to visible window %p\n", hwnd ); 2985 ok( GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE, "Window %p not visible\n", hwnd ); 2986 ShowWindow(hwnd, SW_HIDE); 2987 SetFocus(0); 2988 SetFocus(hwnd); 2989 ok( GetFocus() == hwnd, "Failed to set focus to invisible window %p\n", hwnd ); 2990 ok( !(GetWindowLongA(hwnd,GWL_STYLE) & WS_VISIBLE), "Window %p still visible\n", hwnd ); 2991 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, hwnd, 0, 0, NULL); 2992 assert(child); 2993 SetFocus(child); 2994 ok( GetFocus() == child, "Failed to set focus to invisible child %p\n", child ); 2995 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child ); 2996 ShowWindow(child, SW_SHOW); 2997 ok( GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE, "Child %p is not visible\n", child ); 2998 ok( GetFocus() == child, "Focus no longer on child %p\n", child ); 2999 ShowWindow(child, SW_HIDE); 3000 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child ); 3001 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() ); 3002 ShowWindow(child, SW_SHOW); 3003 child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, 0, 0, NULL); 3004 assert(child2); 3005 ShowWindow(child2, SW_SHOW); 3006 SetFocus(child2); 3007 ShowWindow(child, SW_HIDE); 3008 ok( !(GetWindowLongA(child,GWL_STYLE) & WS_VISIBLE), "Child %p is visible\n", child ); 3009 ok( GetFocus() == child2, "Focus should be on %p, not %p\n", child2, GetFocus() ); 3010 ShowWindow(child, SW_SHOW); 3011 SetFocus(child); 3012 ok( GetFocus() == child, "Focus should be on child %p\n", child ); 3013 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_HIDEWINDOW); 3014 ok( GetFocus() == child, "Focus should still be on child %p\n", child ); 3015 3016 ShowWindow(child, SW_HIDE); 3017 SetFocus(hwnd); 3018 ok( GetFocus() == hwnd, "Focus should be on parent %p, not %p\n", hwnd, GetFocus() ); 3019 SetWindowPos(child,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); 3020 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() ); 3021 ShowWindow(child, SW_HIDE); 3022 ok( GetFocus() == hwnd, "Focus should still be on parent %p, not %p\n", hwnd, GetFocus() ); 3023 3024 ShowWindow(hwnd, SW_SHOW); 3025 ShowWindow(child, SW_SHOW); 3026 SetFocus(child); 3027 ok( GetFocus() == child, "Focus should be on child %p\n", child ); 3028 EnableWindow(hwnd, FALSE); 3029 ok( GetFocus() == child, "Focus should still be on child %p\n", child ); 3030 EnableWindow(hwnd, TRUE); 3031 3032 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3033 ShowWindow(hwnd, SW_SHOWMINIMIZED); 3034 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3035 todo_wine 3036 ok( GetFocus() != child, "Focus should not be on child %p\n", child ); 3037 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd ); 3038 ShowWindow(hwnd, SW_RESTORE); 3039 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3040 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); 3041 ShowWindow(hwnd, SW_SHOWMINIMIZED); 3042 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3043 ok( GetFocus() != child, "Focus should not be on child %p\n", child ); 3044 todo_wine 3045 ok( GetFocus() != hwnd, "Focus should not be on parent %p\n", hwnd ); 3046 old_wnd_proc = (WNDPROC)SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)set_focus_on_activate_proc); 3047 ShowWindow(hwnd, SW_RESTORE); 3048 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3049 todo_wine 3050 ok( GetFocus() == child, "Focus should be on child %p, not %p\n", child, GetFocus() ); 3051 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)old_wnd_proc); 3052 3053 SetFocus( hwnd ); 3054 SetParent( child, GetDesktopWindow()); 3055 SetParent( child2, child ); 3056 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3057 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); 3058 ret = SetFocus( child2 ); 3059 ok( ret == 0, "SetFocus %p should fail\n", child2); 3060 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3061 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); 3062 ret = SetFocus( child ); 3063 ok( ret == 0, "SetFocus %p should fail\n", child); 3064 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3065 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); 3066 SetWindowLongW( child, GWL_STYLE, WS_POPUP|WS_CHILD ); 3067 SetFocus( child2 ); 3068 ok( GetActiveWindow() == child, "child window %p should be active\n", child); 3069 ok( GetFocus() == child2, "Focus should be on child2 %p\n", child2 ); 3070 SetFocus( hwnd ); 3071 ok( GetActiveWindow() == hwnd, "parent window %p should be active\n", hwnd); 3072 ok( GetFocus() == hwnd, "Focus should be on parent %p\n", hwnd ); 3073 SetFocus( child ); 3074 ok( GetActiveWindow() == child, "child window %p should be active\n", child); 3075 ok( GetFocus() == child, "Focus should be on child %p\n", child ); 3076 3077 DestroyWindow( child2 ); 3078 DestroyWindow( child ); 3079 } 3080 3081 static void test_SetActiveWindow(HWND hwnd) 3082 { 3083 HWND hwnd2; 3084 3085 flush_events( TRUE ); 3086 ShowWindow(hwnd, SW_HIDE); 3087 SetFocus(0); 3088 SetActiveWindow(0); 3089 check_wnd_state(0, 0, 0, 0); 3090 3091 /*trace("testing SetActiveWindow %p\n", hwnd);*/ 3092 3093 ShowWindow(hwnd, SW_SHOW); 3094 check_wnd_state(hwnd, hwnd, hwnd, 0); 3095 3096 hwnd2 = SetActiveWindow(0); 3097 ok(hwnd2 == hwnd, "SetActiveWindow returned %p instead of %p\n", hwnd2, hwnd); 3098 if (!GetActiveWindow()) /* doesn't always work on vista */ 3099 { 3100 ros_skip_flaky 3101 check_wnd_state(0, 0, 0, 0); 3102 hwnd2 = SetActiveWindow(hwnd); 3103 ros_skip_flaky 3104 ok(hwnd2 == 0, "SetActiveWindow returned %p instead of 0\n", hwnd2); 3105 } 3106 check_wnd_state(hwnd, hwnd, hwnd, 0); 3107 3108 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); 3109 check_wnd_state(hwnd, hwnd, hwnd, 0); 3110 3111 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW); 3112 check_wnd_state(hwnd, hwnd, hwnd, 0); 3113 3114 ShowWindow(hwnd, SW_HIDE); 3115 check_wnd_state(0, 0, 0, 0); 3116 3117 /*trace("testing SetActiveWindow on an invisible window %p\n", hwnd);*/ 3118 SetActiveWindow(hwnd); 3119 check_wnd_state(hwnd, hwnd, hwnd, 0); 3120 3121 ShowWindow(hwnd, SW_SHOW); 3122 check_wnd_state(hwnd, hwnd, hwnd, 0); 3123 3124 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); 3125 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3126 3127 DestroyWindow(hwnd2); 3128 check_wnd_state(hwnd, hwnd, hwnd, 0); 3129 3130 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); 3131 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3132 3133 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); 3134 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3135 3136 DestroyWindow(hwnd2); 3137 check_wnd_state(hwnd, hwnd, hwnd, 0); 3138 } 3139 3140 struct create_window_thread_params 3141 { 3142 HWND window; 3143 HANDLE window_created; 3144 HANDLE test_finished; 3145 }; 3146 3147 static DWORD WINAPI create_window_thread(void *param) 3148 { 3149 struct create_window_thread_params *p = param; 3150 DWORD res; 3151 BOOL ret; 3152 3153 p->window = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0); 3154 3155 ret = SetEvent(p->window_created); 3156 ok(ret, "SetEvent failed, last error %#x.\n", GetLastError()); 3157 3158 res = WaitForSingleObject(p->test_finished, INFINITE); 3159 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError()); 3160 3161 DestroyWindow(p->window); 3162 return 0; 3163 } 3164 3165 static void test_SetForegroundWindow(HWND hwnd) 3166 { 3167 struct create_window_thread_params thread_params; 3168 HANDLE thread; 3169 DWORD res, tid; 3170 BOOL ret; 3171 HWND hwnd2; 3172 MSG msg; 3173 LONG style; 3174 3175 flush_events( TRUE ); 3176 ShowWindow(hwnd, SW_HIDE); 3177 SetFocus(0); 3178 SetActiveWindow(0); 3179 check_wnd_state(0, 0, 0, 0); 3180 3181 /*trace("testing SetForegroundWindow %p\n", hwnd);*/ 3182 3183 ShowWindow(hwnd, SW_SHOW); 3184 check_wnd_state(hwnd, hwnd, hwnd, 0); 3185 3186 hwnd2 = SetActiveWindow(0); 3187 ok(hwnd2 == hwnd, "SetActiveWindow(0) returned %p instead of %p\n", hwnd2, hwnd); 3188 if (GetActiveWindow() == hwnd) /* doesn't always work on vista */ 3189 check_wnd_state(hwnd, hwnd, hwnd, 0); 3190 else 3191 check_wnd_state(0, 0, 0, 0); 3192 3193 ret = SetForegroundWindow(hwnd); 3194 if (!ret) 3195 { 3196 skip( "SetForegroundWindow not working\n" ); 3197 return; 3198 } 3199 check_wnd_state(hwnd, hwnd, hwnd, 0); 3200 3201 SetLastError(0xdeadbeef); 3202 ret = SetForegroundWindow(0); 3203 ok(!ret, "SetForegroundWindow returned TRUE instead of FALSE\n"); 3204 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || 3205 broken(GetLastError() == 0xdeadbeef), /* win9x */ 3206 "got error %d expected ERROR_INVALID_WINDOW_HANDLE\n", GetLastError()); 3207 check_wnd_state(hwnd, hwnd, hwnd, 0); 3208 3209 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); 3210 check_wnd_state(hwnd, hwnd, hwnd, 0); 3211 3212 SetWindowPos(hwnd,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_SHOWWINDOW); 3213 check_wnd_state(hwnd, hwnd, hwnd, 0); 3214 3215 hwnd2 = GetForegroundWindow(); 3216 ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2); 3217 ret = SetForegroundWindow( GetDesktopWindow() ); 3218 ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError()); 3219 hwnd2 = GetForegroundWindow(); 3220 ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2); 3221 3222 ShowWindow(hwnd, SW_HIDE); 3223 check_wnd_state(0, 0, 0, 0); 3224 3225 /*trace("testing SetForegroundWindow on an invisible window %p\n", hwnd);*/ 3226 ret = SetForegroundWindow(hwnd); 3227 ok(ret || broken(!ret), /* win98 */ "SetForegroundWindow returned FALSE instead of TRUE\n"); 3228 check_wnd_state(hwnd, hwnd, hwnd, 0); 3229 3230 ShowWindow(hwnd, SW_SHOW); 3231 check_wnd_state(hwnd, hwnd, hwnd, 0); 3232 3233 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); 3234 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3235 3236 DestroyWindow(hwnd2); 3237 check_wnd_state(hwnd, hwnd, hwnd, 0); 3238 3239 hwnd2 = CreateWindowExA(0, "static", NULL, WS_POPUP|WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, 0, NULL); 3240 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3241 3242 SetWindowPos(hwnd2,0,0,0,0,0,SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_HIDEWINDOW); 3243 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3244 3245 DestroyWindow(hwnd2); 3246 check_wnd_state(hwnd, hwnd, hwnd, 0); 3247 3248 hwnd2 = CreateWindowA("static", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, 0, 0, 0, 0); 3249 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3250 3251 thread_params.window_created = CreateEventW(NULL, FALSE, FALSE, NULL); 3252 ok(!!thread_params.window_created, "CreateEvent failed, last error %#x.\n", GetLastError()); 3253 thread_params.test_finished = CreateEventW(NULL, FALSE, FALSE, NULL); 3254 ok(!!thread_params.test_finished, "CreateEvent failed, last error %#x.\n", GetLastError()); 3255 thread = CreateThread(NULL, 0, create_window_thread, &thread_params, 0, &tid); 3256 ok(!!thread, "Failed to create thread, last error %#x.\n", GetLastError()); 3257 res = WaitForSingleObject(thread_params.window_created, INFINITE); 3258 ok(res == WAIT_OBJECT_0, "Wait failed (%#x), last error %#x.\n", res, GetLastError()); 3259 check_wnd_state(hwnd2, thread_params.window, hwnd2, 0); 3260 3261 SetForegroundWindow(hwnd2); 3262 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3263 3264 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 3265 if (0) check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3266 todo_wine ok(GetActiveWindow() == hwnd2, "Expected active window %p, got %p.\n", hwnd2, GetActiveWindow()); 3267 todo_wine ok(GetFocus() == hwnd2, "Expected focus window %p, got %p.\n", hwnd2, GetFocus()); 3268 3269 SetForegroundWindow(hwnd); 3270 check_wnd_state(hwnd, hwnd, hwnd, 0); 3271 style = GetWindowLongA(hwnd2, GWL_STYLE) | WS_CHILD; 3272 ok(SetWindowLongA(hwnd2, GWL_STYLE, style), "SetWindowLong failed\n"); 3273 ok(SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n"); 3274 check_wnd_state(hwnd2, hwnd2, hwnd2, 0); 3275 3276 SetForegroundWindow(hwnd); 3277 check_wnd_state(hwnd, hwnd, hwnd, 0); 3278 ok(SetWindowLongA(hwnd2, GWL_STYLE, style & (~WS_POPUP)), "SetWindowLong failed\n"); 3279 ok(!SetForegroundWindow(hwnd2), "SetForegroundWindow failed\n"); 3280 check_wnd_state(hwnd, hwnd, hwnd, 0); 3281 3282 SetEvent(thread_params.test_finished); 3283 WaitForSingleObject(thread, INFINITE); 3284 CloseHandle(thread_params.test_finished); 3285 CloseHandle(thread_params.window_created); 3286 CloseHandle(thread); 3287 DestroyWindow(hwnd2); 3288 } 3289 3290 static WNDPROC old_button_proc; 3291 3292 static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPARAM lparam) 3293 { 3294 LRESULT ret; 3295 USHORT key_state; 3296 3297 key_state = GetKeyState(VK_LBUTTON); 3298 ok(!(key_state & 0x8000), "VK_LBUTTON should not be pressed, state %04x\n", key_state); 3299 3300 ret = CallWindowProcA(old_button_proc, button, msg, wparam, lparam); 3301 3302 if (msg == WM_LBUTTONDOWN) 3303 { 3304 HWND hwnd, capture; 3305 3306 check_wnd_state(button, button, button, button); 3307 3308 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 3309 assert(hwnd); 3310 trace("hwnd %p\n", hwnd); 3311 3312 check_wnd_state(button, button, button, button); 3313 3314 ShowWindow(hwnd, SW_SHOWNOACTIVATE); 3315 3316 check_wnd_state(button, button, button, button); 3317 3318 DestroyWindow(hwnd); 3319 3320 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 3321 assert(hwnd); 3322 trace("hwnd %p\n", hwnd); 3323 3324 check_wnd_state(button, button, button, button); 3325 3326 /* button wnd proc should release capture on WM_KILLFOCUS if it does 3327 * match internal button state. 3328 */ 3329 SendMessageA(button, WM_KILLFOCUS, 0, 0); 3330 check_wnd_state(button, button, button, 0); 3331 3332 ShowWindow(hwnd, SW_SHOW); 3333 check_wnd_state(hwnd, hwnd, hwnd, 0); 3334 3335 capture = SetCapture(hwnd); 3336 ok(capture == 0, "SetCapture() = %p\n", capture); 3337 3338 check_wnd_state(hwnd, hwnd, hwnd, hwnd); 3339 3340 DestroyWindow(hwnd); 3341 3342 check_wnd_state(button, 0, button, 0); 3343 } 3344 3345 return ret; 3346 } 3347 3348 static void test_capture_1(void) 3349 { 3350 HWND button, capture; 3351 3352 capture = GetCapture(); 3353 ok(capture == 0, "GetCapture() = %p\n", capture); 3354 3355 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 3356 assert(button); 3357 trace("button %p\n", button); 3358 3359 old_button_proc = (WNDPROC)SetWindowLongPtrA(button, GWLP_WNDPROC, (LONG_PTR)button_hook_proc); 3360 3361 SendMessageA(button, WM_LBUTTONDOWN, 0, 0); 3362 3363 capture = SetCapture(button); 3364 ok(capture == 0, "SetCapture() = %p\n", capture); 3365 check_wnd_state(button, 0, button, button); 3366 3367 DestroyWindow(button); 3368 /* old active window test depends on previously executed window 3369 * activation tests, and fails under NT4. 3370 check_wnd_state(oldActive, 0, oldFocus, 0);*/ 3371 } 3372 3373 static void test_capture_2(void) 3374 { 3375 HWND button, hwnd, capture, oldFocus, oldActive; 3376 3377 oldFocus = GetFocus(); 3378 oldActive = GetActiveWindow(); 3379 check_wnd_state(oldActive, 0, oldFocus, 0); 3380 3381 button = CreateWindowExA(0, "button", NULL, WS_POPUP | WS_VISIBLE, 0, 0, 10, 10, 0, 0, 0, NULL); 3382 assert(button); 3383 trace("button %p\n", button); 3384 3385 check_wnd_state(button, button, button, 0); 3386 3387 capture = SetCapture(button); 3388 ok(capture == 0, "SetCapture() = %p\n", capture); 3389 3390 check_wnd_state(button, button, button, button); 3391 3392 /* button wnd proc should ignore WM_KILLFOCUS if it doesn't match 3393 * internal button state. 3394 */ 3395 SendMessageA(button, WM_KILLFOCUS, 0, 0); 3396 check_wnd_state(button, button, button, button); 3397 3398 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 3399 assert(hwnd); 3400 trace("hwnd %p\n", hwnd); 3401 3402 check_wnd_state(button, button, button, button); 3403 3404 ShowWindow(hwnd, SW_SHOWNOACTIVATE); 3405 3406 check_wnd_state(button, button, button, button); 3407 3408 DestroyWindow(hwnd); 3409 3410 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 10, 10, 0, 0, 0, NULL); 3411 assert(hwnd); 3412 trace("hwnd %p\n", hwnd); 3413 3414 check_wnd_state(button, button, button, button); 3415 3416 ShowWindow(hwnd, SW_SHOW); 3417 3418 check_wnd_state(hwnd, hwnd, hwnd, button); 3419 3420 capture = SetCapture(hwnd); 3421 ok(capture == button, "SetCapture() = %p\n", capture); 3422 3423 check_wnd_state(hwnd, hwnd, hwnd, hwnd); 3424 3425 DestroyWindow(hwnd); 3426 check_wnd_state(button, button, button, 0); 3427 3428 DestroyWindow(button); 3429 check_wnd_state(oldActive, 0, oldFocus, 0); 3430 } 3431 3432 static void test_capture_3(HWND hwnd1, HWND hwnd2) 3433 { 3434 BOOL ret; 3435 3436 ShowWindow(hwnd1, SW_HIDE); 3437 ShowWindow(hwnd2, SW_HIDE); 3438 3439 ok(!IsWindowVisible(hwnd1), "%p should be invisible\n", hwnd1); 3440 ok(!IsWindowVisible(hwnd2), "%p should be invisible\n", hwnd2); 3441 3442 SetCapture(hwnd1); 3443 check_wnd_state(0, 0, 0, hwnd1); 3444 3445 SetCapture(hwnd2); 3446 check_wnd_state(0, 0, 0, hwnd2); 3447 3448 ShowWindow(hwnd1, SW_SHOW); 3449 check_wnd_state(hwnd1, hwnd1, hwnd1, hwnd2); 3450 3451 ret = ReleaseCapture(); 3452 ok (ret, "releasecapture did not return TRUE.\n"); 3453 ret = ReleaseCapture(); 3454 ok (ret, "releasecapture did not return TRUE after second try.\n"); 3455 } 3456 3457 static LRESULT CALLBACK test_capture_4_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 3458 { 3459 GUITHREADINFO gti; 3460 HWND cap_wnd, cap_wnd2, set_cap_wnd; 3461 BOOL status; 3462 switch (msg) 3463 { 3464 case WM_CAPTURECHANGED: 3465 3466 /* now try to release capture from menu. this should fail */ 3467 if (pGetGUIThreadInfo) 3468 { 3469 memset(>i, 0, sizeof(GUITHREADINFO)); 3470 gti.cbSize = sizeof(GUITHREADINFO); 3471 status = pGetGUIThreadInfo(GetCurrentThreadId(), >i); 3472 ok(status, "GetGUIThreadInfo() failed!\n"); 3473 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags); 3474 } 3475 cap_wnd = GetCapture(); 3476 3477 ok(cap_wnd == (HWND)lParam, "capture window %p does not match lparam %lx\n", cap_wnd, lParam); 3478 todo_wine ok(cap_wnd == hWnd, "capture window %p does not match hwnd %p\n", cap_wnd, hWnd); 3479 3480 /* check that re-setting the capture for the menu fails */ 3481 set_cap_wnd = SetCapture(cap_wnd); 3482 ok(!set_cap_wnd || broken(set_cap_wnd == cap_wnd), /* nt4 */ 3483 "SetCapture should have failed!\n"); 3484 if (set_cap_wnd) 3485 { 3486 DestroyWindow(hWnd); 3487 break; 3488 } 3489 3490 /* check that SetCapture fails for another window and that it does not touch the error code */ 3491 set_cap_wnd = SetCapture(hWnd); 3492 ok(!set_cap_wnd, "SetCapture should have failed!\n"); 3493 3494 /* check that ReleaseCapture fails and does not touch the error code */ 3495 status = ReleaseCapture(); 3496 ok(!status, "ReleaseCapture should have failed!\n"); 3497 3498 /* check that thread info did not change */ 3499 if (pGetGUIThreadInfo) 3500 { 3501 memset(>i, 0, sizeof(GUITHREADINFO)); 3502 gti.cbSize = sizeof(GUITHREADINFO); 3503 status = pGetGUIThreadInfo(GetCurrentThreadId(), >i); 3504 ok(status, "GetGUIThreadInfo() failed!\n"); 3505 ok(gti.flags & GUI_INMENUMODE, "Thread info incorrect (flags=%08X)!\n", gti.flags); 3506 } 3507 3508 /* verify that no capture change took place */ 3509 cap_wnd2 = GetCapture(); 3510 ok(cap_wnd2 == cap_wnd, "Capture changed!\n"); 3511 3512 /* we are done. kill the window */ 3513 DestroyWindow(hWnd); 3514 break; 3515 3516 default: 3517 return( DefWindowProcA( hWnd, msg, wParam, lParam ) ); 3518 } 3519 return 0; 3520 } 3521 3522 /* Test that no-one can mess around with the current capture while a menu is open */ 3523 static void test_capture_4(void) 3524 { 3525 BOOL ret; 3526 HMENU hmenu; 3527 HWND hwnd; 3528 WNDCLASSA wclass; 3529 HINSTANCE hInstance = GetModuleHandleA( NULL ); 3530 ATOM aclass; 3531 3532 if (!pGetGUIThreadInfo) 3533 { 3534 win_skip("GetGUIThreadInfo is not available\n"); 3535 return; 3536 } 3537 wclass.lpszClassName = "TestCapture4Class"; 3538 wclass.style = CS_HREDRAW | CS_VREDRAW; 3539 wclass.lpfnWndProc = test_capture_4_proc; 3540 wclass.hInstance = hInstance; 3541 wclass.hIcon = LoadIconA( 0, (LPCSTR)IDI_APPLICATION ); 3542 wclass.hCursor = LoadCursorA( 0, (LPCSTR)IDC_ARROW ); 3543 wclass.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 ); 3544 wclass.lpszMenuName = 0; 3545 wclass.cbClsExtra = 0; 3546 wclass.cbWndExtra = 0; 3547 aclass = RegisterClassA( &wclass ); 3548 ok( aclass, "RegisterClassA failed with error %d\n", GetLastError()); 3549 hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest", 3550 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 3551 400, 200, NULL, NULL, hInstance, NULL); 3552 ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); 3553 if (!hwnd) return; 3554 hmenu = CreatePopupMenu(); 3555 3556 ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest2"); 3557 ok( ret, "AppendMenuA has failed!\n"); 3558 3559 /* set main window to have initial capture */ 3560 SetCapture(hwnd); 3561 3562 if (is_win9x) 3563 { 3564 win_skip("TrackPopupMenu test crashes on Win9x/WinMe\n"); 3565 } 3566 else 3567 { 3568 /* create popup (it will self-destruct) */ 3569 ret = TrackPopupMenu(hmenu, TPM_RETURNCMD, 100, 100, 0, hwnd, NULL); 3570 ok( ret == 0, "TrackPopupMenu returned %d expected zero\n", ret); 3571 } 3572 3573 /* clean up */ 3574 DestroyMenu(hmenu); 3575 DestroyWindow(hwnd); 3576 } 3577 3578 /* PeekMessage wrapper that ignores the messages we don't care about */ 3579 static BOOL peek_message( MSG *msg ) 3580 { 3581 BOOL ret; 3582 do 3583 { 3584 ret = PeekMessageA(msg, 0, 0, 0, PM_REMOVE); 3585 } while (ret && ignore_message(msg->message)); 3586 return ret; 3587 } 3588 3589 static void test_keyboard_input(HWND hwnd) 3590 { 3591 MSG msg; 3592 BOOL ret; 3593 3594 flush_events( TRUE ); 3595 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE|SWP_SHOWWINDOW); 3596 UpdateWindow(hwnd); 3597 flush_events( TRUE ); 3598 3599 ok(GetActiveWindow() == hwnd, "wrong active window %p\n", GetActiveWindow()); 3600 3601 SetFocus(hwnd); 3602 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 3603 3604 flush_events( TRUE ); 3605 3606 PostMessageA(hwnd, WM_KEYDOWN, 0, 0); 3607 ret = peek_message(&msg); 3608 ok( ret, "no message available\n"); 3609 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3610 ret = peek_message(&msg); 3611 ok( !ret, "message %04x available\n", msg.message); 3612 3613 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 3614 3615 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0); 3616 ret = peek_message(&msg); 3617 ok(ret, "no message available\n"); 3618 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3619 ret = peek_message(&msg); 3620 ok( !ret, "message %04x available\n", msg.message); 3621 3622 ok(GetFocus() == hwnd, "wrong focus window %p\n", GetFocus()); 3623 3624 keybd_event(VK_SPACE, 0, 0, 0); 3625 if (!peek_message(&msg)) 3626 { 3627 skip( "keybd_event didn't work, skipping keyboard test\n" ); 3628 return; 3629 } 3630 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3631 ret = peek_message(&msg); 3632 ok( !ret, "message %04x available\n", msg.message); 3633 3634 SetFocus(0); 3635 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3636 3637 flush_events( TRUE ); 3638 3639 PostMessageA(hwnd, WM_KEYDOWN, 0, 0); 3640 ret = peek_message(&msg); 3641 ok(ret, "no message available\n"); 3642 ok(msg.hwnd == hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3643 ret = peek_message(&msg); 3644 ok( !ret, "message %04x available\n", msg.message); 3645 3646 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3647 3648 PostThreadMessageA(GetCurrentThreadId(), WM_KEYDOWN, 0, 0); 3649 ret = peek_message(&msg); 3650 ok(ret, "no message available\n"); 3651 ok(!msg.hwnd && msg.message == WM_KEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3652 ret = peek_message(&msg); 3653 ok( !ret, "message %04x available\n", msg.message); 3654 3655 ok(GetFocus() == 0, "wrong focus window %p\n", GetFocus()); 3656 3657 keybd_event(VK_SPACE, 0, 0, 0); 3658 ret = peek_message(&msg); 3659 ok(ret, "no message available\n"); 3660 ok(msg.hwnd == hwnd && msg.message == WM_SYSKEYDOWN, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3661 ret = peek_message(&msg); 3662 ok( !ret, "message %04x available\n", msg.message); 3663 } 3664 3665 static BOOL wait_for_message( MSG *msg ) 3666 { 3667 BOOL ret; 3668 3669 for (;;) 3670 { 3671 ret = peek_message(msg); 3672 if (ret) 3673 { 3674 if (msg->message == WM_PAINT) DispatchMessageA(msg); 3675 else break; 3676 } 3677 else if (MsgWaitForMultipleObjects( 0, NULL, FALSE, 100, QS_ALLINPUT ) == WAIT_TIMEOUT) break; 3678 } 3679 if (!ret) msg->message = 0; 3680 return ret; 3681 } 3682 3683 static void test_mouse_input(HWND hwnd) 3684 { 3685 RECT rc; 3686 POINT pt; 3687 int x, y; 3688 HWND popup; 3689 MSG msg; 3690 BOOL ret; 3691 LRESULT res; 3692 3693 ShowWindow(hwnd, SW_SHOWNORMAL); 3694 UpdateWindow(hwnd); 3695 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 3696 3697 GetWindowRect(hwnd, &rc); 3698 trace("main window %p: %s\n", hwnd, wine_dbgstr_rect(&rc)); 3699 3700 popup = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP, 3701 rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, 3702 hwnd, 0, 0, NULL); 3703 assert(popup != 0); 3704 ShowWindow(popup, SW_SHOW); 3705 UpdateWindow(popup); 3706 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 3707 3708 GetWindowRect(popup, &rc); 3709 trace("popup window %p: %s\n", popup, wine_dbgstr_rect(&rc)); 3710 3711 x = rc.left + (rc.right - rc.left) / 2; 3712 y = rc.top + (rc.bottom - rc.top) / 2; 3713 trace("setting cursor to (%d,%d)\n", x, y); 3714 3715 SetCursorPos(x, y); 3716 GetCursorPos(&pt); 3717 if (x != pt.x || y != pt.y) 3718 { 3719 skip( "failed to set mouse position, skipping mouse input tests\n" ); 3720 goto done; 3721 } 3722 3723 flush_events( TRUE ); 3724 3725 /* Check that setting the same position may generate WM_MOUSEMOVE */ 3726 SetCursorPos(x, y); 3727 msg.message = 0; 3728 ret = peek_message(&msg); 3729 if (ret) 3730 { 3731 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", 3732 msg.hwnd, msg.message); 3733 ok(msg.pt.x == x && msg.pt.y == y, "wrong message coords (%d,%d)/(%d,%d)\n", 3734 x, y, msg.pt.x, msg.pt.y); 3735 } 3736 3737 /* force the system to update its internal queue mouse position, 3738 * otherwise it won't generate relative mouse movements below. 3739 */ 3740 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0); 3741 flush_events( TRUE ); 3742 3743 msg.message = 0; 3744 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0); 3745 flush_events( FALSE ); 3746 /* FIXME: SetCursorPos in Wine generates additional WM_MOUSEMOVE message */ 3747 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 3748 { 3749 if (ignore_message(msg.message)) continue; 3750 ok(msg.hwnd == popup && msg.message == WM_MOUSEMOVE, 3751 "hwnd %p message %04x\n", msg.hwnd, msg.message); 3752 DispatchMessageA(&msg); 3753 } 3754 ret = peek_message(&msg); 3755 ok( !ret, "message %04x available\n", msg.message); 3756 3757 mouse_event(MOUSEEVENTF_MOVE, -1, -1, 0, 0); 3758 ShowWindow(popup, SW_HIDE); 3759 ret = wait_for_message( &msg ); 3760 if (ret) 3761 ok(msg.hwnd == hwnd && msg.message == WM_MOUSEMOVE, "hwnd %p message %04x\n", msg.hwnd, msg.message); 3762 flush_events( TRUE ); 3763 3764 mouse_event(MOUSEEVENTF_MOVE, 1, 1, 0, 0); 3765 ShowWindow(hwnd, SW_HIDE); 3766 ret = wait_for_message( &msg ); 3767 ok( !ret, "message %04x available\n", msg.message); 3768 flush_events( TRUE ); 3769 3770 /* test mouse clicks */ 3771 3772 ShowWindow(hwnd, SW_SHOW); 3773 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 3774 flush_events( TRUE ); 3775 ShowWindow(popup, SW_SHOW); 3776 SetWindowPos( popup, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE ); 3777 flush_events( TRUE ); 3778 3779 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 3780 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 3781 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 3782 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 3783 3784 ret = wait_for_message( &msg ); 3785 if (!ret) 3786 { 3787 skip( "simulating mouse click doesn't work, skipping mouse button tests\n" ); 3788 goto done; 3789 } 3790 if (msg.message == WM_MOUSEMOVE) /* win2k has an extra WM_MOUSEMOVE here */ 3791 { 3792 ret = wait_for_message( &msg ); 3793 ok(ret, "no message available\n"); 3794 } 3795 3796 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n", 3797 msg.hwnd, popup, msg.message); 3798 3799 ret = wait_for_message( &msg ); 3800 ok(ret, "no message available\n"); 3801 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n", 3802 msg.hwnd, popup, msg.message); 3803 3804 ret = wait_for_message( &msg ); 3805 ok(ret, "no message available\n"); 3806 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDBLCLK, "hwnd %p/%p message %04x\n", 3807 msg.hwnd, popup, msg.message); 3808 3809 ret = wait_for_message( &msg ); 3810 ok(ret, "no message available\n"); 3811 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n", 3812 msg.hwnd, popup, msg.message); 3813 3814 ret = peek_message(&msg); 3815 ok(!ret, "message %04x available\n", msg.message); 3816 3817 ShowWindow(popup, SW_HIDE); 3818 flush_events( TRUE ); 3819 3820 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 3821 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 3822 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 3823 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 3824 3825 ret = wait_for_message( &msg ); 3826 ok(ret, "no message available\n"); 3827 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n", 3828 msg.hwnd, hwnd, msg.message); 3829 ret = wait_for_message( &msg ); 3830 ok(ret, "no message available\n"); 3831 ok(msg.hwnd == hwnd && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n", 3832 msg.hwnd, hwnd, msg.message); 3833 3834 test_lbuttondown_flag = TRUE; 3835 SendMessageA(hwnd, WM_COMMAND, (WPARAM)popup, 0); 3836 test_lbuttondown_flag = FALSE; 3837 3838 ret = wait_for_message( &msg ); 3839 ok(ret, "no message available\n"); 3840 ok(msg.hwnd == popup && msg.message == WM_LBUTTONDOWN, "hwnd %p/%p message %04x\n", 3841 msg.hwnd, popup, msg.message); 3842 ok(peek_message(&msg), "no message available\n"); 3843 ok(msg.hwnd == popup && msg.message == WM_LBUTTONUP, "hwnd %p/%p message %04x\n", 3844 msg.hwnd, popup, msg.message); 3845 ok(peek_message(&msg), "no message available\n"); 3846 3847 /* Test WM_MOUSEACTIVATE */ 3848 #define TEST_MOUSEACTIVATE(A,B) \ 3849 res = SendMessageA(hwnd, WM_MOUSEACTIVATE, (WPARAM)hwnd, (LPARAM)MAKELRESULT(A,0)); \ 3850 ok(res == B, "WM_MOUSEACTIVATE for %s returned %ld\n", #A, res); 3851 3852 TEST_MOUSEACTIVATE(HTERROR,MA_ACTIVATE); 3853 TEST_MOUSEACTIVATE(HTTRANSPARENT,MA_ACTIVATE); 3854 TEST_MOUSEACTIVATE(HTNOWHERE,MA_ACTIVATE); 3855 TEST_MOUSEACTIVATE(HTCLIENT,MA_ACTIVATE); 3856 TEST_MOUSEACTIVATE(HTCAPTION,MA_ACTIVATE); 3857 TEST_MOUSEACTIVATE(HTSYSMENU,MA_ACTIVATE); 3858 TEST_MOUSEACTIVATE(HTSIZE,MA_ACTIVATE); 3859 TEST_MOUSEACTIVATE(HTMENU,MA_ACTIVATE); 3860 TEST_MOUSEACTIVATE(HTHSCROLL,MA_ACTIVATE); 3861 TEST_MOUSEACTIVATE(HTVSCROLL,MA_ACTIVATE); 3862 TEST_MOUSEACTIVATE(HTMINBUTTON,MA_ACTIVATE); 3863 TEST_MOUSEACTIVATE(HTMAXBUTTON,MA_ACTIVATE); 3864 TEST_MOUSEACTIVATE(HTLEFT,MA_ACTIVATE); 3865 TEST_MOUSEACTIVATE(HTRIGHT,MA_ACTIVATE); 3866 TEST_MOUSEACTIVATE(HTTOP,MA_ACTIVATE); 3867 TEST_MOUSEACTIVATE(HTTOPLEFT,MA_ACTIVATE); 3868 TEST_MOUSEACTIVATE(HTTOPRIGHT,MA_ACTIVATE); 3869 TEST_MOUSEACTIVATE(HTBOTTOM,MA_ACTIVATE); 3870 TEST_MOUSEACTIVATE(HTBOTTOMLEFT,MA_ACTIVATE); 3871 TEST_MOUSEACTIVATE(HTBOTTOMRIGHT,MA_ACTIVATE); 3872 TEST_MOUSEACTIVATE(HTBORDER,MA_ACTIVATE); 3873 TEST_MOUSEACTIVATE(HTOBJECT,MA_ACTIVATE); 3874 TEST_MOUSEACTIVATE(HTCLOSE,MA_ACTIVATE); 3875 TEST_MOUSEACTIVATE(HTHELP,MA_ACTIVATE); 3876 3877 done: 3878 /* Clear any messages left behind by WM_MOUSEACTIVATE tests */ 3879 flush_events( TRUE ); 3880 3881 DestroyWindow(popup); 3882 } 3883 3884 static void test_validatergn(HWND hwnd) 3885 { 3886 HWND child; 3887 RECT rc, rc2; 3888 HRGN rgn; 3889 int ret; 3890 child = CreateWindowExA(0, "static", NULL, WS_CHILD| WS_VISIBLE, 10, 10, 10, 10, hwnd, 0, 0, NULL); 3891 ShowWindow(hwnd, SW_SHOW); 3892 UpdateWindow( hwnd); 3893 /* test that ValidateRect validates children*/ 3894 InvalidateRect( child, NULL, 1); 3895 GetWindowRect( child, &rc); 3896 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2); 3897 ret = GetUpdateRect( child, &rc2, 0); 3898 ok( ret == 1, "Expected GetUpdateRect to return non-zero, got %d\n", ret); 3899 ok( rc2.right > rc2.left && rc2.bottom > rc2.top, 3900 "Update rectangle is empty!\n"); 3901 ValidateRect( hwnd, &rc); 3902 ret = GetUpdateRect( child, &rc2, 0); 3903 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret); 3904 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0, 3905 "Update rectangle %s is not empty!\n", wine_dbgstr_rect(&rc2)); 3906 3907 /* now test ValidateRgn */ 3908 InvalidateRect( child, NULL, 1); 3909 GetWindowRect( child, &rc); 3910 MapWindowPoints( NULL, hwnd, (POINT*) &rc, 2); 3911 rgn = CreateRectRgnIndirect( &rc); 3912 ValidateRgn( hwnd, rgn); 3913 ret = GetUpdateRect( child, &rc2, 0); 3914 ok( !ret, "Expected GetUpdateRect to return zero, got %d\n", ret); 3915 ok( rc2.left == 0 && rc2.top == 0 && rc2.right == 0 && rc2.bottom == 0, 3916 "Update rectangle %s is not empty!\n", wine_dbgstr_rect(&rc2)); 3917 3918 DeleteObject( rgn); 3919 DestroyWindow( child ); 3920 } 3921 3922 static void nccalchelper(HWND hwnd, INT x, INT y, RECT *prc) 3923 { 3924 RECT rc; 3925 MoveWindow( hwnd, 0, 0, x, y, 0); 3926 GetWindowRect( hwnd, prc); 3927 rc = *prc; 3928 DefWindowProcA(hwnd, WM_NCCALCSIZE, 0, (LPARAM)prc); 3929 trace("window rect is %s, nccalc rect is %s\n", wine_dbgstr_rect(&rc), wine_dbgstr_rect(prc)); 3930 } 3931 3932 static void test_nccalcscroll(HWND parent) 3933 { 3934 RECT rc1; 3935 INT sbheight = GetSystemMetrics( SM_CYHSCROLL); 3936 INT sbwidth = GetSystemMetrics( SM_CXVSCROLL); 3937 HWND hwnd = CreateWindowExA(0, "static", NULL, 3938 WS_CHILD| WS_VISIBLE | WS_VSCROLL | WS_HSCROLL , 3939 10, 10, 200, 200, parent, 0, 0, NULL); 3940 ShowWindow( parent, SW_SHOW); 3941 UpdateWindow( parent); 3942 3943 /* test window too low for a horizontal scroll bar */ 3944 nccalchelper( hwnd, 100, sbheight, &rc1); 3945 ok( rc1.bottom - rc1.top == sbheight, "Height should be %d size is %s\n", sbheight, 3946 wine_dbgstr_rect(&rc1)); 3947 3948 /* test window just high enough for a horizontal scroll bar */ 3949 nccalchelper( hwnd, 100, sbheight + 1, &rc1); 3950 ok( rc1.bottom - rc1.top == 1, "Height should be 1 size is %s\n", wine_dbgstr_rect(&rc1)); 3951 3952 /* test window too narrow for a vertical scroll bar */ 3953 nccalchelper( hwnd, sbwidth - 1, 100, &rc1); 3954 ok( rc1.right - rc1.left == sbwidth - 1 , "Width should be %d size is %s\n", sbwidth - 1, 3955 wine_dbgstr_rect(&rc1)); 3956 3957 /* test window just wide enough for a vertical scroll bar */ 3958 nccalchelper( hwnd, sbwidth, 100, &rc1); 3959 ok( rc1.right - rc1.left == 0, "Width should be 0 size is %s\n", wine_dbgstr_rect(&rc1)); 3960 3961 /* same test, but with client edge: not enough width */ 3962 SetWindowLongA( hwnd, GWL_EXSTYLE, WS_EX_CLIENTEDGE | GetWindowLongA( hwnd, GWL_EXSTYLE)); 3963 nccalchelper( hwnd, sbwidth, 100, &rc1); 3964 ok( rc1.right - rc1.left == sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), 3965 "Width should be %d size is %s\n", sbwidth - 2 * GetSystemMetrics(SM_CXEDGE), 3966 wine_dbgstr_rect(&rc1)); 3967 3968 DestroyWindow( hwnd); 3969 } 3970 3971 static void test_SetParent(void) 3972 { 3973 HWND desktop = GetDesktopWindow(); 3974 HMENU hMenu; 3975 HWND ret, parent, child1, child2, child3, child4, sibling, popup; 3976 BOOL bret; 3977 3978 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 3979 100, 100, 200, 200, 0, 0, 0, NULL); 3980 assert(parent != 0); 3981 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD, 3982 0, 0, 50, 50, parent, 0, 0, NULL); 3983 assert(child1 != 0); 3984 child2 = CreateWindowExA(0, "static", NULL, WS_POPUP, 3985 0, 0, 50, 50, child1, 0, 0, NULL); 3986 assert(child2 != 0); 3987 child3 = CreateWindowExA(0, "static", NULL, WS_CHILD, 3988 0, 0, 50, 50, child2, 0, 0, NULL); 3989 assert(child3 != 0); 3990 child4 = CreateWindowExA(0, "static", NULL, WS_POPUP, 3991 0, 0, 50, 50, child3, 0, 0, NULL); 3992 assert(child4 != 0); 3993 3994 trace("parent %p, child1 %p, child2 %p, child3 %p, child4 %p\n", 3995 parent, child1, child2, child3, child4); 3996 3997 check_parents(parent, desktop, 0, 0, 0, parent, parent); 3998 check_parents(child1, parent, parent, parent, 0, parent, parent); 3999 check_parents(child2, desktop, parent, parent, parent, child2, parent); 4000 check_parents(child3, child2, child2, child2, 0, child2, parent); 4001 check_parents(child4, desktop, child2, child2, child2, child4, parent); 4002 4003 ok(!IsChild(desktop, parent), "wrong parent/child %p/%p\n", desktop, parent); 4004 ok(!IsChild(desktop, child1), "wrong parent/child %p/%p\n", desktop, child1); 4005 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2); 4006 ok(!IsChild(desktop, child3), "wrong parent/child %p/%p\n", desktop, child3); 4007 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4); 4008 4009 ok(IsChild(parent, child1), "wrong parent/child %p/%p\n", parent, child1); 4010 ok(!IsChild(desktop, child2), "wrong parent/child %p/%p\n", desktop, child2); 4011 ok(!IsChild(parent, child2), "wrong parent/child %p/%p\n", parent, child2); 4012 ok(!IsChild(child1, child2), "wrong parent/child %p/%p\n", child1, child2); 4013 ok(!IsChild(parent, child3), "wrong parent/child %p/%p\n", parent, child3); 4014 ok(IsChild(child2, child3), "wrong parent/child %p/%p\n", child2, child3); 4015 ok(!IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); 4016 ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4); 4017 ok(!IsChild(desktop, child4), "wrong parent/child %p/%p\n", desktop, child4); 4018 4019 if (!is_win9x) /* Win9x doesn't survive this test */ 4020 { 4021 ok(!SetParent(parent, child1), "SetParent should fail\n"); 4022 ok(!SetParent(child2, child3), "SetParent should fail\n"); 4023 ok(SetParent(child1, parent) != 0, "SetParent should not fail\n"); 4024 ret = SetParent(parent, child2); 4025 todo_wine ok( !ret || broken( ret != 0 ), "SetParent should fail\n"); 4026 if (ret) /* nt4, win2k */ 4027 { 4028 ret = SetParent(parent, child3); 4029 ok(ret != 0, "SetParent should not fail\n"); 4030 ret = SetParent(child2, parent); 4031 ok(!ret, "SetParent should fail\n"); 4032 ret = SetParent(parent, child4); 4033 ok(ret != 0, "SetParent should not fail\n"); 4034 check_parents(parent, child4, child4, 0, 0, child4, parent); 4035 check_parents(child1, parent, parent, parent, 0, child4, parent); 4036 check_parents(child2, desktop, parent, parent, parent, child2, parent); 4037 check_parents(child3, child2, child2, child2, 0, child2, parent); 4038 check_parents(child4, desktop, child2, child2, child2, child4, parent); 4039 } 4040 else 4041 { 4042 ret = SetParent(parent, child3); 4043 ok(ret != 0, "SetParent should not fail\n"); 4044 ret = SetParent(child2, parent); 4045 ok(!ret, "SetParent should fail\n"); 4046 ret = SetParent(parent, child4); 4047 ok(!ret, "SetParent should fail\n"); 4048 check_parents(parent, child3, child3, 0, 0, child2, parent); 4049 check_parents(child1, parent, parent, parent, 0, child2, parent); 4050 check_parents(child2, desktop, parent, parent, parent, child2, parent); 4051 check_parents(child3, child2, child2, child2, 0, child2, parent); 4052 check_parents(child4, desktop, child2, child2, child2, child4, parent); 4053 } 4054 } 4055 else 4056 skip("Win9x/WinMe crash\n"); 4057 4058 hMenu = CreateMenu(); 4059 sibling = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 4060 100, 100, 200, 200, 0, hMenu, 0, NULL); 4061 assert(sibling != 0); 4062 4063 ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n"); 4064 ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n"); 4065 4066 ok(SetParent(parent, desktop) != 0, "SetParent should not fail\n"); 4067 ok(SetParent(child4, child3) != 0, "SetParent should not fail\n"); 4068 ok(SetParent(child3, child2) != 0, "SetParent should not fail\n"); 4069 ok(SetParent(child2, child1) != 0, "SetParent should not fail\n"); 4070 ok(!IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4); 4071 SetWindowLongW(child4, GWL_STYLE, WS_CHILD); 4072 ok(IsChild(child3, child4), "wrong parent/child %p/%p\n", child3, child4); 4073 ok(IsChild(child2, child4), "wrong parent/child %p/%p\n", child2, child4); 4074 ok(!IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4); 4075 SetWindowLongW(child2, GWL_STYLE, WS_CHILD); 4076 ok(IsChild(child1, child4), "wrong parent/child %p/%p\n", child1, child4); 4077 ok(IsChild(parent, child4), "wrong parent/child %p/%p\n", parent, child4); 4078 4079 ok(DestroyWindow(parent), "DestroyWindow() failed\n"); 4080 4081 ok(!IsWindow(parent), "parent still exists\n"); 4082 ok(!IsWindow(sibling), "sibling still exists\n"); 4083 ok(!IsWindow(child1), "child1 still exists\n"); 4084 ok(!IsWindow(child2), "child2 still exists\n"); 4085 ok(!IsWindow(child3), "child3 still exists\n"); 4086 ok(!IsWindow(child4), "child4 still exists\n"); 4087 4088 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 4089 100, 100, 200, 200, 0, 0, 0, NULL); 4090 assert(parent != 0); 4091 child1 = CreateWindowExA(0, "static", NULL, WS_CHILD, 4092 0, 0, 50, 50, parent, 0, 0, NULL); 4093 assert(child1 != 0); 4094 popup = CreateWindowExA(0, "static", NULL, WS_POPUP, 4095 0, 0, 50, 50, 0, 0, 0, NULL); 4096 assert(popup != 0); 4097 4098 trace("parent %p, child %p, popup %p\n", parent, child1, popup); 4099 4100 check_parents(parent, desktop, 0, 0, 0, parent, parent); 4101 check_parents(child1, parent, parent, parent, 0, parent, parent); 4102 check_parents(popup, desktop, 0, 0, 0, popup, popup); 4103 4104 SetActiveWindow(parent); 4105 SetFocus(parent); 4106 check_active_state(parent, 0, parent); 4107 4108 ret = SetParent(popup, child1); 4109 ok(ret == desktop, "expected %p, got %p\n", desktop, ret); 4110 check_parents(popup, child1, child1, 0, 0, parent, popup); 4111 check_active_state(popup, 0, popup); 4112 4113 SetActiveWindow(parent); 4114 SetFocus(popup); 4115 check_active_state(popup, 0, popup); 4116 4117 EnableWindow(child1, FALSE); 4118 check_active_state(popup, 0, popup); 4119 SetFocus(parent); 4120 check_active_state(parent, 0, parent); 4121 SetFocus(popup); 4122 check_active_state(popup, 0, popup); 4123 EnableWindow(child1, TRUE); 4124 4125 ShowWindow(child1, SW_MINIMIZE); 4126 SetFocus(parent); 4127 check_active_state(parent, 0, parent); 4128 SetFocus(popup); 4129 check_active_state(popup, 0, popup); 4130 ShowWindow(child1, SW_HIDE); 4131 4132 SetActiveWindow(parent); 4133 SetFocus(parent); 4134 check_active_state(parent, 0, parent); 4135 4136 bret = SetForegroundWindow(popup); 4137 ok(bret, "SetForegroundWindow() failed\n"); 4138 check_active_state(popup, popup, popup); 4139 4140 ShowWindow(parent, SW_SHOW); 4141 SetActiveWindow(popup); 4142 ok(DestroyWindow(popup), "DestroyWindow() failed\n"); 4143 check_active_state(parent, parent, parent); 4144 4145 ok(DestroyWindow(parent), "DestroyWindow() failed\n"); 4146 4147 ok(!IsWindow(parent), "parent still exists\n"); 4148 ok(!IsWindow(child1), "child1 still exists\n"); 4149 ok(!IsWindow(popup), "popup still exists\n"); 4150 } 4151 4152 static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4153 { 4154 LPCREATESTRUCTA lpcs; 4155 LPSTYLESTRUCT lpss; 4156 4157 switch (msg) 4158 { 4159 case WM_NCCREATE: 4160 case WM_CREATE: 4161 lpcs = (LPCREATESTRUCTA)lparam; 4162 lpss = lpcs->lpCreateParams; 4163 if (lpss) 4164 { 4165 if ((lpcs->dwExStyle & WS_EX_DLGMODALFRAME) || 4166 ((!(lpcs->dwExStyle & WS_EX_STATICEDGE)) && 4167 (lpcs->style & (WS_DLGFRAME | WS_THICKFRAME)))) 4168 ok(lpcs->dwExStyle & WS_EX_WINDOWEDGE, "Window should have WS_EX_WINDOWEDGE style\n"); 4169 else 4170 ok(!(lpcs->dwExStyle & WS_EX_WINDOWEDGE), "Window shouldn't have WS_EX_WINDOWEDGE style\n"); 4171 4172 ok((lpss->styleOld & ~WS_EX_WINDOWEDGE) == (lpcs->dwExStyle & ~WS_EX_WINDOWEDGE), 4173 "Ex style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n", 4174 lpss->styleOld, lpcs->dwExStyle); 4175 4176 ok(lpss->styleNew == lpcs->style, 4177 "Style (0x%08x) should match what the caller passed to CreateWindowEx (0x%08x)\n", 4178 lpss->styleNew, lpcs->style); 4179 } 4180 break; 4181 } 4182 return DefWindowProcA(hwnd, msg, wparam, lparam); 4183 } 4184 4185 static ATOM atomStyleCheckClass; 4186 4187 static void register_style_check_class(void) 4188 { 4189 WNDCLASSA wc = 4190 { 4191 0, 4192 StyleCheckProc, 4193 0, 4194 0, 4195 GetModuleHandleA(NULL), 4196 NULL, 4197 LoadCursorA(0, (LPCSTR)IDC_ARROW), 4198 (HBRUSH)(COLOR_BTNFACE+1), 4199 NULL, 4200 "WineStyleCheck", 4201 }; 4202 4203 atomStyleCheckClass = RegisterClassA(&wc); 4204 assert(atomStyleCheckClass); 4205 } 4206 4207 static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyleOut, DWORD dwExStyleOut) 4208 { 4209 DWORD dwActualStyle; 4210 DWORD dwActualExStyle; 4211 STYLESTRUCT ss; 4212 HWND hwnd; 4213 HWND hwndParent = NULL; 4214 4215 ss.styleNew = dwStyleIn; 4216 ss.styleOld = dwExStyleIn; 4217 4218 if (dwStyleIn & WS_CHILD) 4219 { 4220 hwndParent = CreateWindowExA(0, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL, 4221 WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL); 4222 } 4223 4224 hwnd = CreateWindowExA(dwExStyleIn, (LPCSTR)MAKEINTATOM(atomStyleCheckClass), NULL, 4225 dwStyleIn, 0, 0, 0, 0, hwndParent, NULL, NULL, &ss); 4226 assert(hwnd); 4227 4228 flush_events( TRUE ); 4229 4230 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE); 4231 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4232 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle); 4233 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle); 4234 4235 /* try setting the styles explicitly */ 4236 SetWindowLongA( hwnd, GWL_EXSTYLE, dwExStyleIn ); 4237 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE); 4238 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4239 /* WS_EX_WINDOWEDGE can't always be changed */ 4240 if (dwExStyleIn & WS_EX_DLGMODALFRAME) 4241 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE; 4242 else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE)) 4243 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE; 4244 else 4245 dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE; 4246 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle); 4247 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle); 4248 4249 SetWindowLongA( hwnd, GWL_STYLE, dwStyleIn ); 4250 dwActualStyle = GetWindowLongA(hwnd, GWL_STYLE); 4251 dwActualExStyle = GetWindowLongA(hwnd, GWL_EXSTYLE); 4252 /* WS_CLIPSIBLINGS can't be reset on top-level windows */ 4253 if ((dwStyleIn & (WS_CHILD|WS_POPUP)) == WS_CHILD) dwStyleOut = dwStyleIn; 4254 else dwStyleOut = dwStyleIn | WS_CLIPSIBLINGS; 4255 /* WS_EX_WINDOWEDGE can't always be changed */ 4256 if (dwExStyleIn & WS_EX_DLGMODALFRAME) 4257 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE; 4258 else if ((dwActualStyle & (WS_DLGFRAME | WS_THICKFRAME)) && !(dwExStyleIn & WS_EX_STATICEDGE)) 4259 dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE; 4260 else 4261 dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE; 4262 ok(dwActualStyle == dwStyleOut, "expected style %#x, got %#x\n", dwStyleOut, dwActualStyle); 4263 /* FIXME: Remove the condition below once Wine is fixed */ 4264 todo_wine_if (dwActualExStyle != dwExStyleOut) 4265 ok(dwActualExStyle == dwExStyleOut, "expected ex_style %#x, got %#x\n", dwExStyleOut, dwActualExStyle); 4266 4267 DestroyWindow(hwnd); 4268 if (hwndParent) DestroyWindow(hwndParent); 4269 } 4270 4271 /* tests what window styles the window manager automatically adds */ 4272 static void test_window_styles(void) 4273 { 4274 register_style_check_class(); 4275 4276 check_window_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE); 4277 check_window_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE); 4278 check_window_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE); 4279 check_window_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE); 4280 check_window_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE); 4281 check_window_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE); 4282 check_window_style(WS_CHILD, 0, WS_CHILD, 0); 4283 check_window_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE); 4284 check_window_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE); 4285 check_window_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE); 4286 check_window_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE); 4287 check_window_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE); 4288 check_window_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE); 4289 check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0); 4290 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); 4291 check_window_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); 4292 check_window_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0); 4293 check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4294 check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4295 check_window_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4296 check_window_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4297 check_window_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW); 4298 check_window_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0); 4299 check_window_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0); 4300 check_window_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW); 4301 check_window_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, 0); 4302 check_window_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, 0); 4303 check_window_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4304 check_window_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4305 check_window_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4306 check_window_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4307 check_window_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE); 4308 check_window_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE); 4309 4310 if (pGetLayeredWindowAttributes) 4311 { 4312 check_window_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE); 4313 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE); 4314 check_window_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, 4315 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE); 4316 } 4317 } 4318 4319 static HWND root_dialog(HWND hwnd) 4320 { 4321 while ((GetWindowLongA(hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) && 4322 (GetWindowLongA(hwnd, GWL_STYLE) & (WS_CHILD|WS_POPUP)) == WS_CHILD) 4323 { 4324 HWND parent = GetParent(hwnd); 4325 4326 /* simple detector for a window being a dialog */ 4327 if (!DefDlgProcA(parent, DM_GETDEFID, 0, 0)) 4328 break; 4329 4330 hwnd = parent; 4331 4332 if (!(GetWindowLongA(hwnd, GWL_STYLE) & DS_CONTROL)) 4333 break; 4334 } 4335 4336 return hwnd; 4337 } 4338 4339 static INT_PTR WINAPI empty_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4340 { 4341 return 0; 4342 } 4343 4344 static LRESULT expected_id; 4345 4346 static INT_PTR WINAPI empty_dlg_proc3(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4347 { 4348 if (msg == WM_INITDIALOG) 4349 { 4350 HWND parent = GetParent(hwnd); 4351 LRESULT id, ret; 4352 4353 id = DefDlgProcA(parent, DM_GETDEFID, 0, 0); 4354 if (!id || root_dialog(hwnd) == hwnd) 4355 parent = 0; 4356 4357 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4358 if (!parent) 4359 ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); 4360 else 4361 ok(id == expected_id, "expected %08lx, got %08lx\n", expected_id, id); 4362 4363 ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x3333, 0); 4364 ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); 4365 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4366 ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id); 4367 4368 if (parent) 4369 { 4370 id = DefDlgProcA(parent, DM_GETDEFID, 0, 0); 4371 ok(id == MAKELONG(0x3333,DC_HASDEFID), "expected (0x3333,DC_HASDEFID), got %08lx\n", id); 4372 4373 expected_id = MAKELONG(0x3333,DC_HASDEFID); 4374 } 4375 4376 EndDialog(hwnd, 0); 4377 } 4378 4379 return 0; 4380 } 4381 4382 struct dialog_param 4383 { 4384 HWND parent, grand_parent; 4385 DLGTEMPLATE *dlg_data; 4386 }; 4387 4388 static INT_PTR WINAPI empty_dlg_proc2(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4389 { 4390 if (msg == WM_INITDIALOG) 4391 { 4392 DWORD style = GetWindowLongA(hwnd, GWL_STYLE); 4393 struct dialog_param *param = (struct dialog_param *)lparam; 4394 BOOL parent_is_child; 4395 HWND disabled_hwnd; 4396 LRESULT id, ret; 4397 4398 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4399 ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); 4400 ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x2222, 0); 4401 ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); 4402 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4403 ok(id == MAKELONG(0x2222,DC_HASDEFID), "expected (0x2222,DC_HASDEFID), got %08lx\n", id); 4404 4405 expected_id = MAKELONG(0x2222,DC_HASDEFID); 4406 4407 parent_is_child = (GetWindowLongA(param->parent, GWL_STYLE) & (WS_POPUP | WS_CHILD)) == WS_CHILD; 4408 4409 ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd); 4410 if (parent_is_child) 4411 { 4412 ok(IsWindowEnabled(param->parent), "wrong state for %08x\n", style); 4413 disabled_hwnd = param->grand_parent; 4414 } 4415 else 4416 { 4417 ok(!IsWindowEnabled(param->parent), "wrong state for %08x\n", style); 4418 disabled_hwnd = param->parent; 4419 } 4420 4421 if (param->grand_parent) 4422 { 4423 if (parent_is_child) 4424 ok(!IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style); 4425 else 4426 ok(IsWindowEnabled(param->grand_parent), "wrong state for %08x\n", style); 4427 } 4428 4429 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, disabled_hwnd, empty_dlg_proc3, 0); 4430 ok(IsWindowEnabled(disabled_hwnd), "wrong state for %08x\n", style); 4431 4432 ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd); 4433 ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent); 4434 if (param->grand_parent) 4435 ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style); 4436 4437 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4438 ok(IsWindowEnabled(hwnd), "wrong state for %p\n", hwnd); 4439 ok(IsWindowEnabled(param->parent), "wrong state for %p\n", param->parent); 4440 if (param->grand_parent) 4441 ok(IsWindowEnabled(param->grand_parent), "wrong state for %p (%08x)\n", param->grand_parent, style); 4442 4443 param->dlg_data->style |= WS_CHILD; 4444 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4445 ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); 4446 4447 param->dlg_data->style |= DS_CONTROL; 4448 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4449 ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); 4450 4451 param->dlg_data->dwExtendedStyle |= WS_EX_CONTROLPARENT; 4452 SetWindowLongA(hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_CONTROLPARENT); 4453 SetWindowLongA(hwnd, GWL_STYLE, style & ~DS_CONTROL); 4454 param->dlg_data->style &= ~DS_CONTROL; 4455 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4456 ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); 4457 4458 SetWindowLongA(hwnd, GWL_STYLE, style | DS_CONTROL); 4459 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4460 ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); 4461 4462 param->dlg_data->style |= DS_CONTROL; 4463 DialogBoxIndirectParamA(GetModuleHandleA(NULL), param->dlg_data, hwnd, empty_dlg_proc3, 0); 4464 ok(IsWindowEnabled(hwnd), "wrong state for %p (%08x)\n", hwnd, style); 4465 4466 EndDialog(hwnd, 0); 4467 } 4468 return 0; 4469 } 4470 4471 static void check_dialog_style(DWORD style_in, DWORD ex_style_in, DWORD style_out, DWORD ex_style_out) 4472 { 4473 struct 4474 { 4475 DLGTEMPLATE dt; 4476 WORD menu_name; 4477 WORD class_id; 4478 WORD class_atom; 4479 WCHAR caption[1]; 4480 } dlg_data; 4481 DWORD style, ex_style; 4482 HWND hwnd, grand_parent = 0, parent = 0; 4483 struct dialog_param param; 4484 LRESULT id, ret; 4485 4486 if (style_in & WS_CHILD) 4487 { 4488 grand_parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 4489 0, 0, 0, 0, NULL, NULL, NULL, NULL); 4490 ok(grand_parent != 0, "grand_parent creation failed\n"); 4491 } 4492 4493 parent = CreateWindowExA(0, "static", NULL, style_in, 4494 0, 0, 0, 0, grand_parent, NULL, NULL, NULL); 4495 ok(parent != 0, "parent creation failed, style %#x\n", style_in); 4496 4497 dlg_data.dt.style = style_in; 4498 dlg_data.dt.dwExtendedStyle = ex_style_in; 4499 dlg_data.dt.cdit = 0; 4500 dlg_data.dt.x = 0; 4501 dlg_data.dt.y = 0; 4502 dlg_data.dt.cx = 100; 4503 dlg_data.dt.cy = 100; 4504 dlg_data.menu_name = 0; 4505 dlg_data.class_id = 0; 4506 dlg_data.class_atom = 0; 4507 dlg_data.caption[0] = 0; 4508 4509 hwnd = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc, 0); 4510 ok(hwnd != 0, "dialog creation failed, style %#x, exstyle %#x\n", style_in, ex_style_in); 4511 4512 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4513 ok(id == MAKELONG(IDOK,DC_HASDEFID), "expected (IDOK,DC_HASDEFID), got %08lx\n", id); 4514 ret = DefDlgProcA(hwnd, DM_SETDEFID, 0x1111, 0); 4515 ok(ret, "DefDlgProc(DM_SETDEFID) failed\n"); 4516 id = DefDlgProcA(hwnd, DM_GETDEFID, 0, 0); 4517 ok(id == MAKELONG(0x1111,DC_HASDEFID), "expected (0x1111,DC_HASDEFID), got %08lx\n", id); 4518 4519 flush_events( TRUE ); 4520 4521 style = GetWindowLongA(hwnd, GWL_STYLE); 4522 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 4523 ok(style == (style_out | DS_3DLOOK), "got %#x\n", style); 4524 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style); 4525 4526 ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in); 4527 4528 /* try setting the styles explicitly */ 4529 SetWindowLongA(hwnd, GWL_EXSTYLE, ex_style_in); 4530 style = GetWindowLongA(hwnd, GWL_STYLE); 4531 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 4532 ok(style == (style_out | DS_3DLOOK), "got %#x\n", style); 4533 /* WS_EX_WINDOWEDGE can't always be changed */ 4534 if (ex_style_in & WS_EX_DLGMODALFRAME) 4535 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE; 4536 else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE)) 4537 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE; 4538 else 4539 ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE; 4540 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style); 4541 4542 SetWindowLongA(hwnd, GWL_STYLE, style_in); 4543 style = GetWindowLongA(hwnd, GWL_STYLE); 4544 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 4545 /* WS_CLIPSIBLINGS can't be reset on top-level windows */ 4546 if ((style_in & (WS_CHILD | WS_POPUP)) == WS_CHILD) style_out = style_in; 4547 else style_out = style_in | WS_CLIPSIBLINGS; 4548 ok(style == style_out, "expected style %#x, got %#x\n", style_out, style); 4549 /* WS_EX_WINDOWEDGE can't always be changed */ 4550 if (ex_style_in & WS_EX_DLGMODALFRAME) 4551 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE; 4552 else if ((style & (WS_DLGFRAME | WS_THICKFRAME)) && !(ex_style_in & WS_EX_STATICEDGE)) 4553 ex_style_out = ex_style_in | WS_EX_WINDOWEDGE; 4554 else 4555 ex_style_out = ex_style_in & ~WS_EX_WINDOWEDGE; 4556 /* FIXME: Remove the condition below once Wine is fixed */ 4557 todo_wine_if (ex_style != ex_style_out) 4558 ok(ex_style == ex_style_out, "expected ex_style %#x, got %#x\n", ex_style_out, ex_style); 4559 4560 DestroyWindow(hwnd); 4561 4562 param.parent = parent; 4563 param.grand_parent = grand_parent; 4564 param.dlg_data = &dlg_data.dt; 4565 DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, parent, empty_dlg_proc2, (LPARAM)¶m); 4566 4567 ok(IsWindowEnabled(parent), "wrong parent state (dialog style %#x)\n", style_in); 4568 if (grand_parent) 4569 ok(IsWindowEnabled(grand_parent), "wrong grand parent state (dialog style %#x)\n", style_in); 4570 4571 DestroyWindow(parent); 4572 DestroyWindow(grand_parent); 4573 } 4574 4575 static void test_dialog_styles(void) 4576 { 4577 check_dialog_style(0, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4578 check_dialog_style(WS_DLGFRAME, 0, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4579 check_dialog_style(WS_THICKFRAME, 0, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4580 check_dialog_style(WS_DLGFRAME, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT); 4581 check_dialog_style(WS_THICKFRAME, WS_EX_STATICEDGE, WS_THICKFRAME|WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_STATICEDGE|WS_EX_CONTROLPARENT); 4582 check_dialog_style(DS_CONTROL, 0, WS_CLIPSIBLINGS|WS_CAPTION|DS_CONTROL, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4583 check_dialog_style(WS_CAPTION, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4584 check_dialog_style(WS_BORDER, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4585 check_dialog_style(WS_DLGFRAME, 0, WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4586 check_dialog_style(WS_BORDER|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4587 check_dialog_style(WS_DLGFRAME|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4588 check_dialog_style(WS_CAPTION|WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4589 check_dialog_style(WS_SYSMENU, 0, WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4590 check_dialog_style(WS_CAPTION|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4591 check_dialog_style(WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4592 check_dialog_style(WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CAPTION|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4593 check_dialog_style(WS_OVERLAPPEDWINDOW, 0, WS_CLIPSIBLINGS|WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4594 check_dialog_style(WS_CHILD, 0, WS_CHILD, 0); 4595 check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE); 4596 check_dialog_style(WS_CHILD|WS_THICKFRAME, 0, WS_CHILD|WS_THICKFRAME, WS_EX_WINDOWEDGE); 4597 check_dialog_style(WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_DLGFRAME, WS_EX_STATICEDGE); 4598 check_dialog_style(WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_THICKFRAME, WS_EX_STATICEDGE); 4599 check_dialog_style(WS_CHILD|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4600 check_dialog_style(WS_CHILD|WS_CAPTION, 0, WS_CHILD|WS_CAPTION, WS_EX_WINDOWEDGE); 4601 check_dialog_style(WS_CHILD|WS_BORDER, 0, WS_CHILD|WS_BORDER, 0); 4602 check_dialog_style(WS_CHILD|WS_DLGFRAME, 0, WS_CHILD|WS_DLGFRAME, WS_EX_WINDOWEDGE); 4603 check_dialog_style(WS_CHILD|WS_BORDER|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4604 check_dialog_style(WS_CHILD|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4605 check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_CAPTION|WS_SYSMENU, WS_EX_WINDOWEDGE); 4606 check_dialog_style(WS_CHILD|WS_SYSMENU, 0, WS_CHILD|WS_SYSMENU, 0); 4607 check_dialog_style(WS_CHILD|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4608 check_dialog_style(WS_CHILD|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4609 check_dialog_style(WS_CHILD|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|DS_CONTROL, WS_EX_CONTROLPARENT); 4610 check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0); 4611 check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME, WS_CHILD, WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); 4612 check_dialog_style(WS_CHILD, WS_EX_DLGMODALFRAME|WS_EX_STATICEDGE, WS_CHILD, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_DLGMODALFRAME); 4613 check_dialog_style(WS_CHILD|WS_POPUP, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0); 4614 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4615 check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, 0, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4616 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4617 check_dialog_style(WS_CHILD|WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_CHILD|WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE); 4618 check_dialog_style(WS_CHILD|WS_POPUP|DS_CONTROL, 0, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT); 4619 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4620 check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER, 0, WS_CHILD|WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, 0); 4621 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME, 0, WS_CHILD|WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4622 check_dialog_style(WS_CHILD|WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4623 check_dialog_style(WS_CHILD|WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4624 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 4625 check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU, 0, WS_CHILD|WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, 0); 4626 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4627 check_dialog_style(WS_CHILD|WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4628 check_dialog_style(WS_CHILD|WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_CHILD|WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4629 check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_APPWINDOW, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, WS_EX_APPWINDOW); 4630 check_dialog_style(WS_CHILD|WS_POPUP, WS_EX_WINDOWEDGE, WS_CHILD|WS_POPUP|WS_CLIPSIBLINGS, 0); 4631 check_dialog_style(WS_CHILD, WS_EX_WINDOWEDGE, WS_CHILD, 0); 4632 check_dialog_style(0, WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_WINDOWEDGE|WS_EX_TOOLWINDOW|WS_EX_CONTROLPARENT); 4633 check_dialog_style(WS_POPUP, 0, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4634 check_dialog_style(WS_POPUP, WS_EX_WINDOWEDGE, WS_POPUP|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4635 check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4636 check_dialog_style(WS_POPUP|WS_THICKFRAME, 0, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4637 check_dialog_style(WS_POPUP|WS_DLGFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT); 4638 check_dialog_style(WS_POPUP|WS_THICKFRAME, WS_EX_STATICEDGE, WS_POPUP|WS_THICKFRAME|WS_CLIPSIBLINGS, WS_EX_STATICEDGE|WS_EX_CONTROLPARENT); 4639 check_dialog_style(WS_POPUP|DS_CONTROL, 0, WS_POPUP|WS_CLIPSIBLINGS|DS_CONTROL, WS_EX_CONTROLPARENT); 4640 check_dialog_style(WS_POPUP|WS_CAPTION, 0, WS_POPUP|WS_CAPTION|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4641 check_dialog_style(WS_POPUP|WS_BORDER, 0, WS_POPUP|WS_BORDER|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4642 check_dialog_style(WS_POPUP|WS_DLGFRAME, 0, WS_POPUP|WS_DLGFRAME|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4643 check_dialog_style(WS_POPUP|WS_BORDER|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4644 check_dialog_style(WS_POPUP|WS_DLGFRAME|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4645 check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU, 0, WS_POPUP|WS_CAPTION|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4646 check_dialog_style(WS_POPUP|WS_SYSMENU, 0, WS_POPUP|WS_SYSMENU|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4647 check_dialog_style(WS_POPUP|WS_CAPTION|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4648 check_dialog_style(WS_POPUP|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4649 check_dialog_style(WS_POPUP|WS_CAPTION|WS_SYSMENU|DS_CONTROL, 0, WS_POPUP|DS_CONTROL|WS_CLIPSIBLINGS, WS_EX_CONTROLPARENT); 4650 check_dialog_style(WS_CAPTION, WS_EX_STATICEDGE, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_STATICEDGE|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4651 check_dialog_style(0, WS_EX_APPWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_APPWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4652 4653 if (pGetLayeredWindowAttributes) 4654 { 4655 check_dialog_style(0, WS_EX_LAYERED, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4656 check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT, WS_CLIPSIBLINGS|WS_CAPTION, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4657 check_dialog_style(0, WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW, WS_CLIPSIBLINGS|WS_CAPTION, 4658 WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOOLWINDOW|WS_EX_WINDOWEDGE|WS_EX_CONTROLPARENT); 4659 } 4660 } 4661 4662 struct dlg_parent_param 4663 { 4664 HWND ga_parent; 4665 HWND gwl_parent; 4666 HWND get_parent; 4667 HWND owner; 4668 HWND root; 4669 HWND ga_root_owner; 4670 }; 4671 4672 static INT_PTR WINAPI parent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4673 { 4674 if (msg == WM_INITDIALOG) { 4675 struct dlg_parent_param *param = (void*)lparam; 4676 check_parents(hwnd, param->ga_parent, param->gwl_parent, param->get_parent, param->owner, 4677 param->root ? param->root : hwnd, param->ga_root_owner ? param->ga_root_owner : hwnd); 4678 4679 ok(!IsWindowEnabled(param->gwl_parent), "parent is not disabled\n"); 4680 EndDialog(hwnd, 2); 4681 ok(IsWindowEnabled(param->gwl_parent), "parent is not enabled\n"); 4682 } 4683 4684 return 0; 4685 } 4686 4687 static INT_PTR WINAPI reparent_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4688 { 4689 if (msg == WM_INITDIALOG) { 4690 ok(!IsWindowEnabled(GetParent(hwnd)), "parent is not disabled\n"); 4691 SetParent(hwnd, (HWND)lparam); 4692 } 4693 4694 return 0; 4695 } 4696 4697 static INT_PTR WINAPI reparent_owned_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4698 { 4699 if (msg == WM_INITDIALOG) { 4700 HWND new_parent = (HWND)lparam; 4701 HWND owner = GetWindow(hwnd, GW_OWNER); 4702 ok(!IsWindowEnabled(owner), "owner is not disabled\n"); 4703 SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) | WS_CHILD); 4704 SetParent(hwnd, new_parent); 4705 ok(GetParent(hwnd) == new_parent, "GetParent(hwnd) = %p, expected %p\n", GetParent(hwnd), new_parent); 4706 PostMessageA(hwnd, WM_QUIT, 0, 0); 4707 } 4708 4709 return 0; 4710 } 4711 4712 static LRESULT WINAPI reparent_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4713 { 4714 if (msg == WM_ENTERIDLE) { 4715 HWND dialog = (HWND)lparam; 4716 HWND owner = GetParent(dialog); 4717 /* EndDialog will enable owner */ 4718 EnableWindow(owner, FALSE); 4719 EndDialog(dialog, 2); 4720 ok(IsWindowEnabled(owner), "owner is not enabled\n"); 4721 /* ...but it won't be enabled on dialog exit */ 4722 EnableWindow(owner, FALSE); 4723 } 4724 return DefWindowProcA( hwnd, msg, wparam, lparam ); 4725 } 4726 4727 static LRESULT WINAPI post_quit_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4728 { 4729 if (msg == WM_ENTERIDLE) { 4730 HWND dialog = (HWND)lparam; 4731 PostMessageA(dialog, WM_QUIT, 0, 0); 4732 } 4733 return DefWindowProcA( hwnd, msg, wparam, lparam ); 4734 } 4735 4736 static LRESULT WINAPI destroy_dialog_owner_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 4737 { 4738 if (msg == WM_ENTERIDLE) { 4739 HWND dialog = (HWND)lparam; 4740 DestroyWindow(dialog); 4741 } 4742 return DefWindowProcA( hwnd, msg, wparam, lparam ); 4743 } 4744 4745 static void test_dialog_parent(void) 4746 { 4747 HWND dialog, parent, child, child2, other, desktop = GetDesktopWindow(); 4748 struct dlg_parent_param param; 4749 INT_PTR ret; 4750 struct 4751 { 4752 DLGTEMPLATE dt; 4753 WORD menu_name; 4754 WORD class_id; 4755 WORD class_atom; 4756 WCHAR caption[1]; 4757 } dlg_data; 4758 4759 dlg_data.dt.dwExtendedStyle = 0; 4760 dlg_data.dt.cdit = 0; 4761 dlg_data.dt.x = 0; 4762 dlg_data.dt.y = 0; 4763 dlg_data.dt.cx = 100; 4764 dlg_data.dt.cy = 100; 4765 dlg_data.menu_name = 0; 4766 dlg_data.class_id = 0; 4767 dlg_data.class_atom = 0; 4768 dlg_data.caption[0] = 0; 4769 4770 parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL); 4771 /* Create a child without WS_CHILD flag. It's a valid owner window. */ 4772 child = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL); 4773 SetParent(child, parent); 4774 /* Regular child. If passed as an owner, its parent will be true owner window. */ 4775 child2 = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 0, 0, child, NULL, NULL, NULL); 4776 4777 trace("parent %p child %p child2 %p desktop %p\n", parent, child, child2, desktop); 4778 4779 /* When dialog is created with WS_CHILD style, its parent depends on function used to create it. */ 4780 dlg_data.dt.style = WS_CHILD; 4781 4782 /* CreateDialogIndirectParam uses passed parent as dialog parent. */ 4783 dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0); 4784 ok(dialog != 0, "dialog creation failed\n"); 4785 check_parents(dialog, child2, child2, child2, NULL, parent, child); 4786 4787 ok(IsWindowEnabled(child2), "child2 is disabled\n"); 4788 EnableWindow(child2, FALSE); 4789 EndDialog(dialog, 0); 4790 ok(IsWindowEnabled(child2), "child2 is not enabled\n"); 4791 DestroyWindow(dialog); 4792 4793 /* DialogBoxIndirectParam uses the first parent of passed owner that's not a child window as dialog 4794 * parent (like in case of dialog with owner). */ 4795 param.ga_parent = param.gwl_parent = param.get_parent = child; 4796 param.owner = NULL; 4797 param.root = parent; 4798 param.ga_root_owner = child; 4799 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m); 4800 ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret); 4801 4802 /* Dialogs without WS_CHILD behave as expected, they use passed owner just like CreateWindow does. */ 4803 dlg_data.dt.style = WS_OVERLAPPEDWINDOW; 4804 4805 dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0); 4806 ok(dialog != 0, "dialog creation failed\n"); 4807 check_parents(dialog, desktop, child, NULL, child, dialog, dialog); 4808 4809 ok(IsWindowEnabled(child), "child is disabled\n"); 4810 EnableWindow(child, FALSE); 4811 EndDialog(dialog, 0); 4812 ok(IsWindowEnabled(child), "child is not enabled\n"); 4813 DestroyWindow(dialog); 4814 4815 param.ga_parent = desktop; 4816 param.gwl_parent = child; 4817 param.get_parent = NULL; 4818 param.owner = child; 4819 param.root = param.ga_root_owner = NULL; 4820 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m); 4821 ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret); 4822 4823 other = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, NULL, NULL, NULL, NULL); 4824 SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)reparent_dialog_owner_proc); 4825 4826 /* When dialog is created with WS_CHILD|WS_POPUP style, we have an owner. */ 4827 dlg_data.dt.style = WS_CHILD|WS_POPUP; 4828 4829 dialog = CreateDialogIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, empty_dlg_proc, 0); 4830 ok(dialog != 0, "dialog creation failed\n"); 4831 check_parents(dialog, desktop, child, child, child, dialog, child); 4832 4833 ok(IsWindowEnabled(child), "child is disabled\n"); 4834 EnableWindow(child, FALSE); 4835 EndDialog(dialog, 0); 4836 ok(IsWindowEnabled(child), "child is not enabled\n"); 4837 DestroyWindow(dialog); 4838 4839 param.ga_parent = desktop; 4840 param.gwl_parent = param.get_parent = child; 4841 param.owner = child; 4842 param.root = NULL; 4843 param.ga_root_owner = child; 4844 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, parent_dlg_proc, (LPARAM)¶m); 4845 ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret); 4846 4847 /* If we change parent in WM_INITDIALOG for WS_CHILD dialog WM_ENTERIDLE is still sent to the original 4848 * parent. EndDialog will enable the new parent. */ 4849 EnableWindow(child, TRUE); 4850 EnableWindow(other, FALSE); 4851 dlg_data.dt.style = WS_CHILD; 4852 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_dlg_proc, (LPARAM)other); 4853 ok(ret == 2, "DialogBoxIndirectParam returned %ld\n", ret); 4854 ok(!IsWindowEnabled(other), "other is not disabled\n"); 4855 ok(!IsWindowEnabled(child), "child is not disabled\n"); 4856 ok(IsWindowEnabled(child2), "child2 is not enabled\n"); 4857 EnableWindow(child, TRUE); 4858 4859 /* If we change parent and style in WM_INITDIALOG for dialog with an owner to make it true child 4860 * (thus GetParent() will return the new parent instead of an owner), WM_ENTERIDLE is still sent 4861 * to the original parent. EndDialog will enable the new parent. */ 4862 EnableWindow(other, FALSE); 4863 dlg_data.dt.style = WS_OVERLAPPED; 4864 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, child2, reparent_owned_dlg_proc, (LPARAM)other); 4865 ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret); 4866 ok(!IsWindowEnabled(other), "other is not disabled\n"); 4867 ok(!IsWindowEnabled(child), "child is not disabled\n"); 4868 ok(IsWindowEnabled(child2), "child2 is not enabled\n"); 4869 EnableWindow(child, TRUE); 4870 EnableWindow(other, TRUE); 4871 4872 /* Quit dialog message loop by sending WM_QUIT message. Dialog owner is not enabled. */ 4873 SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)post_quit_dialog_owner_proc); 4874 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0); 4875 ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret); 4876 ok(!IsWindowEnabled(other), "other is enabled\n"); 4877 EnableWindow(other, TRUE); 4878 4879 /* Quit dialog message loop by destroying the window. Dialog owner is not enabled. */ 4880 SetWindowLongPtrA(child, GWLP_WNDPROC, (ULONG_PTR)destroy_dialog_owner_proc); 4881 ret = DialogBoxIndirectParamA(GetModuleHandleA(NULL), &dlg_data.dt, other, empty_dlg_proc, 0); 4882 ok(ret == 1, "DialogBoxIndirectParam returned %ld\n", ret); 4883 ok(!IsWindowEnabled(other), "other is enabled\n"); 4884 EnableWindow(other, TRUE); 4885 4886 DestroyWindow(parent); 4887 } 4888 4889 static void test_scrollwindow( HWND hwnd) 4890 { 4891 HDC hdc; 4892 RECT rc, rc2, rc3; 4893 COLORREF colr; 4894 4895 ShowWindow( hwnd, SW_SHOW); 4896 UpdateWindow( hwnd); 4897 flush_events( TRUE ); 4898 GetClientRect( hwnd, &rc); 4899 hdc = GetDC( hwnd); 4900 /* test ScrollWindow(Ex) with no clip rectangle */ 4901 /* paint the lower half of the window black */ 4902 rc2 = rc; 4903 rc2.top = ( rc2.top + rc2.bottom) / 2; 4904 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH)); 4905 /* paint the upper half of the window white */ 4906 rc2.bottom = rc2.top; 4907 rc2.top =0; 4908 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH)); 4909 /* scroll lower half up */ 4910 rc2 = rc; 4911 rc2.top = ( rc2.top + rc2.bottom) / 2; 4912 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, NULL, NULL, NULL, SW_ERASE); 4913 flush_events(FALSE); 4914 /* expected: black should have scrolled to the upper half */ 4915 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 ); 4916 ok ( colr == 0, "pixel should be black, color is %08x\n", colr); 4917 /* Repeat that test of ScrollWindow(Ex) now with clip rectangle */ 4918 /* paint the lower half of the window black */ 4919 rc2 = rc; 4920 rc2.top = ( rc2.top + rc2.bottom) / 2; 4921 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH)); 4922 /* paint the upper half of the window white */ 4923 rc2.bottom = rc2.top; 4924 rc2.top =0; 4925 FillRect( hdc, &rc2, GetStockObject(WHITE_BRUSH)); 4926 /* scroll lower half up */ 4927 rc2 = rc; 4928 rc2.top = ( rc2.top + rc2.bottom) / 2; 4929 rc3 = rc; 4930 rc3.left = rc3.right / 4; 4931 rc3.right -= rc3.right / 4; 4932 ScrollWindowEx( hwnd, 0, - rc2.top, &rc2, &rc3, NULL, NULL, SW_ERASE); 4933 flush_events(FALSE); 4934 /* expected: black should have scrolled to the upper half */ 4935 colr = GetPixel( hdc, (rc2.left+rc2.right)/ 2, rc2.bottom / 4 ); 4936 ok ( colr == 0, "pixel should be black, color is %08x\n", colr); 4937 4938 /* clean up */ 4939 ReleaseDC( hwnd, hdc); 4940 } 4941 4942 static void test_scrollvalidate( HWND parent) 4943 { 4944 HDC hdc; 4945 HRGN hrgn=CreateRectRgn(0,0,0,0); 4946 HRGN exprgn, tmprgn, clipping; 4947 RECT rc, rcu, cliprc; 4948 /* create two overlapping child windows. The visual region 4949 * of hwnd1 is clipped by the overlapping part of 4950 * hwnd2 because of the WS_CLIPSIBLING style */ 4951 HWND hwnd1, hwnd2; 4952 4953 clipping = CreateRectRgn(0,0,0,0); 4954 tmprgn = CreateRectRgn(0,0,0,0); 4955 exprgn = CreateRectRgn(0,0,0,0); 4956 hwnd2 = CreateWindowExA(0, "static", NULL, 4957 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER , 4958 75, 30, 100, 100, parent, 0, 0, NULL); 4959 hwnd1 = CreateWindowExA(0, "static", NULL, 4960 WS_CHILD| WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER , 4961 25, 50, 100, 100, parent, 0, 0, NULL); 4962 ShowWindow( parent, SW_SHOW); 4963 UpdateWindow( parent); 4964 GetClientRect( hwnd1, &rc); 4965 cliprc=rc; 4966 SetRectRgn( clipping, 10, 10, 90, 90); 4967 hdc = GetDC( hwnd1); 4968 /* for a visual touch */ 4969 TextOutA( hdc, 0,10, "0123456789", 10); 4970 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu); 4971 if (winetest_debug > 0) dump_region(hrgn); 4972 /* create a region with what is expected */ 4973 SetRectRgn( exprgn, 39,0,49,74); 4974 SetRectRgn( tmprgn, 88,79,98,93); 4975 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 4976 SetRectRgn( tmprgn, 0,93,98,98); 4977 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 4978 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 4979 trace("update rect is %s\n", wine_dbgstr_rect(&rcu)); 4980 /* now with clipping region */ 4981 SelectClipRgn( hdc, clipping); 4982 ScrollDC( hdc, -10, -5, &rc, &cliprc, hrgn, &rcu); 4983 if (winetest_debug > 0) dump_region(hrgn); 4984 /* create a region with what is expected */ 4985 SetRectRgn( exprgn, 39,10,49,74); 4986 SetRectRgn( tmprgn, 80,79,90,85); 4987 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 4988 SetRectRgn( tmprgn, 10,85,90,90); 4989 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 4990 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 4991 trace("update rect is %s\n", wine_dbgstr_rect(&rcu)); 4992 ReleaseDC( hwnd1, hdc); 4993 4994 /* test scrolling a rect by more than its size */ 4995 DestroyWindow( hwnd2); 4996 ValidateRect( hwnd1, NULL); 4997 SetRect( &rc, 40,40, 50,50); 4998 InvalidateRect( hwnd1, &rc, 1); 4999 ScrollWindowEx( hwnd1, -20, 0, &rc, NULL, hrgn, &rcu, 5000 SW_SCROLLCHILDREN | SW_INVALIDATE); 5001 if (winetest_debug > 0) dump_region(hrgn); 5002 SetRectRgn( exprgn, 20, 40, 30, 50); 5003 SetRectRgn( tmprgn, 40, 40, 50, 50); 5004 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5005 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5006 ok( rcu.left == 20 && rcu.top == 40 && rcu.right == 50 && rcu.bottom == 50, 5007 "unexpected update rect: %s\n", wine_dbgstr_rect(&rcu)); 5008 5009 /* test scrolling a window with an update region */ 5010 ValidateRect( hwnd1, NULL); 5011 SetRect( &rc, 40,40, 50,50); 5012 InvalidateRect( hwnd1, &rc, 1); 5013 GetClientRect( hwnd1, &rc); 5014 cliprc=rc; 5015 ScrollWindowEx( hwnd1, -10, 0, &rc, &cliprc, hrgn, &rcu, 5016 SW_SCROLLCHILDREN | SW_INVALIDATE); 5017 if (winetest_debug > 0) dump_region(hrgn); 5018 SetRectRgn( exprgn, 88,0,98,98); 5019 SetRectRgn( tmprgn, 30, 40, 50, 50); 5020 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5021 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5022 5023 /* clear an update region */ 5024 UpdateWindow( hwnd1 ); 5025 5026 SetRect( &rc, 0,40, 100,60); 5027 SetRect( &cliprc, 0,0, 100,100); 5028 ScrollWindowEx( hwnd1, 0, -25, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE); 5029 if (winetest_debug > 0) dump_region( hrgn ); 5030 SetRectRgn( exprgn, 0, 40, 98, 60 ); 5031 ok( EqualRgn( exprgn, hrgn), "wrong update region in excessive scroll\n"); 5032 5033 /* now test ScrollWindowEx with a combination of 5034 * WS_CLIPCHILDREN style and SW_SCROLLCHILDREN flag */ 5035 /* make hwnd2 the child of hwnd1 */ 5036 hwnd2 = CreateWindowExA(0, "static", NULL, 5037 WS_CHILD| WS_VISIBLE | WS_BORDER , 5038 50, 50, 100, 100, hwnd1, 0, 0, NULL); 5039 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPSIBLINGS); 5040 GetClientRect( hwnd1, &rc); 5041 cliprc=rc; 5042 5043 /* WS_CLIPCHILDREN and SW_SCROLLCHILDREN */ 5044 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN ); 5045 ValidateRect( hwnd1, NULL); 5046 ValidateRect( hwnd2, NULL); 5047 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, 5048 SW_SCROLLCHILDREN | SW_INVALIDATE); 5049 if (winetest_debug > 0) dump_region(hrgn); 5050 SetRectRgn( exprgn, 88,0,98,88); 5051 SetRectRgn( tmprgn, 0,88,98,98); 5052 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5053 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5054 5055 /* SW_SCROLLCHILDREN */ 5056 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN ); 5057 ValidateRect( hwnd1, NULL); 5058 ValidateRect( hwnd2, NULL); 5059 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_SCROLLCHILDREN | SW_INVALIDATE); 5060 if (winetest_debug > 0) dump_region(hrgn); 5061 /* expected region is the same as in previous test */ 5062 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5063 5064 /* no SW_SCROLLCHILDREN */ 5065 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) & ~WS_CLIPCHILDREN ); 5066 ValidateRect( hwnd1, NULL); 5067 ValidateRect( hwnd2, NULL); 5068 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE); 5069 if (winetest_debug > 0) dump_region(hrgn); 5070 /* expected region is the same as in previous test */ 5071 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5072 5073 /* WS_CLIPCHILDREN and no SW_SCROLLCHILDREN */ 5074 SetWindowLongA( hwnd1, GWL_STYLE, GetWindowLongA( hwnd1, GWL_STYLE) | WS_CLIPCHILDREN ); 5075 ValidateRect( hwnd1, NULL); 5076 ValidateRect( hwnd2, NULL); 5077 ScrollWindowEx( hwnd1, -10, -10, &rc, &cliprc, hrgn, &rcu, SW_INVALIDATE); 5078 if (winetest_debug > 0) dump_region(hrgn); 5079 SetRectRgn( exprgn, 88,0,98,20); 5080 SetRectRgn( tmprgn, 20,20,98,30); 5081 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5082 SetRectRgn( tmprgn, 20,30,30,88); 5083 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5084 SetRectRgn( tmprgn, 0,88,30,98); 5085 CombineRgn( exprgn, exprgn, tmprgn, RGN_OR); 5086 ok( EqualRgn( exprgn, hrgn), "wrong update region\n"); 5087 5088 /* clean up */ 5089 DeleteObject( hrgn); 5090 DeleteObject( exprgn); 5091 DeleteObject( tmprgn); 5092 DestroyWindow( hwnd1); 5093 DestroyWindow( hwnd2); 5094 } 5095 5096 /* couple of tests of return values of scrollbar functions 5097 * called on a scrollbarless window */ 5098 static void test_scroll(void) 5099 { 5100 BOOL ret; 5101 INT min, max; 5102 SCROLLINFO si; 5103 HWND hwnd = CreateWindowExA(0, "Static", "Wine test window", 5104 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, 5105 100, 100, 200, 200, 0, 0, 0, NULL); 5106 /* horizontal */ 5107 ret = GetScrollRange( hwnd, SB_HORZ, &min, &max); 5108 if (!ret) /* win9x */ 5109 { 5110 win_skip( "GetScrollRange doesn't work\n" ); 5111 DestroyWindow( hwnd); 5112 return; 5113 } 5114 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min); 5115 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min); 5116 si.cbSize = sizeof( si); 5117 si.fMask = SIF_PAGE; 5118 si.nPage = 0xdeadbeef; 5119 ret = GetScrollInfo( hwnd, SB_HORZ, &si); 5120 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret); 5121 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage); 5122 /* vertical */ 5123 ret = GetScrollRange( hwnd, SB_VERT, &min, &max); 5124 ok( ret, "GetScrollRange returns FALSE\n"); 5125 ok( min == 0, "minimum scroll pos is %d (should be zero)\n", min); 5126 ok( max == 0, "maximum scroll pos is %d (should be zero)\n", min); 5127 si.cbSize = sizeof( si); 5128 si.fMask = SIF_PAGE; 5129 si.nPage = 0xdeadbeef; 5130 ret = GetScrollInfo( hwnd, SB_VERT, &si); 5131 ok( !ret, "GetScrollInfo returns %d (should be zero)\n", ret); 5132 ok( si.nPage == 0xdeadbeef, "unexpected value for nPage is %d\n", si.nPage); 5133 /* clean up */ 5134 DestroyWindow( hwnd); 5135 } 5136 5137 static void test_scrolldc( HWND parent) 5138 { 5139 HDC hdc; 5140 HRGN exprgn, tmprgn, hrgn; 5141 RECT rc, rc2, rcu, cliprc; 5142 HWND hwnd1; 5143 COLORREF colr; 5144 5145 hrgn = CreateRectRgn(0,0,0,0); 5146 tmprgn = CreateRectRgn(0,0,0,0); 5147 exprgn = CreateRectRgn(0,0,0,0); 5148 5149 hwnd1 = CreateWindowExA(0, "static", NULL, 5150 WS_CHILD| WS_VISIBLE, 5151 25, 50, 100, 100, parent, 0, 0, NULL); 5152 ShowWindow( parent, SW_SHOW); 5153 UpdateWindow( parent); 5154 flush_events( TRUE ); 5155 GetClientRect( hwnd1, &rc); 5156 hdc = GetDC( hwnd1); 5157 /* paint the upper half of the window black */ 5158 rc2 = rc; 5159 rc2.bottom = ( rc.top + rc.bottom) /2; 5160 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH)); 5161 /* clip region is the lower half */ 5162 cliprc=rc; 5163 cliprc.top = (rc.top + rc.bottom) /2; 5164 /* test whether scrolled pixels are properly clipped */ 5165 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1); 5166 ok ( colr == 0, "pixel should be black, color is %08x\n", colr); 5167 /* this scroll should not cause any visible changes */ 5168 ScrollDC( hdc, 5, -20, &rc, &cliprc, hrgn, &rcu); 5169 colr = GetPixel( hdc, (rc.left+rc.right)/2, ( rc.top + rc.bottom) /2 - 1); 5170 ok ( colr == 0, "pixel should be black, color is %08x\n", colr); 5171 /* test with NULL clip rect */ 5172 ScrollDC( hdc, 20, -20, &rc, NULL, hrgn, &rcu); 5173 /*FillRgn(hdc, hrgn, GetStockObject(WHITE_BRUSH));*/ 5174 trace("update rect: %s\n", wine_dbgstr_rect(&rcu)); 5175 if (winetest_debug > 0) dump_region(hrgn); 5176 SetRect(&rc2, 0, 0, 100, 100); 5177 ok(EqualRect(&rcu, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rcu), 5178 wine_dbgstr_rect(&rc2)); 5179 5180 SetRectRgn( exprgn, 0, 0, 20, 80); 5181 SetRectRgn( tmprgn, 0, 80, 100, 100); 5182 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR); 5183 if (winetest_debug > 0) dump_region(exprgn); 5184 ok(EqualRgn(exprgn, hrgn), "wrong update region\n"); 5185 /* test clip rect > scroll rect */ 5186 FillRect( hdc, &rc, GetStockObject(WHITE_BRUSH)); 5187 rc2=rc; 5188 InflateRect( &rc2, -(rc.right-rc.left)/4, -(rc.bottom-rc.top)/4); 5189 FillRect( hdc, &rc2, GetStockObject(BLACK_BRUSH)); 5190 ScrollDC( hdc, 10, 10, &rc2, &rc, hrgn, &rcu); 5191 SetRectRgn( exprgn, 25, 25, 75, 35); 5192 SetRectRgn( tmprgn, 25, 35, 35, 75); 5193 CombineRgn(exprgn, exprgn, tmprgn, RGN_OR); 5194 ok(EqualRgn(exprgn, hrgn), "wrong update region\n"); 5195 trace("update rect: %s\n", wine_dbgstr_rect(&rcu)); 5196 if (winetest_debug > 0) dump_region(hrgn); 5197 5198 /* clean up */ 5199 DeleteObject(hrgn); 5200 DeleteObject(exprgn); 5201 DeleteObject(tmprgn); 5202 DestroyWindow(hwnd1); 5203 } 5204 5205 static void test_params(void) 5206 { 5207 HWND hwnd; 5208 INT rc; 5209 5210 ok(!IsWindow(0), "IsWindow(0)\n"); 5211 ok(!IsWindow(HWND_BROADCAST), "IsWindow(HWND_BROADCAST)\n"); 5212 ok(!IsWindow(HWND_TOPMOST), "IsWindow(HWND_TOPMOST)\n"); 5213 5214 /* Just a param check */ 5215 if (pGetMonitorInfoA) 5216 { 5217 SetLastError(0xdeadbeef); 5218 rc = GetWindowTextA(hwndMain2, NULL, 1024); 5219 ok( rc==0, "GetWindowText: rc=%d err=%d\n",rc,GetLastError()); 5220 } 5221 else 5222 { 5223 /* Skips actually on Win95 and NT4 */ 5224 win_skip("Test would crash on Win95\n"); 5225 } 5226 5227 SetLastError(0xdeadbeef); 5228 hwnd=CreateWindowA("LISTBOX", "TestList", 5229 (LBS_STANDARD & ~LBS_SORT), 5230 0, 0, 100, 100, 5231 NULL, (HMENU)1, NULL, 0); 5232 5233 ok(!hwnd || broken(hwnd != NULL), /* w2k3 sp2 */ 5234 "CreateWindow with invalid menu handle should fail\n"); 5235 if (!hwnd) 5236 ok(GetLastError() == ERROR_INVALID_MENU_HANDLE || /* NT */ 5237 GetLastError() == 0xdeadbeef, /* Win9x */ 5238 "wrong last error value %d\n", GetLastError()); 5239 } 5240 5241 static void test_AWRwindow(LPCSTR class, LONG style, LONG exStyle, BOOL menu) 5242 { 5243 HWND hwnd = 0; 5244 5245 hwnd = CreateWindowExA(exStyle, class, class, style, 5246 110, 100, 5247 225, 200, 5248 0, 5249 menu ? hmenu : 0, 5250 0, 0); 5251 if (!hwnd) { 5252 trace("Failed to create window class=%s, style=0x%08x, exStyle=0x%08x\n", class, style, exStyle); 5253 return; 5254 } 5255 ShowWindow(hwnd, SW_SHOW); 5256 5257 test_nonclient_area(hwnd); 5258 5259 SetMenu(hwnd, 0); 5260 DestroyWindow(hwnd); 5261 } 5262 5263 static BOOL AWR_init(void) 5264 { 5265 WNDCLASSA class; 5266 5267 class.style = CS_HREDRAW | CS_VREDRAW; 5268 class.lpfnWndProc = DefWindowProcA; 5269 class.cbClsExtra = 0; 5270 class.cbWndExtra = 0; 5271 class.hInstance = 0; 5272 class.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION); 5273 class.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 5274 class.hbrBackground = 0; 5275 class.lpszMenuName = 0; 5276 class.lpszClassName = szAWRClass; 5277 5278 if (!RegisterClassA(&class)) { 5279 ok(FALSE, "RegisterClass failed\n"); 5280 return FALSE; 5281 } 5282 5283 hmenu = CreateMenu(); 5284 if (!hmenu) 5285 return FALSE; 5286 ok(hmenu != 0, "Failed to create menu\n"); 5287 ok(AppendMenuA(hmenu, MF_STRING, 1, "Test!"), "Failed to create menu item\n"); 5288 5289 return TRUE; 5290 } 5291 5292 5293 static void test_AWR_window_size(BOOL menu) 5294 { 5295 static const DWORD styles[] = { 5296 WS_POPUP, WS_MAXIMIZE, WS_BORDER, WS_DLGFRAME, WS_CAPTION, WS_SYSMENU, 5297 WS_THICKFRAME, WS_MINIMIZEBOX, WS_MAXIMIZEBOX, WS_HSCROLL, WS_VSCROLL 5298 }; 5299 static const DWORD exStyles[] = { 5300 WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE, WS_EX_APPWINDOW, 5301 WS_EX_DLGMODALFRAME, WS_EX_DLGMODALFRAME | WS_EX_STATICEDGE 5302 }; 5303 5304 unsigned int i; 5305 5306 /* A exhaustive check of all the styles takes too long 5307 * so just do a (hopefully representative) sample 5308 */ 5309 for (i = 0; i < COUNTOF(styles); ++i) 5310 test_AWRwindow(szAWRClass, styles[i], 0, menu); 5311 for (i = 0; i < COUNTOF(exStyles); ++i) { 5312 test_AWRwindow(szAWRClass, WS_POPUP, exStyles[i], menu); 5313 test_AWRwindow(szAWRClass, WS_THICKFRAME, exStyles[i], menu); 5314 } 5315 } 5316 5317 static void test_AWR_flags(void) 5318 { 5319 static const DWORD styles[] = { WS_POPUP, WS_BORDER, WS_DLGFRAME, WS_THICKFRAME }; 5320 static const DWORD exStyles[] = { WS_EX_CLIENTEDGE, WS_EX_TOOLWINDOW, WS_EX_WINDOWEDGE, 5321 WS_EX_APPWINDOW, WS_EX_DLGMODALFRAME, WS_EX_STATICEDGE }; 5322 5323 DWORD i, j, k, style, exstyle; 5324 RECT rect, rect2; 5325 5326 for (i = 0; i < (1 << COUNTOF(styles)); i++) 5327 { 5328 for (k = style = 0; k < COUNTOF(styles); k++) if (i & (1 << k)) style |= styles[k]; 5329 5330 for (j = 0; j < (1 << COUNTOF(exStyles)); j++) 5331 { 5332 for (k = exstyle = 0; k < COUNTOF(exStyles); k++) if (j & (1 << k)) exstyle |= exStyles[k]; 5333 SetRect( &rect, 100, 100, 200, 200 ); 5334 rect2 = rect; 5335 AdjustWindowRectEx( &rect, style, FALSE, exstyle ); 5336 wine_AdjustWindowRectEx( &rect2, style, FALSE, exstyle ); 5337 ok( EqualRect( &rect, &rect2 ), "rects do not match: win %s wine %s\n", 5338 wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &rect2 )); 5339 } 5340 } 5341 } 5342 #undef COUNTOF 5343 5344 #define SHOWSYSMETRIC(SM) trace(#SM "=%d\n", GetSystemMetrics(SM)) 5345 5346 static void test_AdjustWindowRect(void) 5347 { 5348 if (!AWR_init()) 5349 return; 5350 5351 SHOWSYSMETRIC(SM_CYCAPTION); 5352 SHOWSYSMETRIC(SM_CYSMCAPTION); 5353 SHOWSYSMETRIC(SM_CYMENU); 5354 SHOWSYSMETRIC(SM_CXEDGE); 5355 SHOWSYSMETRIC(SM_CYEDGE); 5356 SHOWSYSMETRIC(SM_CXVSCROLL); 5357 SHOWSYSMETRIC(SM_CYHSCROLL); 5358 SHOWSYSMETRIC(SM_CXFRAME); 5359 SHOWSYSMETRIC(SM_CYFRAME); 5360 SHOWSYSMETRIC(SM_CXDLGFRAME); 5361 SHOWSYSMETRIC(SM_CYDLGFRAME); 5362 SHOWSYSMETRIC(SM_CXBORDER); 5363 SHOWSYSMETRIC(SM_CYBORDER); 5364 5365 test_AWR_window_size(FALSE); 5366 test_AWR_window_size(TRUE); 5367 test_AWR_flags(); 5368 5369 DestroyMenu(hmenu); 5370 } 5371 #undef SHOWSYSMETRIC 5372 5373 5374 /* Global variables to trigger exit from loop */ 5375 static int redrawComplete, WMPAINT_count; 5376 5377 static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 5378 { 5379 switch (msg) 5380 { 5381 case WM_PAINT: 5382 trace("doing WM_PAINT %d\n", WMPAINT_count); 5383 WMPAINT_count++; 5384 if (WMPAINT_count > 10 && redrawComplete == 0) { 5385 PAINTSTRUCT ps; 5386 BeginPaint(hwnd, &ps); 5387 EndPaint(hwnd, &ps); 5388 return 1; 5389 } 5390 return 0; 5391 } 5392 return DefWindowProcA(hwnd, msg, wparam, lparam); 5393 } 5394 5395 /* Ensure we exit from RedrawNow regardless of invalidated area */ 5396 static void test_redrawnow(void) 5397 { 5398 WNDCLASSA cls; 5399 HWND hwndMain; 5400 5401 cls.style = CS_DBLCLKS; 5402 cls.lpfnWndProc = redraw_window_procA; 5403 cls.cbClsExtra = 0; 5404 cls.cbWndExtra = 0; 5405 cls.hInstance = GetModuleHandleA(0); 5406 cls.hIcon = 0; 5407 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 5408 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 5409 cls.lpszMenuName = NULL; 5410 cls.lpszClassName = "RedrawWindowClass"; 5411 5412 if(!RegisterClassA(&cls)) { 5413 trace("Register failed %d\n", GetLastError()); 5414 return; 5415 } 5416 5417 hwndMain = CreateWindowA("RedrawWindowClass", "Main Window", WS_OVERLAPPEDWINDOW, 5418 CW_USEDEFAULT, 0, 100, 100, NULL, NULL, 0, NULL); 5419 5420 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); 5421 ShowWindow(hwndMain, SW_SHOW); 5422 ok( WMPAINT_count == 0, "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); 5423 RedrawWindow(hwndMain, NULL,NULL,RDW_UPDATENOW | RDW_ALLCHILDREN); 5424 ok( WMPAINT_count == 1 || broken(WMPAINT_count == 0), /* sometimes on win9x */ 5425 "Multiple unexpected WM_PAINT calls %d\n", WMPAINT_count); 5426 redrawComplete = TRUE; 5427 ok( WMPAINT_count < 10, "RedrawWindow (RDW_UPDATENOW) never completed (%d)\n", WMPAINT_count); 5428 5429 /* clean up */ 5430 DestroyWindow( hwndMain); 5431 } 5432 5433 struct parentdc_stat { 5434 RECT client; 5435 RECT clip; 5436 RECT paint; 5437 }; 5438 5439 struct parentdc_test { 5440 struct parentdc_stat main, main_todo; 5441 struct parentdc_stat child1, child1_todo; 5442 struct parentdc_stat child2, child2_todo; 5443 }; 5444 5445 static LRESULT WINAPI parentdc_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 5446 { 5447 RECT rc; 5448 PAINTSTRUCT ps; 5449 5450 struct parentdc_stat *t = (struct parentdc_stat *)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 5451 5452 switch (msg) 5453 { 5454 case WM_PAINT: 5455 GetClientRect(hwnd, &rc); 5456 t->client = rc; 5457 GetWindowRect(hwnd, &rc); 5458 trace("WM_PAINT: hwnd %p, client rect %s, window rect %s\n", hwnd, 5459 wine_dbgstr_rect(&t->client), wine_dbgstr_rect(&rc)); 5460 BeginPaint(hwnd, &ps); 5461 t->paint = ps.rcPaint; 5462 GetClipBox(ps.hdc, &rc); 5463 t->clip = rc; 5464 trace("clip rect %s, paint rect %s\n", wine_dbgstr_rect(&rc), 5465 wine_dbgstr_rect(&ps.rcPaint)); 5466 EndPaint(hwnd, &ps); 5467 return 0; 5468 } 5469 return DefWindowProcA(hwnd, msg, wparam, lparam); 5470 } 5471 5472 static void zero_parentdc_stat(struct parentdc_stat *t) 5473 { 5474 SetRectEmpty(&t->client); 5475 SetRectEmpty(&t->clip); 5476 SetRectEmpty(&t->paint); 5477 } 5478 5479 static void zero_parentdc_test(struct parentdc_test *t) 5480 { 5481 zero_parentdc_stat(&t->main); 5482 zero_parentdc_stat(&t->child1); 5483 zero_parentdc_stat(&t->child2); 5484 } 5485 5486 #define parentdc_field_ok(t, w, r, f, got) \ 5487 ok (t.w.r.f==got.w.r.f, "window " #w ", rect " #r ", field " #f \ 5488 ": expected %d, got %d\n", \ 5489 t.w.r.f, got.w.r.f) 5490 5491 #define parentdc_todo_field_ok(t, w, r, f, got) \ 5492 todo_wine_if (t.w##_todo.r.f) \ 5493 parentdc_field_ok(t, w, r, f, got); 5494 5495 #define parentdc_rect_ok(t, w, r, got) \ 5496 parentdc_todo_field_ok(t, w, r, left, got); \ 5497 parentdc_todo_field_ok(t, w, r, top, got); \ 5498 parentdc_todo_field_ok(t, w, r, right, got); \ 5499 parentdc_todo_field_ok(t, w, r, bottom, got); 5500 5501 #define parentdc_win_ok(t, w, got) \ 5502 parentdc_rect_ok(t, w, client, got); \ 5503 parentdc_rect_ok(t, w, clip, got); \ 5504 parentdc_rect_ok(t, w, paint, got); 5505 5506 #define parentdc_ok(t, got) \ 5507 parentdc_win_ok(t, main, got); \ 5508 parentdc_win_ok(t, child1, got); \ 5509 parentdc_win_ok(t, child2, got); 5510 5511 static void test_csparentdc(void) 5512 { 5513 WNDCLASSA clsMain, cls; 5514 HWND hwndMain, hwnd1, hwnd2; 5515 RECT rc; 5516 5517 struct parentdc_test test_answer; 5518 5519 #define nothing_todo {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} 5520 const struct parentdc_test test1 = 5521 { 5522 {{0, 0, 150, 150}, {0, 0, 150, 150}, {0, 0, 150, 150}}, nothing_todo, 5523 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}}, 5524 {{0, 0, 40, 40}, {-40, -40, 110, 110}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}}, 5525 }; 5526 5527 const struct parentdc_test test2 = 5528 { 5529 {{0, 0, 150, 150}, {0, 0, 50, 50}, {0, 0, 50, 50}}, nothing_todo, 5530 {{0, 0, 40, 40}, {-20, -20, 30, 30}, {0, 0, 30, 30}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}, 5531 {{0, 0, 40, 40}, {-40, -40, 10, 10}, {0, 0, 10, 10}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}, 5532 }; 5533 5534 const struct parentdc_test test3 = 5535 { 5536 {{0, 0, 150, 150}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo, 5537 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5538 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5539 }; 5540 5541 const struct parentdc_test test4 = 5542 { 5543 {{0, 0, 150, 150}, {40, 40, 50, 50}, {40, 40, 50, 50}}, nothing_todo, 5544 {{0, 0, 40, 40}, {20, 20, 30, 30}, {20, 20, 30, 30}}, nothing_todo, 5545 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo, 5546 }; 5547 5548 const struct parentdc_test test5 = 5549 { 5550 {{0, 0, 150, 150}, {20, 20, 60, 60}, {20, 20, 60, 60}}, nothing_todo, 5551 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}}, 5552 {{0, 0, 40, 40}, {-20, -20, 20, 20}, {0, 0, 20, 20}}, {{0, 0, 0, 0}, {1, 1, 0, 0}, {0, 0, 0, 0}}, 5553 }; 5554 5555 const struct parentdc_test test6 = 5556 { 5557 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5558 {{0, 0, 40, 40}, {0, 0, 10, 10}, {0, 0, 10, 10}}, nothing_todo, 5559 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5560 }; 5561 5562 const struct parentdc_test test7 = 5563 { 5564 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5565 {{0, 0, 40, 40}, {-20, -20, 130, 130}, {0, 0, 40, 40}}, {{0, 0, 0, 0}, {1, 1, 1, 1}, {0, 0, 0, 0}}, 5566 {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, nothing_todo, 5567 }; 5568 #undef nothing_todo 5569 5570 clsMain.style = CS_DBLCLKS; 5571 clsMain.lpfnWndProc = parentdc_window_procA; 5572 clsMain.cbClsExtra = 0; 5573 clsMain.cbWndExtra = 0; 5574 clsMain.hInstance = GetModuleHandleA(0); 5575 clsMain.hIcon = 0; 5576 clsMain.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 5577 clsMain.hbrBackground = GetStockObject(WHITE_BRUSH); 5578 clsMain.lpszMenuName = NULL; 5579 clsMain.lpszClassName = "ParentDcMainWindowClass"; 5580 5581 if(!RegisterClassA(&clsMain)) { 5582 trace("Register failed %d\n", GetLastError()); 5583 return; 5584 } 5585 5586 cls.style = CS_DBLCLKS | CS_PARENTDC; 5587 cls.lpfnWndProc = parentdc_window_procA; 5588 cls.cbClsExtra = 0; 5589 cls.cbWndExtra = 0; 5590 cls.hInstance = GetModuleHandleA(0); 5591 cls.hIcon = 0; 5592 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 5593 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 5594 cls.lpszMenuName = NULL; 5595 cls.lpszClassName = "ParentDcWindowClass"; 5596 5597 if(!RegisterClassA(&cls)) { 5598 trace("Register failed %d\n", GetLastError()); 5599 return; 5600 } 5601 5602 SetRect(&rc, 0, 0, 150, 150); 5603 AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0); 5604 hwndMain = CreateWindowA("ParentDcMainWindowClass", "Main Window", WS_OVERLAPPEDWINDOW, 5605 CW_USEDEFAULT, 0, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, 0, NULL); 5606 SetWindowLongPtrA(hwndMain, GWLP_USERDATA, (DWORD_PTR)&test_answer.main); 5607 hwnd1 = CreateWindowA("ParentDcWindowClass", "Child Window 1", WS_CHILD, 5608 20, 20, 40, 40, hwndMain, NULL, 0, NULL); 5609 SetWindowLongPtrA(hwnd1, GWLP_USERDATA, (DWORD_PTR)&test_answer.child1); 5610 hwnd2 = CreateWindowA("ParentDcWindowClass", "Child Window 2", WS_CHILD, 5611 40, 40, 40, 40, hwndMain, NULL, 0, NULL); 5612 SetWindowLongPtrA(hwnd2, GWLP_USERDATA, (DWORD_PTR)&test_answer.child2); 5613 ShowWindow(hwndMain, SW_SHOW); 5614 ShowWindow(hwnd1, SW_SHOW); 5615 ShowWindow(hwnd2, SW_SHOW); 5616 SetWindowPos(hwndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); 5617 flush_events( TRUE ); 5618 5619 zero_parentdc_test(&test_answer); 5620 InvalidateRect(hwndMain, NULL, TRUE); 5621 flush_events( TRUE ); 5622 parentdc_ok(test1, test_answer); 5623 5624 zero_parentdc_test(&test_answer); 5625 SetRect(&rc, 0, 0, 50, 50); 5626 InvalidateRect(hwndMain, &rc, TRUE); 5627 flush_events( TRUE ); 5628 parentdc_ok(test2, test_answer); 5629 5630 zero_parentdc_test(&test_answer); 5631 SetRect(&rc, 0, 0, 10, 10); 5632 InvalidateRect(hwndMain, &rc, TRUE); 5633 flush_events( TRUE ); 5634 parentdc_ok(test3, test_answer); 5635 5636 zero_parentdc_test(&test_answer); 5637 SetRect(&rc, 40, 40, 50, 50); 5638 InvalidateRect(hwndMain, &rc, TRUE); 5639 flush_events( TRUE ); 5640 parentdc_ok(test4, test_answer); 5641 5642 zero_parentdc_test(&test_answer); 5643 SetRect(&rc, 20, 20, 60, 60); 5644 InvalidateRect(hwndMain, &rc, TRUE); 5645 flush_events( TRUE ); 5646 parentdc_ok(test5, test_answer); 5647 5648 zero_parentdc_test(&test_answer); 5649 SetRect(&rc, 0, 0, 10, 10); 5650 InvalidateRect(hwnd1, &rc, TRUE); 5651 flush_events( TRUE ); 5652 parentdc_ok(test6, test_answer); 5653 5654 zero_parentdc_test(&test_answer); 5655 SetRect(&rc, -5, -5, 65, 65); 5656 InvalidateRect(hwnd1, &rc, TRUE); 5657 flush_events( TRUE ); 5658 parentdc_ok(test7, test_answer); 5659 5660 DestroyWindow(hwndMain); 5661 DestroyWindow(hwnd1); 5662 DestroyWindow(hwnd2); 5663 } 5664 5665 static LRESULT WINAPI def_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 5666 { 5667 return DefWindowProcA(hwnd, msg, wparam, lparam); 5668 } 5669 5670 static LRESULT WINAPI def_window_procW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 5671 { 5672 return DefWindowProcW(hwnd, msg, wparam, lparam); 5673 } 5674 5675 static void test_IsWindowUnicode(void) 5676 { 5677 static const char ansi_class_nameA[] = "ansi class name"; 5678 static const WCHAR ansi_class_nameW[] = {'a','n','s','i',' ','c','l','a','s','s',' ','n','a','m','e',0}; 5679 static const char unicode_class_nameA[] = "unicode class name"; 5680 static const WCHAR unicode_class_nameW[] = {'u','n','i','c','o','d','e',' ','c','l','a','s','s',' ','n','a','m','e',0}; 5681 WNDCLASSA classA; 5682 WNDCLASSW classW; 5683 HWND hwnd; 5684 ATOM atom; 5685 5686 memset(&classW, 0, sizeof(classW)); 5687 classW.hInstance = GetModuleHandleA(0); 5688 classW.lpfnWndProc = def_window_procW; 5689 classW.lpszClassName = unicode_class_nameW; 5690 if (!RegisterClassW(&classW)) return; /* this catches Win9x as well */ 5691 5692 memset(&classA, 0, sizeof(classA)); 5693 classA.hInstance = GetModuleHandleA(0); 5694 classA.lpfnWndProc = def_window_procA; 5695 classA.lpszClassName = ansi_class_nameA; 5696 atom = RegisterClassA(&classA); 5697 assert(atom); 5698 5699 /* unicode class: window proc */ 5700 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP, 5701 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5702 assert(hwnd); 5703 5704 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5705 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA); 5706 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5707 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW); 5708 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5709 5710 DestroyWindow(hwnd); 5711 5712 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP, 5713 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5714 assert(hwnd); 5715 5716 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5717 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA); 5718 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5719 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW); 5720 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5721 5722 DestroyWindow(hwnd); 5723 5724 /* ansi class: window proc */ 5725 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP, 5726 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5727 assert(hwnd); 5728 5729 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5730 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW); 5731 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5732 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA); 5733 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5734 5735 DestroyWindow(hwnd); 5736 5737 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP, 5738 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5739 assert(hwnd); 5740 5741 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5742 SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procW); 5743 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5744 SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (ULONG_PTR)def_window_procA); 5745 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5746 5747 DestroyWindow(hwnd); 5748 5749 /* unicode class: class proc */ 5750 hwnd = CreateWindowExW(0, unicode_class_nameW, NULL, WS_POPUP, 5751 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5752 assert(hwnd); 5753 5754 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5755 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA); 5756 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5757 /* do not restore class window proc back to unicode */ 5758 5759 DestroyWindow(hwnd); 5760 5761 hwnd = CreateWindowExA(0, unicode_class_nameA, NULL, WS_POPUP, 5762 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5763 assert(hwnd); 5764 5765 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5766 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW); 5767 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5768 5769 DestroyWindow(hwnd); 5770 5771 /* ansi class: class proc */ 5772 hwnd = CreateWindowExW(0, ansi_class_nameW, NULL, WS_POPUP, 5773 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5774 assert(hwnd); 5775 5776 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5777 SetClassLongPtrW(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procW); 5778 ok(!IsWindowUnicode(hwnd), "IsWindowUnicode expected to return FALSE\n"); 5779 /* do not restore class window proc back to ansi */ 5780 5781 DestroyWindow(hwnd); 5782 5783 hwnd = CreateWindowExA(0, ansi_class_nameA, NULL, WS_POPUP, 5784 0, 0, 100, 100, GetDesktopWindow(), 0, 0, NULL); 5785 assert(hwnd); 5786 5787 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5788 SetClassLongPtrA(hwnd, GCLP_WNDPROC, (ULONG_PTR)def_window_procA); 5789 ok(IsWindowUnicode(hwnd), "IsWindowUnicode expected to return TRUE\n"); 5790 5791 DestroyWindow(hwnd); 5792 } 5793 5794 static LRESULT CALLBACK minmax_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 5795 { 5796 MINMAXINFO *minmax; 5797 5798 if (msg != WM_GETMINMAXINFO) 5799 return DefWindowProcA(hwnd, msg, wp, lp); 5800 5801 minmax = (MINMAXINFO *)lp; 5802 5803 if ((GetWindowLongA(hwnd, GWL_STYLE) & WS_CHILD)) 5804 { 5805 minmax->ptReserved.x = 0; 5806 minmax->ptReserved.y = 0; 5807 minmax->ptMaxSize.x = 400; 5808 minmax->ptMaxSize.y = 400; 5809 minmax->ptMaxPosition.x = 300; 5810 minmax->ptMaxPosition.y = 300; 5811 minmax->ptMaxTrackSize.x = 200; 5812 minmax->ptMaxTrackSize.y = 200; 5813 minmax->ptMinTrackSize.x = 100; 5814 minmax->ptMinTrackSize.y = 100; 5815 } 5816 else 5817 DefWindowProcA(hwnd, msg, wp, lp); 5818 return 1; 5819 } 5820 5821 static int expected_cx, expected_cy; 5822 static RECT expected_rect, broken_rect; 5823 5824 static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 5825 { 5826 switch(msg) 5827 { 5828 case WM_GETMINMAXINFO: 5829 { 5830 RECT rect; 5831 GetWindowRect( hwnd, &rect ); 5832 ok( !rect.left && !rect.top && !rect.right && !rect.bottom, "wrong rect %s\n", 5833 wine_dbgstr_rect( &rect )); 5834 return DefWindowProcA(hwnd, msg, wp, lp); 5835 } 5836 case WM_NCCREATE: 5837 case WM_CREATE: 5838 { 5839 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp; 5840 RECT rect; 5841 GetWindowRect( hwnd, &rect ); 5842 trace( "hwnd %p msg %x size %dx%d rect %s\n", hwnd, msg, cs->cx, cs->cy, 5843 wine_dbgstr_rect( &rect )); 5844 ok( cs->cx == expected_cx || broken(cs->cx == (short)expected_cx), 5845 "wrong x size %d/%d\n", cs->cx, expected_cx ); 5846 ok( cs->cy == expected_cy || broken(cs->cy == (short)expected_cy), 5847 "wrong y size %d/%d\n", cs->cy, expected_cy ); 5848 ok( (rect.right - rect.left == expected_rect.right - expected_rect.left && 5849 rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) || 5850 (rect.right - rect.left == min( 65535, expected_rect.right - expected_rect.left ) && 5851 rect.bottom - rect.top == min( 65535, expected_rect.bottom - expected_rect.top )) || 5852 broken( rect.right - rect.left == broken_rect.right - broken_rect.left && 5853 rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) || 5854 broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left && 5855 rect.bottom - rect.top == (short)broken_rect.bottom - (short)broken_rect.top), 5856 "wrong rect %s / %s\n", wine_dbgstr_rect( &rect ), wine_dbgstr_rect( &expected_rect )); 5857 return DefWindowProcA(hwnd, msg, wp, lp); 5858 } 5859 case WM_NCCALCSIZE: 5860 { 5861 RECT rect, *r = (RECT *)lp; 5862 GetWindowRect( hwnd, &rect ); 5863 ok( EqualRect( &rect, r ), "passed rect %s doesn't match window rect %s\n", 5864 wine_dbgstr_rect( r ), wine_dbgstr_rect( &rect )); 5865 return DefWindowProcA(hwnd, msg, wp, lp); 5866 } 5867 default: 5868 return DefWindowProcA(hwnd, msg, wp, lp); 5869 } 5870 } 5871 5872 static void test_CreateWindow(void) 5873 { 5874 WNDCLASSA cls; 5875 HWND hwnd, parent; 5876 HMENU hmenu; 5877 RECT rc, rc_minmax; 5878 MINMAXINFO minmax; 5879 BOOL res; 5880 5881 #define expect_menu(window, menu) \ 5882 SetLastError(0xdeadbeef); \ 5883 res = (GetMenu(window) == (HMENU)menu); \ 5884 ok(res, "GetMenu error %d\n", GetLastError()) 5885 5886 #define expect_style(window, style)\ 5887 ok((ULONG)GetWindowLongA(window, GWL_STYLE) == (style), "expected style %x != %x\n", (LONG)(style), GetWindowLongA(window, GWL_STYLE)) 5888 5889 #define expect_ex_style(window, ex_style)\ 5890 ok((ULONG)GetWindowLongA(window, GWL_EXSTYLE) == (ex_style), "expected ex_style %x != %x\n", (LONG)(ex_style), GetWindowLongA(window, GWL_EXSTYLE)) 5891 5892 #define expect_gle_broken_9x(gle)\ 5893 ok(GetLastError() == gle ||\ 5894 broken(GetLastError() == 0xdeadbeef),\ 5895 "IsMenu set error %d\n", GetLastError()) 5896 5897 hmenu = CreateMenu(); 5898 assert(hmenu != 0); 5899 parent = GetDesktopWindow(); 5900 assert(parent != 0); 5901 5902 SetLastError(0xdeadbeef); 5903 res = IsMenu(hmenu); 5904 ok(res, "IsMenu error %d\n", GetLastError()); 5905 5906 /* WS_CHILD */ 5907 SetLastError(0xdeadbeef); 5908 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD, 5909 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 5910 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5911 expect_menu(hwnd, 1); 5912 expect_style(hwnd, WS_CHILD); 5913 expect_ex_style(hwnd, WS_EX_APPWINDOW); 5914 DestroyWindow(hwnd); 5915 5916 SetLastError(0xdeadbeef); 5917 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_CAPTION, 5918 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 5919 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5920 expect_menu(hwnd, 1); 5921 expect_style(hwnd, WS_CHILD | WS_CAPTION); 5922 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); 5923 DestroyWindow(hwnd); 5924 5925 SetLastError(0xdeadbeef); 5926 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 5927 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 5928 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5929 expect_menu(hwnd, 1); 5930 expect_style(hwnd, WS_CHILD); 5931 expect_ex_style(hwnd, 0); 5932 DestroyWindow(hwnd); 5933 5934 SetLastError(0xdeadbeef); 5935 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_CAPTION, 5936 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 5937 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5938 expect_menu(hwnd, 1); 5939 expect_style(hwnd, WS_CHILD | WS_CAPTION); 5940 expect_ex_style(hwnd, WS_EX_WINDOWEDGE); 5941 DestroyWindow(hwnd); 5942 5943 /* WS_POPUP */ 5944 SetLastError(0xdeadbeef); 5945 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP, 5946 0, 0, 100, 100, parent, hmenu, 0, NULL); 5947 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5948 expect_menu(hwnd, hmenu); 5949 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS); 5950 expect_ex_style(hwnd, WS_EX_APPWINDOW); 5951 DestroyWindow(hwnd); 5952 SetLastError(0xdeadbeef); 5953 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 5954 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 5955 5956 hmenu = CreateMenu(); 5957 assert(hmenu != 0); 5958 SetLastError(0xdeadbeef); 5959 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP | WS_CAPTION, 5960 0, 0, 100, 100, parent, hmenu, 0, NULL); 5961 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5962 expect_menu(hwnd, hmenu); 5963 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS); 5964 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); 5965 DestroyWindow(hwnd); 5966 SetLastError(0xdeadbeef); 5967 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 5968 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 5969 5970 hmenu = CreateMenu(); 5971 assert(hmenu != 0); 5972 SetLastError(0xdeadbeef); 5973 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 5974 0, 0, 100, 100, parent, hmenu, 0, NULL); 5975 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5976 expect_menu(hwnd, hmenu); 5977 expect_style(hwnd, WS_POPUP | WS_CLIPSIBLINGS); 5978 expect_ex_style(hwnd, 0); 5979 DestroyWindow(hwnd); 5980 SetLastError(0xdeadbeef); 5981 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 5982 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 5983 5984 hmenu = CreateMenu(); 5985 assert(hmenu != 0); 5986 SetLastError(0xdeadbeef); 5987 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_CAPTION, 5988 0, 0, 100, 100, parent, hmenu, 0, NULL); 5989 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 5990 expect_menu(hwnd, hmenu); 5991 expect_style(hwnd, WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS); 5992 expect_ex_style(hwnd, WS_EX_WINDOWEDGE); 5993 DestroyWindow(hwnd); 5994 SetLastError(0xdeadbeef); 5995 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 5996 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 5997 5998 /* WS_CHILD | WS_POPUP */ 5999 SetLastError(0xdeadbeef); 6000 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP, 6001 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 6002 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); 6003 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6004 if (hwnd) 6005 DestroyWindow(hwnd); 6006 6007 hmenu = CreateMenu(); 6008 assert(hmenu != 0); 6009 SetLastError(0xdeadbeef); 6010 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP, 6011 0, 0, 100, 100, parent, hmenu, 0, NULL); 6012 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 6013 expect_menu(hwnd, hmenu); 6014 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS); 6015 expect_ex_style(hwnd, WS_EX_APPWINDOW); 6016 DestroyWindow(hwnd); 6017 SetLastError(0xdeadbeef); 6018 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 6019 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6020 6021 SetLastError(0xdeadbeef); 6022 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 6023 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 6024 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); 6025 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6026 if (hwnd) 6027 DestroyWindow(hwnd); 6028 6029 hmenu = CreateMenu(); 6030 assert(hmenu != 0); 6031 SetLastError(0xdeadbeef); 6032 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 6033 0, 0, 100, 100, parent, hmenu, 0, NULL); 6034 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 6035 expect_menu(hwnd, hmenu); 6036 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS); 6037 expect_ex_style(hwnd, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE); 6038 DestroyWindow(hwnd); 6039 SetLastError(0xdeadbeef); 6040 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 6041 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6042 6043 SetLastError(0xdeadbeef); 6044 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP, 6045 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 6046 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); 6047 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6048 if (hwnd) 6049 DestroyWindow(hwnd); 6050 6051 hmenu = CreateMenu(); 6052 assert(hmenu != 0); 6053 SetLastError(0xdeadbeef); 6054 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP, 6055 0, 0, 100, 100, parent, hmenu, 0, NULL); 6056 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 6057 expect_menu(hwnd, hmenu); 6058 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CLIPSIBLINGS); 6059 expect_ex_style(hwnd, 0); 6060 DestroyWindow(hwnd); 6061 SetLastError(0xdeadbeef); 6062 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 6063 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6064 6065 SetLastError(0xdeadbeef); 6066 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 6067 0, 0, 100, 100, parent, (HMENU)1, 0, NULL); 6068 ok(!hwnd || broken(hwnd != 0 /* Win9x */), "CreateWindowEx should fail\n"); 6069 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6070 if (hwnd) 6071 DestroyWindow(hwnd); 6072 6073 hmenu = CreateMenu(); 6074 assert(hmenu != 0); 6075 SetLastError(0xdeadbeef); 6076 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD | WS_POPUP | WS_CAPTION, 6077 0, 0, 100, 100, parent, hmenu, 0, NULL); 6078 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 6079 expect_menu(hwnd, hmenu); 6080 expect_style(hwnd, WS_CHILD | WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS); 6081 expect_ex_style(hwnd, WS_EX_WINDOWEDGE); 6082 DestroyWindow(hwnd); 6083 SetLastError(0xdeadbeef); 6084 ok(!IsMenu(hmenu), "IsMenu should fail\n"); 6085 expect_gle_broken_9x(ERROR_INVALID_MENU_HANDLE); 6086 6087 /* test child window sizing */ 6088 cls.style = 0; 6089 cls.lpfnWndProc = minmax_wnd_proc; 6090 cls.cbClsExtra = 0; 6091 cls.cbWndExtra = 0; 6092 cls.hInstance = GetModuleHandleA(NULL); 6093 cls.hIcon = 0; 6094 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 6095 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 6096 cls.lpszMenuName = NULL; 6097 cls.lpszClassName = "MinMax_WndClass"; 6098 RegisterClassA(&cls); 6099 6100 SetLastError(0xdeadbeef); 6101 parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, 6102 0, 0, 100, 100, 0, 0, 0, NULL); 6103 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError()); 6104 expect_menu(parent, 0); 6105 expect_style(parent, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_CLIPSIBLINGS); 6106 expect_ex_style(parent, WS_EX_WINDOWEDGE); 6107 6108 memset(&minmax, 0, sizeof(minmax)); 6109 SendMessageA(parent, WM_GETMINMAXINFO, 0, (LPARAM)&minmax); 6110 SetRect(&rc_minmax, 0, 0, minmax.ptMaxSize.x, minmax.ptMaxSize.y); 6111 ok(IsRectEmpty(&rc_minmax), "ptMaxSize is not empty\n"); 6112 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y); 6113 ok(IsRectEmpty(&rc_minmax), "ptMaxTrackSize is not empty\n"); 6114 6115 GetWindowRect(parent, &rc); 6116 ok(!IsRectEmpty(&rc), "parent window rect is empty\n"); 6117 GetClientRect(parent, &rc); 6118 ok(!IsRectEmpty(&rc), "parent client rect is empty\n"); 6119 6120 InflateRect(&rc, 200, 200); 6121 trace("creating child with rect %s\n", wine_dbgstr_rect(&rc)); 6122 6123 SetLastError(0xdeadbeef); 6124 hwnd = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, 6125 rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 6126 parent, (HMENU)1, 0, NULL); 6127 ok(hwnd != 0, "CreateWindowEx error %d\n", GetLastError()); 6128 expect_menu(hwnd, 1); 6129 expect_style(hwnd, WS_CHILD | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME); 6130 expect_ex_style(hwnd, WS_EX_WINDOWEDGE); 6131 6132 memset(&minmax, 0, sizeof(minmax)); 6133 SendMessageA(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax); 6134 SetRect(&rc_minmax, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y); 6135 6136 GetWindowRect(hwnd, &rc); 6137 OffsetRect(&rc, -rc.left, -rc.top); 6138 ok(EqualRect(&rc, &rc_minmax), "rects don't match: %s and %s\n", wine_dbgstr_rect(&rc), 6139 wine_dbgstr_rect(&rc_minmax)); 6140 DestroyWindow(hwnd); 6141 6142 cls.lpfnWndProc = winsizes_wnd_proc; 6143 cls.lpszClassName = "Sizes_WndClass"; 6144 RegisterClassA(&cls); 6145 6146 expected_cx = expected_cy = 200000; 6147 SetRect( &expected_rect, 0, 0, 200000, 200000 ); 6148 broken_rect = expected_rect; 6149 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL); 6150 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6151 GetClientRect( hwnd, &rc ); 6152 ok( rc.right == 200000 || rc.right == 65535 || broken(rc.right == (short)200000), 6153 "invalid rect right %u\n", rc.right ); 6154 ok( rc.bottom == 200000 || rc.bottom == 65535 || broken(rc.bottom == (short)200000), 6155 "invalid rect bottom %u\n", rc.bottom ); 6156 DestroyWindow(hwnd); 6157 6158 expected_cx = expected_cy = -10; 6159 SetRectEmpty(&expected_rect); 6160 SetRect( &broken_rect, 0, 0, -10, -10 ); 6161 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -20, -20, -10, -10, parent, 0, 0, NULL); 6162 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6163 GetClientRect( hwnd, &rc ); 6164 ok( rc.right == 0, "invalid rect right %u\n", rc.right ); 6165 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom ); 6166 DestroyWindow(hwnd); 6167 6168 expected_cx = expected_cy = -200000; 6169 SetRectEmpty(&expected_rect); 6170 SetRect( &broken_rect, 0, 0, -200000, -200000 ); 6171 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, -300000, -300000, -200000, -200000, parent, 0, 0, NULL); 6172 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6173 GetClientRect( hwnd, &rc ); 6174 ok( rc.right == 0, "invalid rect right %u\n", rc.right ); 6175 ok( rc.bottom == 0, "invalid rect bottom %u\n", rc.bottom ); 6176 DestroyWindow(hwnd); 6177 6178 /* we need a parent at 0,0 so that child coordinates match */ 6179 DestroyWindow(parent); 6180 parent = CreateWindowExA(0, "MinMax_WndClass", NULL, WS_POPUP, 0, 0, 100, 100, 0, 0, 0, NULL); 6181 ok(parent != 0, "CreateWindowEx error %d\n", GetLastError()); 6182 6183 expected_cx = 100; 6184 expected_cy = 0x7fffffff; 6185 SetRect( &expected_rect, 10, 10, 110, 0x7fffffff ); 6186 SetRect( &broken_rect, 10, 10, 110, 0x7fffffffU + 10 ); 6187 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 10, 10, 100, 0x7fffffff, parent, 0, 0, NULL); 6188 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6189 GetClientRect( hwnd, &rc ); 6190 ok( rc.right == 100, "invalid rect right %u\n", rc.right ); 6191 ok( rc.bottom == 0x7fffffff - 10 || rc.bottom ==65535 || broken(rc.bottom == 0), 6192 "invalid rect bottom %u\n", rc.bottom ); 6193 DestroyWindow(hwnd); 6194 6195 expected_cx = 0x7fffffff; 6196 expected_cy = 0x7fffffff; 6197 SetRect( &expected_rect, 20, 10, 0x7fffffff, 0x7fffffff ); 6198 SetRect( &broken_rect, 20, 10, 0x7fffffffU + 20, 0x7fffffffU + 10 ); 6199 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL); 6200 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6201 GetClientRect( hwnd, &rc ); 6202 ok( rc.right == 0x7fffffff - 20 || rc.right == 65535 || broken(rc.right == 0), 6203 "invalid rect right %u\n", rc.right ); 6204 ok( rc.bottom == 0x7fffffff - 10 || rc.right == 65535 || broken(rc.bottom == 0), 6205 "invalid rect bottom %u\n", rc.bottom ); 6206 DestroyWindow(hwnd); 6207 6208 /* top level window */ 6209 expected_cx = expected_cy = 200000; 6210 SetRect( &expected_rect, 0, 0, GetSystemMetrics(SM_CXMAXTRACK), GetSystemMetrics(SM_CYMAXTRACK) ); 6211 hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_OVERLAPPEDWINDOW, 300000, 300000, 200000, 200000, 0, 0, 0, NULL); 6212 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6213 GetClientRect( hwnd, &rc ); 6214 ok( rc.right <= expected_cx, "invalid rect right %u\n", rc.right ); 6215 ok( rc.bottom <= expected_cy, "invalid rect bottom %u\n", rc.bottom ); 6216 DestroyWindow(hwnd); 6217 6218 if (pGetLayout && pSetLayout) 6219 { 6220 HDC hdc = GetDC( parent ); 6221 pSetLayout( hdc, LAYOUT_RTL ); 6222 if (pGetLayout( hdc )) 6223 { 6224 ReleaseDC( parent, hdc ); 6225 DestroyWindow( parent ); 6226 SetLastError( 0xdeadbeef ); 6227 parent = CreateWindowExA(WS_EX_APPWINDOW | WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 6228 0, 0, 100, 100, 0, 0, 0, NULL); 6229 ok( parent != 0, "creation failed err %u\n", GetLastError()); 6230 expect_ex_style( parent, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL ); 6231 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL); 6232 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6233 expect_ex_style( hwnd, WS_EX_LAYOUTRTL ); 6234 DestroyWindow( hwnd ); 6235 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 20, 20, parent, 0, 0, NULL); 6236 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6237 expect_ex_style( hwnd, 0 ); 6238 DestroyWindow( hwnd ); 6239 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT ); 6240 hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL); 6241 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6242 expect_ex_style( hwnd, 0 ); 6243 DestroyWindow( hwnd ); 6244 6245 if (pGetProcessDefaultLayout && pSetProcessDefaultLayout) 6246 { 6247 DWORD layout; 6248 6249 SetLastError( 0xdeadbeef ); 6250 ok( !pGetProcessDefaultLayout( NULL ), "GetProcessDefaultLayout succeeded\n" ); 6251 ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() ); 6252 SetLastError( 0xdeadbeef ); 6253 res = pGetProcessDefaultLayout( &layout ); 6254 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ()); 6255 ok( layout == 0, "GetProcessDefaultLayout wrong layout %x\n", layout ); 6256 SetLastError( 0xdeadbeef ); 6257 res = pSetProcessDefaultLayout( 7 ); 6258 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ()); 6259 res = pGetProcessDefaultLayout( &layout ); 6260 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ()); 6261 ok( layout == 7, "GetProcessDefaultLayout wrong layout %x\n", layout ); 6262 SetLastError( 0xdeadbeef ); 6263 res = pSetProcessDefaultLayout( LAYOUT_RTL ); 6264 ok( res, "SetProcessDefaultLayout failed err %u\n", GetLastError ()); 6265 res = pGetProcessDefaultLayout( &layout ); 6266 ok( res, "GetProcessDefaultLayout failed err %u\n", GetLastError ()); 6267 ok( layout == LAYOUT_RTL, "GetProcessDefaultLayout wrong layout %x\n", layout ); 6268 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP, 6269 0, 0, 100, 100, 0, 0, 0, NULL); 6270 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6271 expect_ex_style( hwnd, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL ); 6272 DestroyWindow( hwnd ); 6273 hwnd = CreateWindowExA(WS_EX_APPWINDOW, "static", NULL, WS_POPUP, 6274 0, 0, 100, 100, parent, 0, 0, NULL); 6275 ok( hwnd != 0, "creation failed err %u\n", GetLastError()); 6276 expect_ex_style( hwnd, WS_EX_APPWINDOW ); 6277 DestroyWindow( hwnd ); 6278 pSetProcessDefaultLayout( 0 ); 6279 } 6280 else win_skip( "SetProcessDefaultLayout not supported\n" ); 6281 } 6282 else win_skip( "SetLayout not supported\n" ); 6283 } 6284 else win_skip( "SetLayout not available\n" ); 6285 6286 DestroyWindow(parent); 6287 6288 UnregisterClassA("MinMax_WndClass", GetModuleHandleA(NULL)); 6289 UnregisterClassA("Sizes_WndClass", GetModuleHandleA(NULL)); 6290 6291 #undef expect_gle_broken_9x 6292 #undef expect_menu 6293 #undef expect_style 6294 #undef expect_ex_style 6295 } 6296 6297 /* function that remembers whether the system the test is running on sets the 6298 * last error for user32 functions to make the tests stricter */ 6299 static int check_error(DWORD actual, DWORD expected) 6300 { 6301 static int sets_last_error = -1; 6302 if (sets_last_error == -1) 6303 sets_last_error = (actual != 0xdeadbeef); 6304 return (!sets_last_error && (actual == 0xdeadbeef)) || (actual == expected); 6305 } 6306 6307 static void test_SetWindowLong(void) 6308 { 6309 LONG_PTR retval; 6310 WNDPROC old_window_procW; 6311 6312 SetLastError(0xdeadbeef); 6313 retval = SetWindowLongPtrA(NULL, GWLP_WNDPROC, 0); 6314 ok(!retval, "SetWindowLongPtr on invalid window handle should have returned 0 instead of 0x%lx\n", retval); 6315 ok(check_error(GetLastError(), ERROR_INVALID_WINDOW_HANDLE), 6316 "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instead of %d\n", GetLastError()); 6317 6318 SetLastError(0xdeadbeef); 6319 retval = SetWindowLongPtrA(hwndMain, 0xdeadbeef, 0); 6320 ok(!retval, "SetWindowLongPtr on invalid index should have returned 0 instead of 0x%lx\n", retval); 6321 ok(check_error(GetLastError(), ERROR_INVALID_INDEX), 6322 "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instead of %d\n", GetLastError()); 6323 6324 SetLastError(0xdeadbeef); 6325 retval = SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0); 6326 ok((WNDPROC)retval == main_window_procA || broken(!retval), /* win9x */ 6327 "SetWindowLongPtr on invalid window proc should have returned address of main_window_procA instead of 0x%lx\n", retval); 6328 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError()); 6329 retval = GetWindowLongPtrA(hwndMain, GWLP_WNDPROC); 6330 ok((WNDPROC)retval == main_window_procA, 6331 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval); 6332 ok(!IsWindowUnicode(hwndMain), "hwndMain shouldn't be Unicode\n"); 6333 6334 old_window_procW = (WNDPROC)GetWindowLongPtrW(hwndMain, GWLP_WNDPROC); 6335 SetLastError(0xdeadbeef); 6336 retval = SetWindowLongPtrW(hwndMain, GWLP_WNDPROC, 0); 6337 if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) 6338 { 6339 ok(GetLastError() == 0xdeadbeef, "SetWindowLongPtr shouldn't have set the last error, instead of setting it to %d\n", GetLastError()); 6340 ok(retval != 0, "SetWindowLongPtr error %d\n", GetLastError()); 6341 ok((WNDPROC)retval == old_window_procW, 6342 "SetWindowLongPtr on invalid window proc shouldn't have changed the value returned by GetWindowLongPtr, instead of changing it to 0x%lx\n", retval); 6343 ok(IsWindowUnicode(hwndMain), "hwndMain should now be Unicode\n"); 6344 6345 /* set it back to ANSI */ 6346 SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0); 6347 } 6348 } 6349 6350 static LRESULT WINAPI check_style_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 6351 { 6352 const STYLESTRUCT *expected = (STYLESTRUCT *)GetWindowLongPtrA(hwnd, GWLP_USERDATA); 6353 const STYLESTRUCT *got = (STYLESTRUCT *)lParam; 6354 6355 if (message == WM_STYLECHANGING && wParam == GWL_STYLE) 6356 { 6357 ok(got->styleOld == expected[0].styleOld, "expected old style %#x, got %#x\n", 6358 expected[0].styleOld, got->styleOld); 6359 ok(got->styleNew == expected[0].styleNew, "expected new style %#x, got %#x\n", 6360 expected[0].styleNew, got->styleNew); 6361 } 6362 else if (message == WM_STYLECHANGED && wParam == GWL_STYLE) 6363 { 6364 ok(got->styleOld == expected[1].styleOld, "expected old style %#x, got %#x\n", 6365 expected[1].styleOld, got->styleOld); 6366 ok(got->styleNew == expected[1].styleNew, "expected new style %#x, got %#x\n", 6367 expected[1].styleNew, got->styleNew); 6368 } 6369 6370 return DefWindowProcA(hwnd, message, wParam, lParam); 6371 } 6372 6373 static void test_set_window_style(void) 6374 { 6375 LONG expected_style, new_style, old_style; 6376 STYLESTRUCT expected_stylestruct[2]; 6377 unsigned int i; 6378 WNDCLASSA cls; 6379 HWND hwnd; 6380 6381 static const struct 6382 { 6383 LONG creation_style; 6384 LONG style; 6385 } 6386 tests[] = 6387 { 6388 { WS_MINIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 6389 WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX }, 6390 { WS_MINIMIZE | WS_CLIPSIBLINGS | WS_CAPTION, 6391 WS_CLIPSIBLINGS | WS_CAPTION }, 6392 { WS_MAXIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 6393 WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX }, 6394 { WS_MAXIMIZE | WS_CLIPSIBLINGS | WS_CAPTION, 6395 WS_CLIPSIBLINGS | WS_CAPTION }, 6396 { WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 6397 WS_MINIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX }, 6398 { WS_CLIPSIBLINGS | WS_CAPTION, 6399 WS_MINIMIZE | WS_CLIPSIBLINGS | WS_CAPTION }, 6400 { WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 6401 WS_MAXIMIZE | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX }, 6402 { WS_CLIPSIBLINGS | WS_CAPTION, 6403 WS_MAXIMIZE | WS_CLIPSIBLINGS | WS_CAPTION }, 6404 }; 6405 6406 memset(&cls, 0, sizeof(cls)); 6407 cls.lpfnWndProc = check_style_wnd_proc; 6408 cls.hInstance = GetModuleHandleA(0); 6409 cls.lpszClassName = "TestSetWindowStylesClass"; 6410 ok(RegisterClassA(&cls), "RegisterClass failed\n"); 6411 6412 for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) 6413 { 6414 expected_style = tests[i].style; 6415 if (tests[i].creation_style & WS_MINIMIZE) 6416 expected_style |= WS_MINIMIZE; 6417 6418 expected_stylestruct[0].styleOld = tests[i].creation_style; 6419 expected_stylestruct[0].styleNew = tests[i].style; 6420 expected_stylestruct[1].styleOld = tests[i].creation_style; 6421 expected_stylestruct[1].styleNew = expected_style; 6422 6423 hwnd = CreateWindowA(cls.lpszClassName, "Test set styles", 6424 tests[i].creation_style, 100, 100, 200, 200, 0, 0, 0, NULL); 6425 ok(hwnd != 0, "CreateWindow failed\n"); 6426 SetWindowLongPtrA(hwnd, GWLP_USERDATA, (LONG_PTR)&expected_stylestruct); 6427 6428 old_style = SetWindowLongA(hwnd, GWL_STYLE, tests[i].style); 6429 ok(old_style == tests[i].creation_style, "expected old style %#x, got %#x\n", 6430 tests[i].creation_style, old_style); 6431 new_style = GetWindowLongA(hwnd, GWL_STYLE); 6432 ok(new_style == expected_style, "expected new style %#x, got %#x\n", 6433 expected_style, new_style); 6434 6435 SetWindowLongPtrA(hwnd, GWLP_USERDATA, 0); 6436 DestroyWindow(hwnd); 6437 } 6438 6439 UnregisterClassA(cls.lpszClassName, cls.hInstance); 6440 } 6441 6442 static void test_ShowWindow(void) 6443 { 6444 HWND hwnd; 6445 DWORD style; 6446 RECT rcMain, rc, rcMinimized; 6447 LPARAM ret; 6448 6449 SetRect(&rcMain, 120, 120, 210, 210); 6450 6451 hwnd = CreateWindowExA(0, "MainWindowClass", NULL, 6452 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 6453 WS_MAXIMIZEBOX | WS_POPUP, 6454 rcMain.left, rcMain.top, 6455 rcMain.right - rcMain.left, rcMain.bottom - rcMain.top, 6456 0, 0, 0, NULL); 6457 assert(hwnd); 6458 6459 style = GetWindowLongA(hwnd, GWL_STYLE); 6460 ok(!(style & WS_DISABLED), "window should not be disabled\n"); 6461 ok(!(style & WS_VISIBLE), "window should not be visible\n"); 6462 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6463 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6464 GetWindowRect(hwnd, &rc); 6465 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6466 wine_dbgstr_rect(&rc)); 6467 6468 ret = ShowWindow(hwnd, SW_SHOW); 6469 ok(!ret, "not expected ret: %lu\n", ret); 6470 style = GetWindowLongA(hwnd, GWL_STYLE); 6471 ok(!(style & WS_DISABLED), "window should not be disabled\n"); 6472 ok(style & WS_VISIBLE, "window should be visible\n"); 6473 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6474 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6475 GetWindowRect(hwnd, &rc); 6476 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6477 wine_dbgstr_rect(&rc)); 6478 6479 ret = ShowWindow(hwnd, SW_MINIMIZE); 6480 ok(ret, "not expected ret: %lu\n", ret); 6481 style = GetWindowLongA(hwnd, GWL_STYLE); 6482 ok(!(style & WS_DISABLED), "window should not be disabled\n"); 6483 ok(style & WS_VISIBLE, "window should be visible\n"); 6484 ok(style & WS_MINIMIZE, "window should be minimized\n"); 6485 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6486 GetWindowRect(hwnd, &rcMinimized); 6487 ok(!EqualRect(&rcMain, &rcMinimized), "rects shouldn't match\n"); 6488 /* shouldn't be able to resize minimized windows */ 6489 ret = SetWindowPos(hwnd, 0, 0, 0, 6490 (rcMinimized.right - rcMinimized.left) * 2, 6491 (rcMinimized.bottom - rcMinimized.top) * 2, 6492 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); 6493 ok(ret, "not expected ret: %lu\n", ret); 6494 GetWindowRect(hwnd, &rc); 6495 ok(EqualRect(&rc, &rcMinimized), "rects should match\n"); 6496 6497 ShowWindow(hwnd, SW_RESTORE); 6498 ok(ret, "not expected ret: %lu\n", ret); 6499 style = GetWindowLongA(hwnd, GWL_STYLE); 6500 ok(!(style & WS_DISABLED), "window should not be disabled\n"); 6501 ok(style & WS_VISIBLE, "window should be visible\n"); 6502 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6503 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6504 GetWindowRect(hwnd, &rc); 6505 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6506 wine_dbgstr_rect(&rc)); 6507 6508 ret = EnableWindow(hwnd, FALSE); 6509 ok(!ret, "not expected ret: %lu\n", ret); 6510 style = GetWindowLongA(hwnd, GWL_STYLE); 6511 ok(style & WS_DISABLED, "window should be disabled\n"); 6512 6513 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); 6514 ok(!ret, "not expected ret: %lu\n", ret); 6515 style = GetWindowLongA(hwnd, GWL_STYLE); 6516 ok(style & WS_DISABLED, "window should be disabled\n"); 6517 ok(style & WS_VISIBLE, "window should be visible\n"); 6518 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6519 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6520 GetWindowRect(hwnd, &rc); 6521 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6522 wine_dbgstr_rect(&rc)); 6523 6524 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); 6525 ok(!ret, "not expected ret: %lu\n", ret); 6526 style = GetWindowLongA(hwnd, GWL_STYLE); 6527 ok(style & WS_DISABLED, "window should be disabled\n"); 6528 ok(style & WS_VISIBLE, "window should be visible\n"); 6529 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6530 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6531 GetWindowRect(hwnd, &rc); 6532 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6533 wine_dbgstr_rect(&rc)); 6534 6535 ret = ShowWindow(hwnd, SW_MINIMIZE); 6536 ok(ret, "not expected ret: %lu\n", ret); 6537 style = GetWindowLongA(hwnd, GWL_STYLE); 6538 ok(style & WS_DISABLED, "window should be disabled\n"); 6539 ok(style & WS_VISIBLE, "window should be visible\n"); 6540 ok(style & WS_MINIMIZE, "window should be minimized\n"); 6541 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6542 GetWindowRect(hwnd, &rc); 6543 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n"); 6544 6545 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); 6546 ok(!ret, "not expected ret: %lu\n", ret); 6547 style = GetWindowLongA(hwnd, GWL_STYLE); 6548 ok(style & WS_DISABLED, "window should be disabled\n"); 6549 ok(style & WS_VISIBLE, "window should be visible\n"); 6550 ok(style & WS_MINIMIZE, "window should be minimized\n"); 6551 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6552 GetWindowRect(hwnd, &rc); 6553 ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n"); 6554 6555 ret = ShowWindow(hwnd, SW_RESTORE); 6556 ok(ret, "not expected ret: %lu\n", ret); 6557 style = GetWindowLongA(hwnd, GWL_STYLE); 6558 ok(style & WS_DISABLED, "window should be disabled\n"); 6559 ok(style & WS_VISIBLE, "window should be visible\n"); 6560 ok(!(style & WS_MINIMIZE), "window should not be minimized\n"); 6561 ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); 6562 GetWindowRect(hwnd, &rc); 6563 ok(EqualRect(&rcMain, &rc), "expected %s, got %s\n", wine_dbgstr_rect(&rcMain), 6564 wine_dbgstr_rect(&rc)); 6565 6566 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); 6567 ok(!ret, "not expected ret: %lu\n", ret); 6568 ok(IsWindow(hwnd), "window should exist\n"); 6569 6570 ret = EnableWindow(hwnd, TRUE); 6571 ok(ret, "not expected ret: %lu\n", ret); 6572 6573 ret = DefWindowProcA(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); 6574 ok(!ret, "not expected ret: %lu\n", ret); 6575 ok(!IsWindow(hwnd), "window should not exist\n"); 6576 } 6577 6578 static DWORD CALLBACK gettext_msg_thread( LPVOID arg ) 6579 { 6580 HWND hwnd = arg; 6581 char buf[32]; 6582 INT buf_len; 6583 6584 /* test GetWindowTextA */ 6585 num_gettext_msgs = 0; 6586 memset( buf, 0, sizeof(buf) ); 6587 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6588 ok( buf_len != 0, "expected a nonempty window text\n" ); 6589 ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf ); 6590 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6591 6592 return 0; 6593 } 6594 6595 static DWORD CALLBACK settext_msg_thread( LPVOID arg ) 6596 { 6597 HWND hwnd = arg; 6598 BOOL success; 6599 6600 /* test SetWindowTextA */ 6601 num_settext_msgs = 0; 6602 success = SetWindowTextA( hwnd, "thread_caption" ); 6603 ok( success, "SetWindowTextA failed\n" ); 6604 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs ); 6605 6606 return 0; 6607 } 6608 6609 static void test_gettext(void) 6610 { 6611 DWORD tid, num_msgs; 6612 WCHAR bufW[32]; 6613 HANDLE thread; 6614 BOOL success; 6615 char buf[32]; 6616 INT buf_len; 6617 HWND hwnd, hwnd2; 6618 LRESULT r; 6619 MSG msg; 6620 6621 hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL ); 6622 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 6623 6624 /* test GetWindowTextA */ 6625 num_gettext_msgs = 0; 6626 memset( buf, 0, sizeof(buf) ); 6627 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6628 ok( buf_len != 0, "expected a nonempty window text\n" ); 6629 ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf ); 6630 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6631 6632 /* other process window */ 6633 strcpy( buf, "a" ); 6634 buf_len = GetWindowTextA( GetDesktopWindow(), buf, sizeof(buf) ); 6635 ok( buf_len == 0, "expected a nonempty window text\n" ); 6636 ok( *buf == 0, "got wrong window text '%s'\n", buf ); 6637 6638 strcpy( buf, "blah" ); 6639 buf_len = GetWindowTextA( GetDesktopWindow(), buf, 0 ); 6640 ok( buf_len == 0, "expected a nonempty window text\n" ); 6641 ok( !strcmp(buf, "blah"), "got wrong window text '%s'\n", buf ); 6642 6643 bufW[0] = 0xcc; 6644 buf_len = GetWindowTextW( GetDesktopWindow(), bufW, 0 ); 6645 ok( buf_len == 0, "expected a nonempty window text\n" ); 6646 ok( bufW[0] == 0xcc, "got %x\n", bufW[0] ); 6647 6648 g_wm_gettext_override.enabled = TRUE; 6649 6650 num_gettext_msgs = 0; 6651 memset( buf, 0xcc, sizeof(buf) ); 6652 g_wm_gettext_override.buff = buf; 6653 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6654 ok( buf_len == 0, "got %d\n", buf_len ); 6655 ok( *buf == 0, "got %x\n", *buf ); 6656 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6657 6658 num_gettext_msgs = 0; 6659 strcpy( buf, "blah" ); 6660 g_wm_gettext_override.buff = buf; 6661 buf_len = GetWindowTextA( hwnd, buf, 0 ); 6662 ok( buf_len == 0, "got %d\n", buf_len ); 6663 ok( !strcmp(buf, "blah"), "got %s\n", buf ); 6664 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6665 6666 g_wm_gettext_override.enabled = FALSE; 6667 6668 /* same for W window */ 6669 hwnd2 = CreateWindowExW( 0, mainclassW, NULL, WS_POPUP, 0, 0, 0, 0, 0, 0, 0, NULL ); 6670 ok( hwnd2 != 0, "CreateWindowExA error %d\n", GetLastError() ); 6671 6672 g_wm_gettext_override.enabled = TRUE; 6673 6674 num_gettext_msgs = 0; 6675 memset( bufW, 0xcc, sizeof(bufW) ); 6676 g_wm_gettext_override.buffW = bufW; 6677 buf_len = GetWindowTextW( hwnd2, bufW, sizeof(bufW)/sizeof(WCHAR) ); 6678 ok( buf_len == 0, "got %d\n", buf_len ); 6679 ok( *bufW == 0, "got %x\n", *bufW ); 6680 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6681 6682 num_gettext_msgs = 0; 6683 memset( bufW, 0xcc, sizeof(bufW) ); 6684 g_wm_gettext_override.buffW = bufW; 6685 buf_len = GetWindowTextW( hwnd2, bufW, 0 ); 6686 ok( buf_len == 0, "got %d\n", buf_len ); 6687 ok( *bufW == 0xcccc, "got %x\n", *bufW ); 6688 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6689 6690 g_wm_gettext_override.enabled = FALSE; 6691 6692 DestroyWindow( hwnd2 ); 6693 6694 /* test WM_GETTEXT */ 6695 num_gettext_msgs = 0; 6696 memset( buf, 0, sizeof(buf) ); 6697 r = SendMessageA( hwnd, WM_GETTEXT, sizeof(buf), (LONG_PTR)buf ); 6698 ok( r != 0, "expected a nonempty window text\n" ); 6699 ok( !strcmp(buf, "caption"), "got wrong window text '%s'\n", buf ); 6700 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6701 6702 /* test SetWindowTextA */ 6703 num_settext_msgs = 0; 6704 success = SetWindowTextA( hwnd, "new_caption" ); 6705 ok( success, "SetWindowTextA failed\n" ); 6706 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs ); 6707 6708 num_gettext_msgs = 0; 6709 memset( buf, 0, sizeof(buf) ); 6710 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6711 ok( buf_len != 0, "expected a nonempty window text\n" ); 6712 ok( !strcmp(buf, "new_caption"), "got wrong window text '%s'\n", buf ); 6713 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6714 6715 /* test WM_SETTEXT */ 6716 num_settext_msgs = 0; 6717 r = SendMessageA( hwnd, WM_SETTEXT, 0, (ULONG_PTR)"another_caption" ); 6718 ok( r != 0, "WM_SETTEXT failed\n" ); 6719 ok( num_settext_msgs == 1, "got %u WM_SETTEXT messages\n", num_settext_msgs ); 6720 6721 num_gettext_msgs = 0; 6722 memset( buf, 0, sizeof(buf) ); 6723 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6724 ok( buf_len != 0, "expected a nonempty window text\n" ); 6725 ok( !strcmp(buf, "another_caption"), "got wrong window text '%s'\n", buf ); 6726 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6727 6728 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE )) 6729 DispatchMessageA( &msg ); 6730 6731 /* test interthread GetWindowTextA */ 6732 num_msgs = 0; 6733 thread = CreateThread( NULL, 0, gettext_msg_thread, hwnd, 0, &tid ); 6734 ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError()); 6735 while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0) 6736 { 6737 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE )) 6738 DispatchMessageA( &msg ); 6739 num_msgs++; 6740 } 6741 CloseHandle( thread ); 6742 ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs ); 6743 6744 /* test interthread SetWindowText */ 6745 num_msgs = 0; 6746 thread = CreateThread( NULL, 0, settext_msg_thread, hwnd, 0, &tid ); 6747 ok(thread != NULL, "CreateThread failed, error %d\n", GetLastError()); 6748 while (MsgWaitForMultipleObjects( 1, &thread, FALSE, INFINITE, QS_SENDMESSAGE ) != WAIT_OBJECT_0) 6749 { 6750 while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE | PM_QS_SENDMESSAGE )) 6751 DispatchMessageA( &msg ); 6752 num_msgs++; 6753 } 6754 CloseHandle( thread ); 6755 ok( num_msgs >= 1, "got %u wakeups from MsgWaitForMultipleObjects\n", num_msgs ); 6756 6757 num_gettext_msgs = 0; 6758 memset( buf, 0, sizeof(buf) ); 6759 buf_len = GetWindowTextA( hwnd, buf, sizeof(buf) ); 6760 ok( buf_len != 0, "expected a nonempty window text\n" ); 6761 ok( !strcmp(buf, "thread_caption"), "got wrong window text '%s'\n", buf ); 6762 ok( num_gettext_msgs == 1, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 6763 6764 /* seems to crash on every modern Windows version */ 6765 if (0) 6766 { 6767 r = SendMessageA( hwnd, WM_GETTEXT, 0x10, 0x1000); 6768 ok( r == 0, "settext should return zero\n"); 6769 6770 r = SendMessageA( hwnd, WM_GETTEXT, 0x10000, 0); 6771 ok( r == 0, "settext should return zero (%ld)\n", r); 6772 6773 r = SendMessageA( hwnd, WM_GETTEXT, 0xff000000, 0x1000); 6774 ok( r == 0, "settext should return zero (%ld)\n", r); 6775 6776 r = SendMessageA( hwnd, WM_GETTEXT, 0x1000, 0xff000000); 6777 ok( r == 0, "settext should return zero (%ld)\n", r); 6778 } 6779 6780 DestroyWindow(hwnd); 6781 } 6782 6783 6784 static void test_GetUpdateRect(void) 6785 { 6786 MSG msg; 6787 BOOL ret, parent_wm_paint, grandparent_wm_paint; 6788 RECT rc1, rc2; 6789 HWND hgrandparent, hparent, hchild; 6790 WNDCLASSA cls; 6791 static const char classNameA[] = "GetUpdateRectClass"; 6792 6793 hgrandparent = CreateWindowA("static", "grandparent", WS_OVERLAPPEDWINDOW, 6794 0, 0, 100, 100, NULL, NULL, 0, NULL); 6795 6796 hparent = CreateWindowA("static", "parent", WS_CHILD|WS_VISIBLE, 6797 0, 0, 100, 100, hgrandparent, NULL, 0, NULL); 6798 6799 hchild = CreateWindowA("static", "child", WS_CHILD|WS_VISIBLE, 6800 10, 10, 30, 30, hparent, NULL, 0, NULL); 6801 6802 ShowWindow(hgrandparent, SW_SHOW); 6803 UpdateWindow(hgrandparent); 6804 flush_events( TRUE ); 6805 6806 ShowWindow(hchild, SW_HIDE); 6807 SetRectEmpty(&rc2); 6808 ret = GetUpdateRect(hgrandparent, &rc1, FALSE); 6809 ok(!ret, "GetUpdateRect returned not empty region\n"); 6810 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 6811 wine_dbgstr_rect(&rc2)); 6812 6813 SetRect(&rc2, 10, 10, 40, 40); 6814 ret = GetUpdateRect(hparent, &rc1, FALSE); 6815 ok(ret, "GetUpdateRect returned empty region\n"); 6816 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 6817 wine_dbgstr_rect(&rc2)); 6818 6819 parent_wm_paint = FALSE; 6820 grandparent_wm_paint = FALSE; 6821 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 6822 { 6823 if (msg.message == WM_PAINT) 6824 { 6825 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE; 6826 if (msg.hwnd == hparent) parent_wm_paint = TRUE; 6827 } 6828 DispatchMessageA(&msg); 6829 } 6830 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n"); 6831 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n"); 6832 6833 DestroyWindow(hgrandparent); 6834 6835 cls.style = 0; 6836 cls.lpfnWndProc = DefWindowProcA; 6837 cls.cbClsExtra = 0; 6838 cls.cbWndExtra = 0; 6839 cls.hInstance = GetModuleHandleA(0); 6840 cls.hIcon = 0; 6841 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 6842 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 6843 cls.lpszMenuName = NULL; 6844 cls.lpszClassName = classNameA; 6845 6846 if(!RegisterClassA(&cls)) { 6847 trace("Register failed %d\n", GetLastError()); 6848 return; 6849 } 6850 6851 hgrandparent = CreateWindowA(classNameA, "grandparent", WS_OVERLAPPEDWINDOW, 6852 0, 0, 100, 100, NULL, NULL, 0, NULL); 6853 6854 hparent = CreateWindowA(classNameA, "parent", WS_CHILD|WS_VISIBLE, 6855 0, 0, 100, 100, hgrandparent, NULL, 0, NULL); 6856 6857 hchild = CreateWindowA(classNameA, "child", WS_CHILD|WS_VISIBLE, 6858 10, 10, 30, 30, hparent, NULL, 0, NULL); 6859 6860 ShowWindow(hgrandparent, SW_SHOW); 6861 UpdateWindow(hgrandparent); 6862 flush_events( TRUE ); 6863 6864 ret = GetUpdateRect(hgrandparent, &rc1, FALSE); 6865 ok(!ret, "GetUpdateRect returned not empty region\n"); 6866 6867 ShowWindow(hchild, SW_HIDE); 6868 6869 SetRectEmpty(&rc2); 6870 ret = GetUpdateRect(hgrandparent, &rc1, FALSE); 6871 ok(!ret, "GetUpdateRect returned not empty region\n"); 6872 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 6873 wine_dbgstr_rect(&rc2)); 6874 6875 SetRect(&rc2, 10, 10, 40, 40); 6876 ret = GetUpdateRect(hparent, &rc1, FALSE); 6877 ok(ret, "GetUpdateRect returned empty region\n"); 6878 ok(EqualRect(&rc1, &rc2), "rects do not match %s / %s\n", wine_dbgstr_rect(&rc1), 6879 wine_dbgstr_rect(&rc2)); 6880 6881 parent_wm_paint = FALSE; 6882 grandparent_wm_paint = FALSE; 6883 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 6884 { 6885 if (msg.message == WM_PAINT) 6886 { 6887 if (msg.hwnd == hgrandparent) grandparent_wm_paint = TRUE; 6888 if (msg.hwnd == hparent) parent_wm_paint = TRUE; 6889 } 6890 DispatchMessageA(&msg); 6891 } 6892 ok(parent_wm_paint, "WM_PAINT should have been received in parent\n"); 6893 ok(!grandparent_wm_paint, "WM_PAINT should NOT have been received in grandparent\n"); 6894 6895 DestroyWindow(hgrandparent); 6896 } 6897 6898 6899 static LRESULT CALLBACK TestExposedRegion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 6900 { 6901 if(msg == WM_PAINT) 6902 { 6903 PAINTSTRUCT ps; 6904 RECT updateRect; 6905 DWORD waitResult; 6906 HWND win; 6907 const int waitTime = 2000; 6908 6909 BeginPaint(hwnd, &ps); 6910 6911 /* create and destroy window to create an exposed region on this window */ 6912 win = CreateWindowA("static", "win", WS_VISIBLE, 6913 10,10,50,50, NULL, NULL, 0, NULL); 6914 DestroyWindow(win); 6915 6916 waitResult = MsgWaitForMultipleObjects( 0, NULL, FALSE, waitTime, QS_PAINT ); 6917 6918 ValidateRect(hwnd, NULL); 6919 EndPaint(hwnd, &ps); 6920 6921 if(waitResult != WAIT_TIMEOUT) 6922 { 6923 GetUpdateRect(hwnd, &updateRect, FALSE); 6924 ok(IsRectEmpty(&updateRect), "Exposed rect should be empty\n"); 6925 } 6926 6927 return 1; 6928 } 6929 return DefWindowProcA(hwnd, msg, wParam, lParam); 6930 } 6931 6932 static void test_Expose(void) 6933 { 6934 WNDCLASSA cls; 6935 HWND mw; 6936 6937 memset(&cls, 0, sizeof(WNDCLASSA)); 6938 cls.lpfnWndProc = TestExposedRegion_WndProc; 6939 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 6940 cls.lpszClassName = "TestExposeClass"; 6941 RegisterClassA(&cls); 6942 6943 mw = CreateWindowA("TestExposeClass", "MainWindow", WS_VISIBLE|WS_OVERLAPPEDWINDOW, 6944 0, 0, 200, 100, NULL, NULL, 0, NULL); 6945 6946 UpdateWindow(mw); 6947 DestroyWindow(mw); 6948 } 6949 6950 static LRESULT CALLBACK TestNCRedraw_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 6951 { 6952 static UINT ncredrawflags; 6953 PAINTSTRUCT ps; 6954 6955 switch(msg) 6956 { 6957 case WM_CREATE: 6958 ncredrawflags = *(UINT *) (((CREATESTRUCTA *)lParam)->lpCreateParams); 6959 return 0; 6960 case WM_NCPAINT: 6961 RedrawWindow(hwnd, NULL, NULL, ncredrawflags); 6962 break; 6963 case WM_PAINT: 6964 BeginPaint(hwnd, &ps); 6965 EndPaint(hwnd, &ps); 6966 return 0; 6967 } 6968 return DefWindowProcA(hwnd, msg, wParam, lParam); 6969 } 6970 6971 static void run_NCRedrawLoop(UINT flags) 6972 { 6973 HWND hwnd; 6974 MSG msg; 6975 6976 UINT loopcount = 0; 6977 6978 hwnd = CreateWindowA("TestNCRedrawClass", "MainWindow", 6979 WS_OVERLAPPEDWINDOW, 0, 0, 200, 100, 6980 NULL, NULL, 0, &flags); 6981 ShowWindow(hwnd, SW_SHOW); 6982 UpdateWindow(hwnd); 6983 flush_events( FALSE ); 6984 while (PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE)) 6985 { 6986 if (msg.message == WM_PAINT) loopcount++; 6987 if (loopcount >= 100) break; 6988 TranslateMessage(&msg); 6989 DispatchMessageA(&msg); 6990 MsgWaitForMultipleObjects(0, NULL, FALSE, 100, QS_ALLINPUT); 6991 } 6992 todo_wine_if (flags == (RDW_INVALIDATE | RDW_FRAME)) 6993 ok(loopcount < 100, "Detected infinite WM_PAINT loop (%x).\n", flags); 6994 DestroyWindow(hwnd); 6995 } 6996 6997 static void test_NCRedraw(void) 6998 { 6999 WNDCLASSA wndclass; 7000 7001 wndclass.lpszClassName = "TestNCRedrawClass"; 7002 wndclass.style = CS_HREDRAW | CS_VREDRAW; 7003 wndclass.lpfnWndProc = TestNCRedraw_WndProc; 7004 wndclass.cbClsExtra = 0; 7005 wndclass.cbWndExtra = 0; 7006 wndclass.hInstance = 0; 7007 wndclass.hIcon = LoadIconA(0, (LPCSTR)IDI_APPLICATION); 7008 wndclass.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 7009 wndclass.hbrBackground = GetStockObject(WHITE_BRUSH); 7010 wndclass.lpszMenuName = NULL; 7011 7012 RegisterClassA(&wndclass); 7013 7014 run_NCRedrawLoop(RDW_INVALIDATE | RDW_FRAME); 7015 run_NCRedrawLoop(RDW_INVALIDATE); 7016 } 7017 7018 static void test_GetWindowModuleFileName(void) 7019 { 7020 HWND hwnd; 7021 HINSTANCE hinst; 7022 UINT ret1, ret2; 7023 char buf1[MAX_PATH], buf2[MAX_PATH]; 7024 7025 if (!pGetWindowModuleFileNameA) 7026 { 7027 win_skip("GetWindowModuleFileNameA is not available\n"); 7028 return; 7029 } 7030 7031 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL); 7032 assert(hwnd); 7033 7034 hinst = (HINSTANCE)GetWindowLongPtrA(hwnd, GWLP_HINSTANCE); 7035 ok(hinst == 0 || broken(hinst == GetModuleHandleA(NULL)), /* win9x */ "expected 0, got %p\n", hinst); 7036 7037 buf1[0] = 0; 7038 SetLastError(0xdeadbeef); 7039 ret1 = GetModuleFileNameA(hinst, buf1, sizeof(buf1)); 7040 ok(ret1, "GetModuleFileName error %u\n", GetLastError()); 7041 7042 buf2[0] = 0; 7043 SetLastError(0xdeadbeef); 7044 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2)); 7045 ok(ret2 || broken(!ret2), /* nt4 sp 3 */ 7046 "GetWindowModuleFileNameA error %u\n", GetLastError()); 7047 7048 if (ret2) 7049 { 7050 ok(ret1 == ret2 || broken(ret2 == ret1 + 1), /* win98 */ "%u != %u\n", ret1, ret2); 7051 ok(!strcmp(buf1, buf2), "%s != %s\n", buf1, buf2); 7052 } 7053 hinst = GetModuleHandleA(NULL); 7054 7055 SetLastError(0xdeadbeef); 7056 ret2 = GetModuleFileNameA(hinst, buf2, ret1 - 2); 7057 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3), /* win98 */ 7058 "expected %u, got %u\n", ret1 - 2, ret2); 7059 ok(GetLastError() == 0xdeadbeef /* XP */ || 7060 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ 7061 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); 7062 7063 SetLastError(0xdeadbeef); 7064 ret2 = GetModuleFileNameA(hinst, buf2, 0); 7065 ok(!ret2, "GetModuleFileName should return 0\n"); 7066 ok(GetLastError() == 0xdeadbeef /* XP */ || 7067 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ 7068 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); 7069 7070 SetLastError(0xdeadbeef); 7071 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, ret1 - 2); 7072 ok(ret2 == ret1 - 2 || broken(ret2 == ret1 - 3) /* win98 */ || broken(!ret2), /* nt4 sp3 */ 7073 "expected %u, got %u\n", ret1 - 2, ret2); 7074 ok(GetLastError() == 0xdeadbeef /* XP */ || 7075 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ 7076 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); 7077 7078 SetLastError(0xdeadbeef); 7079 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, 0); 7080 ok(!ret2, "expected 0, got %u\n", ret2); 7081 ok(GetLastError() == 0xdeadbeef /* XP */ || 7082 GetLastError() == ERROR_INSUFFICIENT_BUFFER, /* win2k3, vista */ 7083 "expected 0xdeadbeef or ERROR_INSUFFICIENT_BUFFER, got %u\n", GetLastError()); 7084 7085 DestroyWindow(hwnd); 7086 7087 buf2[0] = 0; 7088 hwnd = (HWND)0xdeadbeef; 7089 SetLastError(0xdeadbeef); 7090 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1)); 7091 ok(!ret1, "expected 0, got %u\n", ret1); 7092 ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || broken(GetLastError() == 0xdeadbeef), /* win9x */ 7093 "expected ERROR_INVALID_WINDOW_HANDLE, got %u\n", GetLastError()); 7094 7095 hwnd = FindWindowA("Shell_TrayWnd", NULL); 7096 ok(IsWindow(hwnd) || broken(!hwnd), "got invalid tray window %p\n", hwnd); 7097 SetLastError(0xdeadbeef); 7098 ret1 = pGetWindowModuleFileNameA(hwnd, buf1, sizeof(buf1)); 7099 ok(!ret1 || broken(ret1), /* win98 */ "expected 0, got %u\n", ret1); 7100 7101 if (!ret1) /* inter-process GetWindowModuleFileName works on win9x, so don't test the desktop there */ 7102 { 7103 ret1 = GetModuleFileNameA(0, buf1, sizeof(buf1)); 7104 hwnd = GetDesktopWindow(); 7105 ok(IsWindow(hwnd), "got invalid desktop window %p\n", hwnd); 7106 SetLastError(0xdeadbeef); 7107 ret2 = pGetWindowModuleFileNameA(hwnd, buf2, sizeof(buf2)); 7108 ok(!ret2 || 7109 ret1 == ret2 || /* vista */ 7110 broken(ret2), /* some win98 return user.exe as file name */ 7111 "expected 0 or %u, got %u %s\n", ret1, ret2, buf2); 7112 } 7113 } 7114 7115 static void test_hwnd_message(void) 7116 { 7117 static const WCHAR mainwindowclassW[] = {'M','a','i','n','W','i','n','d','o','w','C','l','a','s','s',0}; 7118 static const WCHAR message_windowW[] = {'m','e','s','s','a','g','e',' ','w','i','n','d','o','w',0}; 7119 7120 HWND parent = 0, hwnd, found; 7121 RECT rect; 7122 7123 /* HWND_MESSAGE is not supported below w2k, but win9x return != 0 7124 on CreateWindowExA and crash later in the test. 7125 Use UNICODE here to fail on win9x */ 7126 hwnd = CreateWindowExW(0, mainwindowclassW, message_windowW, WS_CAPTION | WS_VISIBLE, 7127 100, 100, 200, 200, HWND_MESSAGE, 0, 0, NULL); 7128 if (!hwnd) 7129 { 7130 win_skip("CreateWindowExW with parent HWND_MESSAGE failed\n"); 7131 return; 7132 } 7133 7134 ok( !GetParent(hwnd), "GetParent should return 0 for message only windows\n" ); 7135 if (pGetAncestor) 7136 { 7137 char buffer[100]; 7138 HWND root, desktop = GetDesktopWindow(); 7139 7140 parent = pGetAncestor(hwnd, GA_PARENT); 7141 ok(parent != 0, "GetAncestor(GA_PARENT) should not return 0 for message windows\n"); 7142 ok(parent != desktop, "GetAncestor(GA_PARENT) should not return desktop for message windows\n"); 7143 root = pGetAncestor(hwnd, GA_ROOT); 7144 ok(root == hwnd, "GetAncestor(GA_ROOT) should return hwnd for message windows\n"); 7145 ok( !pGetAncestor(parent, GA_PARENT) || broken(pGetAncestor(parent, GA_PARENT) != 0), /* win2k */ 7146 "parent shouldn't have parent %p\n", pGetAncestor(parent, GA_PARENT) ); 7147 trace("parent %p root %p desktop %p\n", parent, root, desktop); 7148 if (!GetClassNameA( parent, buffer, sizeof(buffer) )) buffer[0] = 0; 7149 ok( !lstrcmpiA( buffer, "Message" ), "wrong parent class '%s'\n", buffer ); 7150 GetWindowRect( parent, &rect ); 7151 ok( rect.left == 0 && rect.right == 100 && rect.top == 0 && rect.bottom == 100, 7152 "wrong parent rect %s\n", wine_dbgstr_rect( &rect )); 7153 } 7154 GetWindowRect( hwnd, &rect ); 7155 ok( rect.left == 100 && rect.right == 300 && rect.top == 100 && rect.bottom == 300, 7156 "wrong window rect %s\n", wine_dbgstr_rect( &rect )); 7157 7158 /* test FindWindow behavior */ 7159 7160 found = FindWindowExA( 0, 0, 0, "message window" ); 7161 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); 7162 SetLastError(0xdeadbeef); 7163 found = FindWindowExA( GetDesktopWindow(), 0, 0, "message window" ); 7164 ok( found == 0, "found message window %p/%p\n", found, hwnd ); 7165 ok( GetLastError() == 0xdeadbeef, "expected deadbeef, got %d\n", GetLastError() ); 7166 if (parent) 7167 { 7168 found = FindWindowExA( parent, 0, 0, "message window" ); 7169 ok( found == hwnd, "didn't find message window %p/%p\n", found, hwnd ); 7170 } 7171 7172 /* test IsChild behavior */ 7173 7174 if (parent) ok( !IsChild( parent, hwnd ), "HWND_MESSAGE is child of top window\n" ); 7175 7176 /* test IsWindowVisible behavior */ 7177 7178 ok( !IsWindowVisible( hwnd ), "HWND_MESSAGE window is visible\n" ); 7179 if (parent) ok( !IsWindowVisible( parent ), "HWND_MESSAGE parent is visible\n" ); 7180 7181 DestroyWindow(hwnd); 7182 } 7183 7184 static void test_layered_window(void) 7185 { 7186 HWND hwnd; 7187 COLORREF key = 0; 7188 BYTE alpha = 0; 7189 DWORD flags = 0; 7190 POINT pt = { 0, 0 }; 7191 SIZE sz = { 200, 200 }; 7192 HDC hdc; 7193 HBITMAP hbm; 7194 BOOL ret; 7195 7196 if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes || !pUpdateLayeredWindow) 7197 { 7198 win_skip( "layered windows not supported\n" ); 7199 return; 7200 } 7201 7202 hdc = CreateCompatibleDC( 0 ); 7203 hbm = CreateCompatibleBitmap( hdc, 200, 200 ); 7204 SelectObject( hdc, hbm ); 7205 7206 hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION, 7207 100, 100, 200, 200, 0, 0, 0, NULL); 7208 assert( hwnd ); 7209 SetLastError( 0xdeadbeef ); 7210 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7211 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 7212 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); 7213 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7214 ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" ); 7215 ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA ); 7216 ok( !ret, "SetLayeredWindowAttributes should fail on non-layered window\n" ); 7217 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 7218 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7219 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); 7220 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7221 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" ); 7222 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7223 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); 7224 ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA ); 7225 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); 7226 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7227 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); 7228 ok( key == 0x123456 || key == 0, "wrong color key %x\n", key ); 7229 ok( alpha == 44, "wrong alpha %u\n", alpha ); 7230 ok( flags == LWA_ALPHA, "wrong flags %x\n", flags ); 7231 SetLastError( 0xdeadbeef ); 7232 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7233 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" ); 7234 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); 7235 7236 /* clearing WS_EX_LAYERED resets attributes */ 7237 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); 7238 SetLastError( 0xdeadbeef ); 7239 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7240 ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); 7241 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7242 ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" ); 7243 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 7244 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7245 ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); 7246 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7247 ok( ret, "UpdateLayeredWindow should succeed on layered window\n" ); 7248 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE | ULW_EX_NORESIZE ); 7249 ok( !ret, "UpdateLayeredWindow should fail with ex flag\n" ); 7250 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 7251 if (pUpdateLayeredWindowIndirect) 7252 { 7253 UPDATELAYEREDWINDOWINFO info; 7254 info.cbSize = sizeof(info); 7255 info.hdcDst = 0; 7256 info.pptDst = NULL; 7257 info.psize = &sz; 7258 info.hdcSrc = hdc; 7259 info.pptSrc = &pt; 7260 info.crKey = 0; 7261 info.pblend = NULL; 7262 info.dwFlags = ULW_OPAQUE | ULW_EX_NORESIZE; 7263 info.prcDirty = NULL; 7264 ret = pUpdateLayeredWindowIndirect( hwnd, &info ); 7265 ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" ); 7266 sz.cx--; 7267 SetLastError(0); 7268 ret = pUpdateLayeredWindowIndirect( hwnd, &info ); 7269 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" ); 7270 /* particular error code differs from version to version, could be ERROR_INCORRECT_SIZE, 7271 ERROR_MR_MID_NOT_FOUND or ERROR_GEN_FAILURE (Win8/Win10) */ 7272 ok( GetLastError() != 0, "wrong error %u\n", GetLastError() ); 7273 info.dwFlags = ULW_OPAQUE; 7274 ret = pUpdateLayeredWindowIndirect( hwnd, &info ); 7275 ok( ret, "UpdateLayeredWindowIndirect should succeed on layered window\n" ); 7276 sz.cx++; 7277 info.dwFlags = ULW_OPAQUE | 0xf00; 7278 ret = pUpdateLayeredWindowIndirect( hwnd, &info ); 7279 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" ); 7280 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 7281 info.cbSize--; 7282 info.dwFlags = ULW_OPAQUE; 7283 ret = pUpdateLayeredWindowIndirect( hwnd, &info ); 7284 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" ); 7285 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 7286 ret = pUpdateLayeredWindowIndirect( hwnd, NULL ); 7287 ok( !ret, "UpdateLayeredWindowIndirect should fail\n" ); 7288 ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); 7289 } 7290 7291 ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA ); 7292 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); 7293 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7294 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); 7295 ok( key == 0x654321, "wrong color key %x\n", key ); 7296 ok( alpha == 22, "wrong alpha %u\n", alpha ); 7297 ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags ); 7298 SetLastError( 0xdeadbeef ); 7299 ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); 7300 ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" ); 7301 ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); 7302 7303 ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY ); 7304 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); 7305 alpha = 0; 7306 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7307 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); 7308 ok( key == 0x888888, "wrong color key %x\n", key ); 7309 /* alpha not changed on vista if LWA_ALPHA is not set */ 7310 ok( alpha == 22 || alpha == 33, "wrong alpha %u\n", alpha ); 7311 ok( flags == LWA_COLORKEY, "wrong flags %x\n", flags ); 7312 7313 /* color key may or may not be changed without LWA_COLORKEY */ 7314 ret = pSetLayeredWindowAttributes( hwnd, 0x999999, 44, 0 ); 7315 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); 7316 alpha = 0; 7317 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7318 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); 7319 ok( key == 0x888888 || key == 0x999999, "wrong color key %x\n", key ); 7320 ok( alpha == 22 || alpha == 44, "wrong alpha %u\n", alpha ); 7321 ok( flags == 0, "wrong flags %x\n", flags ); 7322 7323 /* default alpha and color key is 0 */ 7324 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); 7325 SetWindowLongA( hwnd, GWL_EXSTYLE, GetWindowLongA(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); 7326 ret = pSetLayeredWindowAttributes( hwnd, 0x222222, 55, 0 ); 7327 ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); 7328 ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); 7329 ok( ret, "GetLayeredWindowAttributes should succeed on layered window\n" ); 7330 ok( key == 0 || key == 0x222222, "wrong color key %x\n", key ); 7331 ok( alpha == 0 || alpha == 55, "wrong alpha %u\n", alpha ); 7332 ok( flags == 0, "wrong flags %x\n", flags ); 7333 7334 DestroyWindow( hwnd ); 7335 DeleteDC( hdc ); 7336 DeleteObject( hbm ); 7337 } 7338 7339 static MONITORINFO mi; 7340 7341 static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 7342 { 7343 switch (msg) 7344 { 7345 case WM_NCCREATE: 7346 { 7347 CREATESTRUCTA *cs = (CREATESTRUCTA *)lp; 7348 ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top && 7349 cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom, 7350 "expected %s, got (%d,%d)-(%d,%d)\n", wine_dbgstr_rect(&mi.rcMonitor), 7351 cs->x, cs->y, cs->cx, cs->cy); 7352 break; 7353 } 7354 case WM_GETMINMAXINFO: 7355 { 7356 MINMAXINFO *minmax = (MINMAXINFO *)lp; 7357 ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left); 7358 ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top); 7359 ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right); 7360 ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom); 7361 break; 7362 } 7363 } 7364 return DefWindowProcA(hwnd, msg, wp, lp); 7365 } 7366 7367 static void test_fullscreen(void) 7368 { 7369 static const DWORD t_style[] = { 7370 WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME 7371 }; 7372 static const DWORD t_ex_style[] = { 7373 0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW 7374 }; 7375 WNDCLASSA cls; 7376 HWND hwnd; 7377 int i, j; 7378 POINT pt; 7379 RECT rc; 7380 HMONITOR hmon; 7381 LRESULT ret; 7382 7383 if (!pGetMonitorInfoA || !pMonitorFromPoint) 7384 { 7385 win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n"); 7386 return; 7387 } 7388 7389 pt.x = pt.y = 0; 7390 SetLastError(0xdeadbeef); 7391 hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); 7392 ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); 7393 7394 mi.cbSize = sizeof(mi); 7395 SetLastError(0xdeadbeef); 7396 ret = pGetMonitorInfoA(hmon, &mi); 7397 ok(ret, "GetMonitorInfo error %u\n", GetLastError()); 7398 trace("monitor %s, work %s\n", wine_dbgstr_rect(&mi.rcMonitor), wine_dbgstr_rect(&mi.rcWork)); 7399 7400 cls.style = 0; 7401 cls.lpfnWndProc = fullscreen_wnd_proc; 7402 cls.cbClsExtra = 0; 7403 cls.cbWndExtra = 0; 7404 cls.hInstance = GetModuleHandleA(NULL); 7405 cls.hIcon = 0; 7406 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 7407 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 7408 cls.lpszMenuName = NULL; 7409 cls.lpszClassName = "fullscreen_class"; 7410 RegisterClassA(&cls); 7411 7412 for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++) 7413 { 7414 DWORD style, ex_style; 7415 7416 /* avoid a WM interaction */ 7417 assert(!(t_style[i] & WS_VISIBLE)); 7418 7419 for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++) 7420 { 7421 int fixup; 7422 7423 style = t_style[i]; 7424 ex_style = t_ex_style[j]; 7425 7426 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7427 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7428 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7429 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7430 GetWindowRect(hwnd, &rc); 7431 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7432 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && 7433 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, 7434 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7435 DestroyWindow(hwnd); 7436 7437 style = t_style[i] | WS_MAXIMIZE; 7438 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7439 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7440 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7441 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7442 GetWindowRect(hwnd, &rc); 7443 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7444 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && 7445 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, 7446 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7447 DestroyWindow(hwnd); 7448 7449 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION; 7450 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7451 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7452 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7453 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7454 GetWindowRect(hwnd, &rc); 7455 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7456 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && 7457 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, 7458 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7459 DestroyWindow(hwnd); 7460 7461 style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX; 7462 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7463 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7464 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7465 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7466 GetWindowRect(hwnd, &rc); 7467 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7468 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && 7469 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, 7470 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7471 DestroyWindow(hwnd); 7472 7473 style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX; 7474 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7475 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7476 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7477 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7478 GetWindowRect(hwnd, &rc); 7479 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7480 /* Windows makes a maximized window slightly larger (to hide the borders?) */ 7481 fixup = min(abs(rc.left), abs(rc.top)); 7482 InflateRect(&rc, -fixup, -fixup); 7483 ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top && 7484 rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom, 7485 "%#x/%#x: window rect %s must be in %s\n", ex_style, style, wine_dbgstr_rect(&rc), 7486 wine_dbgstr_rect(&mi.rcMonitor)); 7487 DestroyWindow(hwnd); 7488 7489 style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX; 7490 hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style, 7491 mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, 7492 GetDesktopWindow(), 0, GetModuleHandleA(NULL), NULL); 7493 ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style); 7494 GetWindowRect(hwnd, &rc); 7495 trace("%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7496 /* Windows makes a maximized window slightly larger (to hide the borders?) */ 7497 fixup = min(abs(rc.left), abs(rc.top)); 7498 InflateRect(&rc, -fixup, -fixup); 7499 if (style & (WS_CHILD | WS_POPUP)) 7500 ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top && 7501 rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom, 7502 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7503 else 7504 ok(rc.left >= mi.rcMonitor.left && rc.top >= mi.rcMonitor.top && 7505 rc.right <= mi.rcMonitor.right && rc.bottom <= mi.rcMonitor.bottom, 7506 "%#x/%#x: window rect %s\n", ex_style, style, wine_dbgstr_rect(&rc)); 7507 DestroyWindow(hwnd); 7508 } 7509 } 7510 7511 UnregisterClassA("fullscreen_class", GetModuleHandleA(NULL)); 7512 } 7513 7514 static BOOL test_thick_child_got_minmax; 7515 static const char * test_thick_child_name; 7516 static LONG test_thick_child_style; 7517 static LONG test_thick_child_exStyle; 7518 7519 static LRESULT WINAPI test_thick_child_size_winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 7520 { 7521 MINMAXINFO* minmax; 7522 int expectedMinTrackX; 7523 int expectedMinTrackY; 7524 int actualMinTrackX; 7525 int actualMinTrackY; 7526 int expectedMaxTrackX; 7527 int expectedMaxTrackY; 7528 int actualMaxTrackX; 7529 int actualMaxTrackY; 7530 int expectedMaxSizeX; 7531 int expectedMaxSizeY; 7532 int actualMaxSizeX; 7533 int actualMaxSizeY; 7534 int expectedPosX; 7535 int expectedPosY; 7536 int actualPosX; 7537 int actualPosY; 7538 LONG adjustedStyle; 7539 RECT rect; 7540 switch (msg) 7541 { 7542 case WM_GETMINMAXINFO: 7543 { 7544 minmax = (MINMAXINFO *)lparam; 7545 trace("hwnd %p, WM_GETMINMAXINFO, %08lx, %08lx\n", hwnd, wparam, lparam); 7546 dump_minmax_info( minmax ); 7547 7548 test_thick_child_got_minmax = TRUE; 7549 7550 7551 adjustedStyle = test_thick_child_style; 7552 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION) 7553 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ 7554 GetClientRect(GetParent(hwnd), &rect); 7555 AdjustWindowRectEx(&rect, adjustedStyle, FALSE, test_thick_child_exStyle); 7556 7557 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER)) 7558 { 7559 expectedMinTrackX = GetSystemMetrics(SM_CXMINTRACK); 7560 expectedMinTrackY = GetSystemMetrics(SM_CYMINTRACK); 7561 } 7562 else 7563 { 7564 expectedMinTrackX = -2 * rect.left; 7565 expectedMinTrackY = -2 * rect.top; 7566 } 7567 actualMinTrackX = minmax->ptMinTrackSize.x; 7568 actualMinTrackY = minmax->ptMinTrackSize.y; 7569 7570 ok(actualMinTrackX == expectedMinTrackX && actualMinTrackY == expectedMinTrackY, 7571 "expected minTrack %dx%d, actual minTrack %dx%d for %s\n", 7572 expectedMinTrackX, expectedMinTrackY, actualMinTrackX, actualMinTrackY, 7573 test_thick_child_name); 7574 7575 actualMaxTrackX = minmax->ptMaxTrackSize.x; 7576 actualMaxTrackY = minmax->ptMaxTrackSize.y; 7577 expectedMaxTrackX = GetSystemMetrics(SM_CXMAXTRACK); 7578 expectedMaxTrackY = GetSystemMetrics(SM_CYMAXTRACK); 7579 ok(actualMaxTrackX == expectedMaxTrackX && actualMaxTrackY == expectedMaxTrackY, 7580 "expected maxTrack %dx%d, actual maxTrack %dx%d for %s\n", 7581 expectedMaxTrackX, expectedMaxTrackY, actualMaxTrackX, actualMaxTrackY, 7582 test_thick_child_name); 7583 7584 expectedMaxSizeX = rect.right - rect.left; 7585 expectedMaxSizeY = rect.bottom - rect.top; 7586 actualMaxSizeX = minmax->ptMaxSize.x; 7587 actualMaxSizeY = minmax->ptMaxSize.y; 7588 7589 ok(actualMaxSizeX == expectedMaxSizeX && actualMaxSizeY == expectedMaxSizeY, 7590 "expected maxSize %dx%d, actual maxSize %dx%d for %s\n", 7591 expectedMaxSizeX, expectedMaxSizeY, actualMaxSizeX, actualMaxSizeY, 7592 test_thick_child_name); 7593 7594 7595 expectedPosX = rect.left; 7596 expectedPosY = rect.top; 7597 actualPosX = minmax->ptMaxPosition.x; 7598 actualPosY = minmax->ptMaxPosition.y; 7599 ok(actualPosX == expectedPosX && actualPosY == expectedPosY, 7600 "expected maxPosition (%d/%d), actual maxPosition (%d/%d) for %s\n", 7601 expectedPosX, expectedPosY, actualPosX, actualPosY, test_thick_child_name); 7602 7603 break; 7604 } 7605 } 7606 7607 return DefWindowProcA(hwnd, msg, wparam, lparam); 7608 } 7609 7610 #define NUMBER_OF_THICK_CHILD_TESTS 16 7611 static void test_thick_child_size(HWND parentWindow) 7612 { 7613 BOOL success; 7614 RECT childRect; 7615 RECT adjustedParentRect; 7616 HWND childWindow; 7617 LONG childWidth; 7618 LONG childHeight; 7619 LONG expectedWidth; 7620 LONG expectedHeight; 7621 WNDCLASSA cls; 7622 static const char className[] = "THICK_CHILD_CLASS"; 7623 int i; 7624 LONG adjustedStyle; 7625 static const LONG styles[NUMBER_OF_THICK_CHILD_TESTS] = { 7626 WS_CHILD | WS_VISIBLE | WS_THICKFRAME, 7627 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME, 7628 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER, 7629 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER, 7630 WS_CHILD | WS_VISIBLE | WS_THICKFRAME, 7631 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME, 7632 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER, 7633 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER, 7634 WS_CHILD | WS_VISIBLE | WS_THICKFRAME, 7635 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME, 7636 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER, 7637 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER, 7638 WS_CHILD | WS_VISIBLE | WS_THICKFRAME, 7639 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME, 7640 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER, 7641 WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER, 7642 }; 7643 7644 static const LONG exStyles[NUMBER_OF_THICK_CHILD_TESTS] = { 7645 0, 7646 0, 7647 0, 7648 0, 7649 WS_EX_DLGMODALFRAME, 7650 WS_EX_DLGMODALFRAME, 7651 WS_EX_DLGMODALFRAME, 7652 WS_EX_DLGMODALFRAME, 7653 WS_EX_STATICEDGE, 7654 WS_EX_STATICEDGE, 7655 WS_EX_STATICEDGE, 7656 WS_EX_STATICEDGE, 7657 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME, 7658 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME, 7659 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME, 7660 WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME, 7661 }; 7662 static const char *styleName[NUMBER_OF_THICK_CHILD_TESTS] = { 7663 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME", 7664 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME", 7665 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER", 7666 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER", 7667 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_DLGMODALFRAME", 7668 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_DLGMODALFRAME", 7669 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME", 7670 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_DLGMODALFRAME", 7671 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME exstyle= WS_EX_STATICEDGE", 7672 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE", 7673 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE", 7674 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE", 7675 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME, exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME", 7676 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME", 7677 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_DLGFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME", 7678 "style=WS_CHILD | WS_VISIBLE | WS_THICKFRAME | WS_BORDER exstyle= WS_EX_STATICEDGE | WS_EX_DLGMODALFRAME", 7679 }; 7680 7681 cls.style = 0; 7682 cls.lpfnWndProc = test_thick_child_size_winproc; 7683 cls.cbClsExtra = 0; 7684 cls.cbWndExtra = 0; 7685 cls.hInstance = GetModuleHandleA(0); 7686 cls.hIcon = 0; 7687 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 7688 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 7689 cls.lpszMenuName = NULL; 7690 cls.lpszClassName = className; 7691 SetLastError(0xdeadbeef); 7692 success = RegisterClassA(&cls); 7693 ok(success,"RegisterClassA failed, error: %u\n", GetLastError()); 7694 7695 for(i = 0; i < NUMBER_OF_THICK_CHILD_TESTS; i++) 7696 { 7697 test_thick_child_name = styleName[i]; 7698 test_thick_child_style = styles[i]; 7699 test_thick_child_exStyle = exStyles[i]; 7700 test_thick_child_got_minmax = FALSE; 7701 7702 SetLastError(0xdeadbeef); 7703 childWindow = CreateWindowExA( exStyles[i], className, "", styles[i], 0, 0, 0, 0, parentWindow, 0, GetModuleHandleA(0), NULL ); 7704 ok(childWindow != NULL, "Failed to create child window, error: %u\n", GetLastError()); 7705 7706 ok(test_thick_child_got_minmax, "Got no WM_GETMINMAXINFO\n"); 7707 7708 SetLastError(0xdeadbeef); 7709 success = GetWindowRect(childWindow, &childRect); 7710 ok(success,"GetWindowRect call failed, error: %u\n", GetLastError()); 7711 childWidth = childRect.right - childRect.left; 7712 childHeight = childRect.bottom - childRect.top; 7713 7714 adjustedStyle = styles[i]; 7715 if ((adjustedStyle & WS_CAPTION) == WS_CAPTION) 7716 adjustedStyle &= ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ 7717 GetClientRect(GetParent(childWindow), &adjustedParentRect); 7718 AdjustWindowRectEx(&adjustedParentRect, adjustedStyle, FALSE, test_thick_child_exStyle); 7719 7720 7721 if (test_thick_child_style & (WS_DLGFRAME | WS_BORDER)) 7722 { 7723 expectedWidth = GetSystemMetrics(SM_CXMINTRACK); 7724 expectedHeight = GetSystemMetrics(SM_CYMINTRACK); 7725 } 7726 else 7727 { 7728 expectedWidth = -2 * adjustedParentRect.left; 7729 expectedHeight = -2 * adjustedParentRect.top; 7730 } 7731 7732 ok((childWidth == expectedWidth) && (childHeight == expectedHeight), 7733 "size of window (%s) is wrong: expected size %dx%d != actual size %dx%d\n", 7734 test_thick_child_name, expectedWidth, expectedHeight, childWidth, childHeight); 7735 7736 SetLastError(0xdeadbeef); 7737 success = DestroyWindow(childWindow); 7738 ok(success,"DestroyWindow call failed, error: %u\n", GetLastError()); 7739 } 7740 ok(UnregisterClassA(className, GetModuleHandleA(NULL)),"UnregisterClass call failed\n"); 7741 } 7742 7743 static void test_handles( HWND full_hwnd ) 7744 { 7745 HWND hwnd = full_hwnd; 7746 BOOL ret; 7747 RECT rect; 7748 7749 SetLastError( 0xdeadbeef ); 7750 ret = GetWindowRect( hwnd, &rect ); 7751 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() ); 7752 7753 #ifdef _WIN64 7754 if ((ULONG_PTR)full_hwnd >> 32) 7755 hwnd = (HWND)((ULONG_PTR)full_hwnd & ~0u); 7756 else 7757 hwnd = (HWND)((ULONG_PTR)full_hwnd | ((ULONG_PTR)~0u << 32)); 7758 SetLastError( 0xdeadbeef ); 7759 ret = GetWindowRect( hwnd, &rect ); 7760 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() ); 7761 7762 hwnd = (HWND)(((ULONG_PTR)full_hwnd & ~0u) | ((ULONG_PTR)0x1234 << 32)); 7763 SetLastError( 0xdeadbeef ); 7764 ret = GetWindowRect( hwnd, &rect ); 7765 ok( ret, "GetWindowRect failed for %p err %u\n", hwnd, GetLastError() ); 7766 7767 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x9876 << 16)); 7768 SetLastError( 0xdeadbeef ); 7769 ret = GetWindowRect( hwnd, &rect ); 7770 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd ); 7771 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); 7772 7773 hwnd = (HWND)(((ULONG_PTR)full_hwnd & 0xffff) | ((ULONG_PTR)0x12345678 << 16)); 7774 SetLastError( 0xdeadbeef ); 7775 ret = GetWindowRect( hwnd, &rect ); 7776 ok( !ret, "GetWindowRect succeeded for %p\n", hwnd ); 7777 ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); 7778 #endif 7779 } 7780 7781 static void test_winregion(void) 7782 { 7783 HWND hwnd; 7784 RECT r; 7785 int ret, width; 7786 HRGN hrgn; 7787 7788 if (!pGetWindowRgnBox) 7789 { 7790 win_skip("GetWindowRgnBox not supported\n"); 7791 return; 7792 } 7793 7794 hwnd = CreateWindowExA(0, "static", NULL, WS_VISIBLE, 10, 10, 10, 10, NULL, 0, 0, NULL); 7795 /* NULL prect */ 7796 SetLastError(0xdeadbeef); 7797 ret = pGetWindowRgnBox(hwnd, NULL); 7798 ok( ret == ERROR, "Expected ERROR, got %d\n", ret); 7799 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError()); 7800 7801 hrgn = CreateRectRgn(2, 3, 10, 15); 7802 ok( hrgn != NULL, "Region creation failed\n"); 7803 if (hrgn) 7804 { 7805 SetWindowRgn(hwnd, hrgn, FALSE); 7806 7807 SetLastError(0xdeadbeef); 7808 ret = pGetWindowRgnBox(hwnd, NULL); 7809 ok( ret == ERROR, "Expected ERROR, got %d\n", ret); 7810 ok( GetLastError() == 0xdeadbeef, "Expected , got %d\n", GetLastError()); 7811 7812 SetRectEmpty(&r); 7813 ret = pGetWindowRgnBox(hwnd, &r); 7814 ok( ret == SIMPLEREGION, "Expected SIMPLEREGION, got %d\n", ret); 7815 ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15, 7816 "Expected (2,3)-(10,15), got %s\n", wine_dbgstr_rect( &r )); 7817 if (pMirrorRgn) 7818 { 7819 hrgn = CreateRectRgn(2, 3, 10, 15); 7820 ret = pMirrorRgn( hwnd, hrgn ); 7821 ok( ret == TRUE, "MirrorRgn failed %u\n", ret ); 7822 SetRectEmpty(&r); 7823 GetWindowRect( hwnd, &r ); 7824 width = r.right - r.left; 7825 SetRectEmpty(&r); 7826 ret = GetRgnBox( hrgn, &r ); 7827 ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret ); 7828 ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15, 7829 "Wrong rectangle %s for width %d\n", wine_dbgstr_rect( &r ), width ); 7830 } 7831 else win_skip( "MirrorRgn not supported\n" ); 7832 } 7833 DestroyWindow(hwnd); 7834 } 7835 7836 static void test_rtl_layout(void) 7837 { 7838 HWND parent, child; 7839 RECT r; 7840 POINT pt; 7841 7842 if (!pSetProcessDefaultLayout) 7843 { 7844 win_skip( "SetProcessDefaultLayout not supported\n" ); 7845 return; 7846 } 7847 7848 parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL); 7849 child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL); 7850 7851 GetWindowRect( parent, &r ); 7852 ok( r.left == 100 && r.right == 400, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7853 GetClientRect( parent, &r ); 7854 ok( r.left == 0 && r.right == 300, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7855 GetClientRect( child, &r ); 7856 ok( r.left == 0 && r.right == 20, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7857 MapWindowPoints( child, parent, (POINT *)&r, 2 ); 7858 ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7859 GetWindowRect( child, &r ); 7860 ok( r.left == 370 && r.right == 390, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7861 MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); 7862 ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7863 GetWindowRect( child, &r ); 7864 MapWindowPoints( NULL, parent, (POINT *)&r, 1 ); 7865 MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 ); 7866 ok( r.left == 30 && r.right == 10, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7867 pt.x = pt.y = 12; 7868 MapWindowPoints( child, parent, &pt, 1 ); 7869 ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y ); 7870 SetWindowPos( parent, 0, 0, 0, 250, 250, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 7871 GetWindowRect( parent, &r ); 7872 ok( r.left == 100 && r.right == 350, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7873 GetWindowRect( child, &r ); 7874 ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7875 SetWindowLongW( parent, GWL_EXSTYLE, 0 ); 7876 GetWindowRect( child, &r ); 7877 ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7878 MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); 7879 ok( r.left == 220 && r.right == 240, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7880 SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_LAYOUTRTL ); 7881 GetWindowRect( child, &r ); 7882 ok( r.left == 320 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7883 MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); 7884 ok( r.left == 10 && r.right == 30, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7885 SetWindowPos( child, 0, 0, 0, 30, 30, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); 7886 GetWindowRect( child, &r ); 7887 ok( r.left == 310 && r.right == 340, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7888 MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); 7889 ok( r.left == 10 && r.right == 40, "wrong rect %s\n", wine_dbgstr_rect( &r )); 7890 DestroyWindow( child ); 7891 DestroyWindow( parent ); 7892 } 7893 7894 static void test_FlashWindow(void) 7895 { 7896 HWND hwnd; 7897 BOOL ret; 7898 if (!pFlashWindow) 7899 { 7900 win_skip( "FlashWindow not supported\n" ); 7901 return; 7902 } 7903 7904 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP, 7905 0, 0, 0, 0, 0, 0, 0, NULL ); 7906 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 7907 7908 SetLastError( 0xdeadbeef ); 7909 ret = pFlashWindow( NULL, TRUE ); 7910 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, 7911 "FlashWindow returned with %d\n", GetLastError() ); 7912 7913 DestroyWindow( hwnd ); 7914 7915 SetLastError( 0xdeadbeef ); 7916 ret = pFlashWindow( hwnd, TRUE ); 7917 ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, 7918 "FlashWindow returned with %d\n", GetLastError() ); 7919 } 7920 7921 static void test_FlashWindowEx(void) 7922 { 7923 HWND hwnd; 7924 FLASHWINFO finfo; 7925 BOOL prev, ret; 7926 7927 if (!pFlashWindowEx) 7928 { 7929 win_skip( "FlashWindowEx not supported\n" ); 7930 return; 7931 } 7932 7933 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP, 7934 0, 0, 0, 0, 0, 0, 0, NULL ); 7935 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 7936 7937 finfo.cbSize = sizeof(FLASHWINFO); 7938 finfo.dwFlags = FLASHW_TIMER; 7939 finfo.uCount = 3; 7940 finfo.dwTimeout = 200; 7941 finfo.hwnd = NULL; 7942 SetLastError(0xdeadbeef); 7943 ret = pFlashWindowEx(&finfo); 7944 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 7945 "FlashWindowEx returned with %d\n", GetLastError()); 7946 7947 finfo.hwnd = hwnd; 7948 SetLastError(0xdeadbeef); 7949 ret = pFlashWindowEx(NULL); 7950 ok(!ret && GetLastError() == ERROR_NOACCESS, 7951 "FlashWindowEx returned with %d\n", GetLastError()); 7952 7953 SetLastError(0xdeadbeef); 7954 ret = pFlashWindowEx(&finfo); 7955 todo_wine ok(!ret, "previous window state should not be active\n"); 7956 7957 finfo.cbSize = sizeof(FLASHWINFO) - 1; 7958 SetLastError(0xdeadbeef); 7959 ret = pFlashWindowEx(&finfo); 7960 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 7961 "FlashWindowEx succeeded\n"); 7962 7963 finfo.cbSize = sizeof(FLASHWINFO) + 1; 7964 SetLastError(0xdeadbeef); 7965 ret = pFlashWindowEx(&finfo); 7966 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 7967 "FlashWindowEx succeeded\n"); 7968 finfo.cbSize = sizeof(FLASHWINFO); 7969 7970 DestroyWindow( hwnd ); 7971 7972 SetLastError(0xdeadbeef); 7973 ret = pFlashWindowEx(&finfo); 7974 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 7975 "FlashWindowEx returned with %d\n", GetLastError()); 7976 7977 ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize); 7978 ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd); 7979 ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags); 7980 ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount); 7981 ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout); 7982 7983 hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_VISIBLE | WS_POPUPWINDOW, 7984 0, 0, 0, 0, 0, 0, 0, NULL ); 7985 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 7986 finfo.hwnd = hwnd; 7987 7988 SetLastError(0xdeadbeef); 7989 ret = pFlashWindowEx(NULL); 7990 ok(!ret && GetLastError() == ERROR_NOACCESS, 7991 "FlashWindowEx returned with %d\n", GetLastError()); 7992 7993 SetLastError(0xdeadbeef); 7994 prev = pFlashWindowEx(&finfo); 7995 7996 ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize); 7997 ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd); 7998 ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags); 7999 ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount); 8000 ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout); 8001 8002 finfo.dwFlags = FLASHW_STOP; 8003 SetLastError(0xdeadbeef); 8004 ret = pFlashWindowEx(&finfo); 8005 ok(prev != ret, "previous window state should be different\n"); 8006 8007 DestroyWindow( hwnd ); 8008 } 8009 8010 static void test_FindWindowEx(void) 8011 { 8012 HWND hwnd, found; 8013 8014 hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL ); 8015 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 8016 8017 num_gettext_msgs = 0; 8018 found = FindWindowExA( 0, 0, "MainWindowClass", "" ); 8019 ok( found == NULL, "expected a NULL hwnd\n" ); 8020 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 8021 8022 num_gettext_msgs = 0; 8023 found = FindWindowExA( 0, 0, "MainWindowClass", NULL ); 8024 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); 8025 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 8026 8027 num_gettext_msgs = 0; 8028 found = FindWindowExA( 0, 0, "MainWindowClass", "caption" ); 8029 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); 8030 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 8031 8032 DestroyWindow( hwnd ); 8033 8034 hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL ); 8035 ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); 8036 8037 num_gettext_msgs = 0; 8038 found = FindWindowExA( 0, 0, "MainWindowClass", "" ); 8039 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); 8040 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 8041 8042 num_gettext_msgs = 0; 8043 found = FindWindowExA( 0, 0, "MainWindowClass", NULL ); 8044 ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); 8045 ok( num_gettext_msgs == 0, "got %u WM_GETTEXT messages\n", num_gettext_msgs ); 8046 8047 DestroyWindow( hwnd ); 8048 8049 /* test behaviour with a window title that is an empty character */ 8050 found = FindWindowExA( 0, 0, "Shell_TrayWnd", "" ); 8051 ok( found != NULL, "found is NULL, expected a valid hwnd\n" ); 8052 found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL ); 8053 ok( found != NULL, "found is NULL, expected a valid hwnd\n" ); 8054 } 8055 8056 static void test_GetLastActivePopup(void) 8057 { 8058 HWND hwndOwner, hwndPopup1, hwndPopup2; 8059 8060 hwndOwner = CreateWindowExA(0, "MainWindowClass", NULL, 8061 WS_VISIBLE | WS_POPUPWINDOW, 8062 100, 100, 200, 200, 8063 NULL, 0, GetModuleHandleA(NULL), NULL); 8064 hwndPopup1 = CreateWindowExA(0, "MainWindowClass", NULL, 8065 WS_VISIBLE | WS_POPUPWINDOW, 8066 100, 100, 200, 200, 8067 hwndOwner, 0, GetModuleHandleA(NULL), NULL); 8068 hwndPopup2 = CreateWindowExA(0, "MainWindowClass", NULL, 8069 WS_VISIBLE | WS_POPUPWINDOW, 8070 100, 100, 200, 200, 8071 hwndPopup1, 0, GetModuleHandleA(NULL), NULL); 8072 ok( GetLastActivePopup(hwndOwner) == hwndPopup2, "wrong last active popup\n" ); 8073 DestroyWindow( hwndPopup2 ); 8074 DestroyWindow( hwndPopup1 ); 8075 DestroyWindow( hwndOwner ); 8076 } 8077 8078 static LRESULT WINAPI my_httrasparent_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 8079 { 8080 if (msg == WM_NCHITTEST) return HTTRANSPARENT; 8081 return DefWindowProcA(hwnd, msg, wp, lp); 8082 } 8083 8084 static LRESULT WINAPI my_window_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 8085 { 8086 return DefWindowProcA(hwnd, msg, wp, lp); 8087 } 8088 8089 static void create_window_tree(HWND parent, HWND *window, int size) 8090 { 8091 static const DWORD style[] = { 0, WS_VISIBLE, WS_DISABLED, WS_VISIBLE | WS_DISABLED }; 8092 int i, pos; 8093 8094 memset(window, 0, size * sizeof(window[0])); 8095 8096 pos = 0; 8097 for (i = 0; i < sizeof(style)/sizeof(style[0]); i++) 8098 { 8099 assert(pos < size); 8100 window[pos] = CreateWindowExA(0, "my_window", NULL, style[i] | WS_CHILD, 8101 0, 0, 100, 100, parent, 0, 0, NULL); 8102 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8103 pos++; 8104 assert(pos < size); 8105 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_window", NULL, style[i] | WS_CHILD, 8106 0, 0, 100, 100, parent, 0, 0, NULL); 8107 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8108 pos++; 8109 8110 assert(pos < size); 8111 window[pos] = CreateWindowExA(0, "my_httrasparent", NULL, style[i] | WS_CHILD, 8112 0, 0, 100, 100, parent, 0, 0, NULL); 8113 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8114 pos++; 8115 assert(pos < size); 8116 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_httrasparent", NULL, style[i] | WS_CHILD, 8117 0, 0, 100, 100, parent, 0, 0, NULL); 8118 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8119 pos++; 8120 8121 assert(pos < size); 8122 window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX, 8123 0, 0, 100, 100, parent, 0, 0, NULL); 8124 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8125 pos++; 8126 assert(pos < size); 8127 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_GROUPBOX, 8128 0, 0, 100, 100, parent, 0, 0, NULL); 8129 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8130 pos++; 8131 assert(pos < size); 8132 window[pos] = CreateWindowExA(0, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON, 8133 0, 0, 100, 100, parent, 0, 0, NULL); 8134 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8135 pos++; 8136 assert(pos < size); 8137 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "my_button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON, 8138 0, 0, 100, 100, parent, 0, 0, NULL); 8139 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8140 pos++; 8141 8142 assert(pos < size); 8143 window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX, 8144 0, 0, 100, 100, parent, 0, 0, NULL); 8145 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8146 pos++; 8147 assert(pos < size); 8148 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_GROUPBOX, 8149 0, 0, 100, 100, parent, 0, 0, NULL); 8150 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8151 pos++; 8152 assert(pos < size); 8153 window[pos] = CreateWindowExA(0, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON, 8154 0, 0, 100, 100, parent, 0, 0, NULL); 8155 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8156 pos++; 8157 assert(pos < size); 8158 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Button", NULL, style[i] | WS_CHILD | BS_PUSHBUTTON, 8159 0, 0, 100, 100, parent, 0, 0, NULL); 8160 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8161 pos++; 8162 8163 assert(pos < size); 8164 window[pos] = CreateWindowExA(0, "Static", NULL, style[i] | WS_CHILD, 8165 0, 0, 100, 100, parent, 0, 0, NULL); 8166 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8167 pos++; 8168 assert(pos < size); 8169 window[pos] = CreateWindowExA(WS_EX_TRANSPARENT, "Static", NULL, style[i] | WS_CHILD, 8170 0, 0, 100, 100, parent, 0, 0, NULL); 8171 ok(window[pos] != 0, "CreateWindowEx failed\n"); 8172 pos++; 8173 } 8174 } 8175 8176 struct window_attributes 8177 { 8178 char class_name[128]; 8179 BOOL is_visible, is_enabled, is_groupbox, is_httransparent, is_extransparent; 8180 }; 8181 8182 static void get_window_attributes(HWND hwnd, struct window_attributes *attrs) 8183 { 8184 DWORD style, ex_style, hittest; 8185 8186 style = GetWindowLongA(hwnd, GWL_STYLE); 8187 ex_style = GetWindowLongA(hwnd, GWL_EXSTYLE); 8188 attrs->class_name[0] = 0; 8189 GetClassNameA(hwnd, attrs->class_name, sizeof(attrs->class_name)); 8190 hittest = SendMessageA(hwnd, WM_NCHITTEST, 0, 0); 8191 8192 attrs->is_visible = (style & WS_VISIBLE) != 0; 8193 attrs->is_enabled = (style & WS_DISABLED) == 0; 8194 attrs->is_groupbox = !lstrcmpiA(attrs->class_name, "Button") && (style & BS_TYPEMASK) == BS_GROUPBOX; 8195 attrs->is_httransparent = hittest == HTTRANSPARENT; 8196 attrs->is_extransparent = (ex_style & WS_EX_TRANSPARENT) != 0; 8197 } 8198 8199 static int window_to_index(HWND hwnd, HWND *window, int size) 8200 { 8201 int i; 8202 8203 for (i = 0; i < size; i++) 8204 { 8205 if (!window[i]) break; 8206 if (window[i] == hwnd) return i; 8207 } 8208 return -1; 8209 } 8210 8211 static void test_child_window_from_point(void) 8212 { 8213 static const int real_child_pos[] = { 14,15,16,17,18,19,20,21,24,25,26,27,42,43, 8214 44,45,46,47,48,49,52,53,54,55,51,50,23,22,-1 }; 8215 static const int real_child_pos_nt4[] = { 14,15,16,17,20,21,24,25,26,27,42,43,44,45, 8216 48,49,52,53,54,55,51,50,47,46,23,22,19,18,-1 }; 8217 WNDCLASSA cls; 8218 HWND hwnd, parent, window[100]; 8219 POINT pt; 8220 int found_invisible, found_disabled, found_groupbox, found_httransparent, found_extransparent; 8221 int ret, i; 8222 8223 ret = GetClassInfoA(0, "Button", &cls); 8224 ok(ret, "GetClassInfo(Button) failed\n"); 8225 cls.lpszClassName = "my_button"; 8226 ret = RegisterClassA(&cls); 8227 ok(ret, "RegisterClass(my_button) failed\n"); 8228 8229 cls.lpszClassName = "my_httrasparent"; 8230 cls.lpfnWndProc = my_httrasparent_proc; 8231 ret = RegisterClassA(&cls); 8232 ok(ret, "RegisterClass(my_httrasparent) failed\n"); 8233 8234 cls.lpszClassName = "my_window"; 8235 cls.lpfnWndProc = my_window_proc; 8236 ret = RegisterClassA(&cls); 8237 ok(ret, "RegisterClass(my_window) failed\n"); 8238 8239 parent = CreateWindowExA(0, "MainWindowClass", NULL, 8240 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE, 8241 100, 100, 200, 200, 8242 0, 0, GetModuleHandleA(NULL), NULL); 8243 ok(parent != 0, "CreateWindowEx failed\n"); 8244 trace("parent %p\n", parent); 8245 8246 create_window_tree(parent, window, sizeof(window)/sizeof(window[0])); 8247 8248 found_invisible = 0; 8249 found_disabled = 0; 8250 found_groupbox = 0; 8251 found_httransparent = 0; 8252 found_extransparent = 0; 8253 8254 /* FIXME: also test WindowFromPoint, ChildWindowFromPoint, ChildWindowFromPointEx */ 8255 for (i = 0; i < sizeof(real_child_pos)/sizeof(real_child_pos[0]); i++) 8256 { 8257 struct window_attributes attrs; 8258 8259 pt.x = pt.y = 50; 8260 hwnd = RealChildWindowFromPoint(parent, pt); 8261 ok(hwnd != 0, "RealChildWindowFromPoint failed\n"); 8262 ret = window_to_index(hwnd, window, sizeof(window)/sizeof(window[0])); 8263 /* FIXME: remove once Wine is fixed */ 8264 todo_wine_if (ret != real_child_pos[i]) 8265 ok(ret == real_child_pos[i] || broken(ret == real_child_pos_nt4[i]), "expected %d, got %d\n", real_child_pos[i], ret); 8266 8267 get_window_attributes(hwnd, &attrs); 8268 if (!attrs.is_visible) found_invisible++; 8269 if (!attrs.is_enabled) found_disabled++; 8270 if (attrs.is_groupbox) found_groupbox++; 8271 if (attrs.is_httransparent) found_httransparent++; 8272 if (attrs.is_extransparent) found_extransparent++; 8273 8274 if (ret != real_child_pos[i] && ret != -1) 8275 { 8276 trace("found hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n", 8277 hwnd, attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent); 8278 get_window_attributes(window[real_child_pos[i]], &attrs); 8279 trace("expected hwnd %p (%s), is_visible %d, is_enabled %d, is_groupbox %d, is_httransparent %d, is_extransparent %d\n", 8280 window[real_child_pos[i]], attrs.class_name, attrs.is_visible, attrs.is_enabled, attrs.is_groupbox, attrs.is_httransparent, attrs.is_extransparent); 8281 } 8282 if (ret == -1) 8283 { 8284 ok(hwnd == parent, "expected %p, got %p\n", parent, hwnd); 8285 break; 8286 } 8287 DestroyWindow(hwnd); 8288 } 8289 8290 DestroyWindow(parent); 8291 8292 ok(!found_invisible, "found %d invisible windows\n", found_invisible); 8293 ok(found_disabled, "found %d disabled windows\n", found_disabled); 8294 todo_wine 8295 ok(found_groupbox == 4, "found %d groupbox windows\n", found_groupbox); 8296 ok(found_httransparent, "found %d httransparent windows\n", found_httransparent); 8297 todo_wine 8298 ok(found_extransparent, "found %d extransparent windows\n", found_extransparent); 8299 8300 ret = UnregisterClassA("my_button", cls.hInstance); 8301 ok(ret, "UnregisterClass(my_button) failed\n"); 8302 ret = UnregisterClassA("my_httrasparent", cls.hInstance); 8303 ok(ret, "UnregisterClass(my_httrasparent) failed\n"); 8304 ret = UnregisterClassA("my_window", cls.hInstance); 8305 ok(ret, "UnregisterClass(my_window) failed\n"); 8306 } 8307 8308 static void simulate_click(int x, int y) 8309 { 8310 INPUT input[2]; 8311 UINT events_no; 8312 8313 SetCursorPos(x, y); 8314 memset(input, 0, sizeof(input)); 8315 input[0].type = INPUT_MOUSE; 8316 U(input[0]).mi.dx = x; 8317 U(input[0]).mi.dy = y; 8318 U(input[0]).mi.dwFlags = MOUSEEVENTF_LEFTDOWN; 8319 input[1].type = INPUT_MOUSE; 8320 U(input[1]).mi.dx = x; 8321 U(input[1]).mi.dy = y; 8322 U(input[1]).mi.dwFlags = MOUSEEVENTF_LEFTUP; 8323 events_no = SendInput(2, input, sizeof(input[0])); 8324 ok(events_no == 2, "SendInput returned %d\n", events_no); 8325 } 8326 8327 static WNDPROC def_static_proc; 8328 static BOOL got_hittest; 8329 static LRESULT WINAPI static_hook_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 8330 { 8331 if(msg == WM_NCHITTEST) 8332 got_hittest = TRUE; 8333 if(msg == WM_LBUTTONDOWN) 8334 ok(0, "unexpected call\n"); 8335 8336 return def_static_proc(hwnd, msg, wp, lp); 8337 } 8338 8339 static void window_from_point_proc(HWND parent) 8340 { 8341 HANDLE start_event, end_event; 8342 HANDLE win, child_static, child_button; 8343 BOOL got_click; 8344 DWORD ret; 8345 POINT pt; 8346 MSG msg; 8347 8348 start_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_start"); 8349 ok(start_event != 0, "OpenEvent failed\n"); 8350 end_event = OpenEventA(EVENT_ALL_ACCESS, FALSE, "test_wfp_end"); 8351 ok(end_event != 0, "OpenEvent failed\n"); 8352 8353 child_static = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE, 8354 0, 0, 100, 100, parent, 0, NULL, NULL); 8355 ok(child_static != 0, "CreateWindowEx failed\n"); 8356 pt.x = pt.y = 150; 8357 win = WindowFromPoint(pt); 8358 ok(win == parent, "WindowFromPoint returned %p, expected %p\n", win, parent); 8359 8360 child_button = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE, 8361 100, 0, 100, 100, parent, 0, NULL, NULL); 8362 ok(child_button != 0, "CreateWindowEx failed\n"); 8363 pt.x = 250; 8364 win = WindowFromPoint(pt); 8365 ok(win == child_button, "WindowFromPoint returned %p, expected %p\n", win, child_button); 8366 8367 /* without this window simulate click test keeps sending WM_NCHITTEST 8368 * message to child_static in an infinite loop */ 8369 win = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE, 8370 0, 0, 100, 100, parent, 0, NULL, NULL); 8371 ok(win != 0, "CreateWindowEx failed\n"); 8372 def_static_proc = (void*)SetWindowLongPtrA(child_static, 8373 GWLP_WNDPROC, (LONG_PTR)static_hook_proc); 8374 flush_events(TRUE); 8375 SetEvent(start_event); 8376 8377 got_hittest = FALSE; 8378 got_click = FALSE; 8379 while(!got_click && wait_for_message(&msg)) { 8380 if(msg.message == WM_LBUTTONUP) { 8381 ok(msg.hwnd == win, "msg.hwnd = %p, expected %p\n", msg.hwnd, win); 8382 got_click = TRUE; 8383 } 8384 DispatchMessageA(&msg); 8385 } 8386 ok(got_hittest, "transparent window didn't get WM_NCHITTEST message\n"); 8387 ok(got_click, "button under static window didn't get WM_LBUTTONUP\n"); 8388 8389 ret = WaitForSingleObject(end_event, 5000); 8390 ok(ret == WAIT_OBJECT_0, "WaitForSingleObject returned %x\n", ret); 8391 8392 CloseHandle(start_event); 8393 CloseHandle(end_event); 8394 } 8395 8396 static void test_window_from_point(const char *argv0) 8397 { 8398 HWND hwnd, child, win; 8399 POINT pt; 8400 PROCESS_INFORMATION info; 8401 STARTUPINFOA startup; 8402 char cmd[MAX_PATH]; 8403 HANDLE start_event, end_event; 8404 8405 hwnd = CreateWindowExA(0, "MainWindowClass", NULL, WS_POPUP | WS_VISIBLE, 8406 100, 100, 200, 100, 0, 0, NULL, NULL); 8407 ok(hwnd != 0, "CreateWindowEx failed\n"); 8408 8409 pt.x = pt.y = 150; 8410 win = WindowFromPoint(pt); 8411 pt.x = 250; 8412 if(win == hwnd) 8413 win = WindowFromPoint(pt); 8414 if(win != hwnd) { 8415 skip("there's another window covering test window\n"); 8416 DestroyWindow(hwnd); 8417 return; 8418 } 8419 8420 child = CreateWindowExA(0, "static", "static", WS_CHILD | WS_VISIBLE, 8421 0, 0, 100, 100, hwnd, 0, NULL, NULL); 8422 ok(child != 0, "CreateWindowEx failed\n"); 8423 pt.x = pt.y = 150; 8424 win = WindowFromPoint(pt); 8425 ok(win == hwnd, "WindowFromPoint returned %p, expected %p\n", win, hwnd); 8426 DestroyWindow(child); 8427 8428 child = CreateWindowExA(0, "button", "button", WS_CHILD | WS_VISIBLE, 8429 0, 0, 100, 100, hwnd, 0, NULL, NULL); 8430 ok(child != 0, "CreateWindowEx failed\n"); 8431 win = WindowFromPoint(pt); 8432 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child); 8433 DestroyWindow(child); 8434 8435 start_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_start"); 8436 ok(start_event != 0, "CreateEvent failed\n"); 8437 end_event = CreateEventA(NULL, FALSE, FALSE, "test_wfp_end"); 8438 ok(start_event != 0, "CreateEvent failed\n"); 8439 8440 sprintf(cmd, "%s win create_children %p\n", argv0, hwnd); 8441 memset(&startup, 0, sizeof(startup)); 8442 startup.cb = sizeof(startup); 8443 ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, 8444 &startup, &info), "CreateProcess failed.\n"); 8445 ok(wait_for_event(start_event, 1000), "didn't get start_event\n"); 8446 8447 child = GetWindow(hwnd, GW_CHILD); 8448 win = WindowFromPoint(pt); 8449 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child); 8450 8451 simulate_click(150, 150); 8452 flush_events(TRUE); 8453 8454 child = GetWindow(child, GW_HWNDNEXT); 8455 pt.x = 250; 8456 win = WindowFromPoint(pt); 8457 ok(win == child, "WindowFromPoint returned %p, expected %p\n", win, child); 8458 8459 SetEvent(end_event); 8460 winetest_wait_child_process(info.hProcess); 8461 CloseHandle(start_event); 8462 CloseHandle(end_event); 8463 CloseHandle(info.hProcess); 8464 CloseHandle(info.hThread); 8465 8466 DestroyWindow(hwnd); 8467 } 8468 8469 static void test_map_points(void) 8470 { 8471 BOOL ret; 8472 POINT p; 8473 HWND wnd, wnd0, dwnd; 8474 INT n; 8475 DWORD err; 8476 POINT pos = { 100, 200 }; 8477 int width = 150; 8478 int height = 150; 8479 RECT window_rect; 8480 RECT client_rect; 8481 8482 /* Create test windows */ 8483 wnd = CreateWindowA("static", "test1", WS_POPUP, pos.x, pos.y, width, height, NULL, NULL, NULL, NULL); 8484 ok(wnd != NULL, "Failed %p\n", wnd); 8485 wnd0 = CreateWindowA("static", "test2", WS_POPUP, 0, 0, width, height, NULL, NULL, NULL, NULL); 8486 ok(wnd0 != NULL, "Failed %p\n", wnd); 8487 dwnd = CreateWindowA("static", "test3", 0, 200, 300, 150, 150, NULL, NULL, NULL, NULL); 8488 DestroyWindow(dwnd); 8489 ok(dwnd != NULL, "Failed %p\n", dwnd); 8490 8491 /* Verify window rect and client rect (they should have the same width and height) */ 8492 GetWindowRect(wnd, &window_rect); 8493 ok(window_rect.left == pos.x, "left is %d instead of %d\n", window_rect.left, pos.x); 8494 ok(window_rect.top == pos.y, "top is %d instead of %d\n", window_rect.top, pos.y); 8495 ok(window_rect.right == pos.x + width, "right is %d instead of %d\n", window_rect.right, pos.x + width); 8496 ok(window_rect.bottom == pos.y + height, "bottom is %d instead of %d\n", window_rect.bottom, pos.y + height); 8497 GetClientRect(wnd, &client_rect); 8498 ok(client_rect.left == 0, "left is %d instead of 0\n", client_rect.left); 8499 ok(client_rect.top == 0, "top is %d instead of 0\n", client_rect.top); 8500 ok(client_rect.right == width, "right is %d instead of %d\n", client_rect.right, width); 8501 ok(client_rect.bottom == height, "bottom is %d instead of %d\n", client_rect.bottom, height); 8502 8503 /* Test MapWindowPoints */ 8504 8505 /* MapWindowPoints(NULL or wnd, NULL or wnd, NULL, 1); crashes on Windows */ 8506 8507 SetLastError(0xdeadbeef); 8508 n = MapWindowPoints(NULL, NULL, NULL, 0); 8509 err = GetLastError(); 8510 ok(n == 0, "Got %d, expected %d\n", n, 0); 8511 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8512 8513 SetLastError(0xdeadbeef); 8514 n = MapWindowPoints(wnd, wnd, NULL, 0); 8515 err = GetLastError(); 8516 ok(n == 0, "Got %d, expected %d\n", n, 0); 8517 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8518 8519 n = MapWindowPoints(wnd, NULL, NULL, 0); 8520 ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n", 8521 n, MAKELONG(window_rect.left, window_rect.top)); 8522 8523 n = MapWindowPoints(NULL, wnd, NULL, 0); 8524 ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n", 8525 n, MAKELONG(-window_rect.left, -window_rect.top)); 8526 8527 SetLastError(0xdeadbeef); 8528 p.x = p.y = 100; 8529 n = MapWindowPoints(dwnd, NULL, &p, 1); 8530 err = GetLastError(); 8531 ok(n == 0, "Got %d, expected %d\n", n, 0); 8532 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8533 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8534 8535 SetLastError(0xdeadbeef); 8536 p.x = p.y = 100; 8537 n = MapWindowPoints(dwnd, wnd, &p, 1); 8538 err = GetLastError(); 8539 ok(n == 0, "Got %d, expected %d\n", n, 0); 8540 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8541 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8542 8543 SetLastError(0xdeadbeef); 8544 p.x = p.y = 100; 8545 n = MapWindowPoints(NULL, dwnd, &p, 1); 8546 err = GetLastError(); 8547 ok(n == 0, "Got %d, expected %d\n", n, 0); 8548 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8549 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8550 8551 SetLastError(0xdeadbeef); 8552 p.x = p.y = 100; 8553 n = MapWindowPoints(wnd, dwnd, &p, 1); 8554 err = GetLastError(); 8555 ok(n == 0, "Got %d, expected %d\n", n, 0); 8556 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8557 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8558 8559 SetLastError(0xdeadbeef); 8560 p.x = p.y = 100; 8561 n = MapWindowPoints(dwnd, dwnd, &p, 1); 8562 err = GetLastError(); 8563 ok(n == 0, "Got %d, expected %d\n", n, 0); 8564 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8565 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8566 8567 SetLastError(0xdeadbeef); 8568 p.x = p.y = 100; 8569 n = MapWindowPoints(NULL, NULL, &p, 1); 8570 err = GetLastError(); 8571 ok(n == 0, "Got %d, expected %d\n", n, 0); 8572 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8573 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8574 8575 SetLastError(0xdeadbeef); 8576 p.x = p.y = 100; 8577 n = MapWindowPoints(wnd, wnd, &p, 1); 8578 err = GetLastError(); 8579 ok(n == 0, "Got %d, expected %d\n", n, 0); 8580 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8581 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8582 8583 p.x = p.y = 100; 8584 n = MapWindowPoints(wnd, NULL, &p, 1); 8585 ok(n == MAKELONG(window_rect.left, window_rect.top), "Got %x, expected %x\n", 8586 n, MAKELONG(window_rect.left, window_rect.top)); 8587 ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n", 8588 p.x, p.y, window_rect.left + 100, window_rect.top + 100); 8589 8590 p.x = p.y = 100; 8591 n = MapWindowPoints(NULL, wnd, &p, 1); 8592 ok(n == MAKELONG(-window_rect.left, -window_rect.top), "Got %x, expected %x\n", 8593 n, MAKELONG(-window_rect.left, -window_rect.top)); 8594 ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n", 8595 p.x, p.y, -window_rect.left + 100, -window_rect.top + 100); 8596 8597 SetLastError(0xdeadbeef); 8598 p.x = p.y = 0; 8599 n = MapWindowPoints(wnd0, NULL, &p, 1); 8600 err = GetLastError(); 8601 ok(n == 0, "Got %x, expected 0\n", n); 8602 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y); 8603 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8604 8605 SetLastError(0xdeadbeef); 8606 p.x = p.y = 0; 8607 n = MapWindowPoints(NULL, wnd0, &p, 1); 8608 err = GetLastError(); 8609 ok(n == 0, "Got %x, expected 0\n", n); 8610 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y); 8611 ok(err == 0xdeadbeef, "Got %x, expected %x\n", err, 0xdeadbeef); 8612 8613 /* Test ClientToScreen */ 8614 8615 /* ClientToScreen(wnd, NULL); crashes on Windows */ 8616 8617 SetLastError(0xdeadbeef); 8618 ret = ClientToScreen(NULL, NULL); 8619 err = GetLastError(); 8620 ok(!ret, "Should fail\n"); 8621 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8622 8623 SetLastError(0xdeadbeef); 8624 p.x = p.y = 100; 8625 ret = ClientToScreen(NULL, &p); 8626 err = GetLastError(); 8627 ok(!ret, "Should fail\n"); 8628 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8629 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8630 8631 SetLastError(0xdeadbeef); 8632 p.x = p.y = 100; 8633 ret = ClientToScreen(dwnd, &p); 8634 err = GetLastError(); 8635 ok(!ret, "Should fail\n"); 8636 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8637 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8638 8639 p.x = p.y = 100; 8640 ret = ClientToScreen(wnd, &p); 8641 ok(ret, "Failed with error %u\n", GetLastError()); 8642 ok((p.x == (window_rect.left + 100)) && (p.y == (window_rect.top + 100)), "Failed got (%d, %d), expected (%d, %d)\n", 8643 p.x, p.y, window_rect.left + 100, window_rect.top + 100); 8644 8645 p.x = p.y = 0; 8646 ret = ClientToScreen(wnd0, &p); 8647 ok(ret, "Failed with error %u\n", GetLastError()); 8648 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y); 8649 8650 /* Test ScreenToClient */ 8651 8652 /* ScreenToClient(wnd, NULL); crashes on Windows */ 8653 8654 SetLastError(0xdeadbeef); 8655 ret = ScreenToClient(NULL, NULL); 8656 err = GetLastError(); 8657 ok(!ret, "Should fail\n"); 8658 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8659 8660 SetLastError(0xdeadbeef); 8661 p.x = p.y = 100; 8662 ret = ScreenToClient(NULL, &p); 8663 err = GetLastError(); 8664 ok(!ret, "Should fail\n"); 8665 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8666 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8667 8668 SetLastError(0xdeadbeef); 8669 p.x = p.y = 100; 8670 ret = ScreenToClient(dwnd, &p); 8671 err = GetLastError(); 8672 ok(!ret, "Should fail\n"); 8673 ok(p.x == 100 && p.y == 100, "Failed got(%d, %d), expected (%d, %d)\n", p.x, p.y, 100, 100); 8674 ok(err == ERROR_INVALID_WINDOW_HANDLE, "Got %x, expected %x\n", err, ERROR_INVALID_WINDOW_HANDLE); 8675 8676 p.x = p.y = 100; 8677 ret = ScreenToClient(wnd, &p); 8678 ok(ret, "Failed with error %u\n", GetLastError()); 8679 ok((p.x == (-window_rect.left + 100)) && (p.y == (-window_rect.top + 100)), "Failed got(%d, %d), expected (%d, %d)\n", 8680 p.x, p.y, -window_rect.left + 100, -window_rect.top + 100); 8681 8682 p.x = p.y = 0; 8683 ret = ScreenToClient(wnd0, &p); 8684 ok(ret, "Failed with error %u\n", GetLastError()); 8685 ok((p.x == 0) && (p.y == 0), "Failed got (%d, %d), expected (0, 0)\n", p.x, p.y); 8686 8687 DestroyWindow(wnd); 8688 DestroyWindow(wnd0); 8689 } 8690 8691 static void test_update_region(void) 8692 { 8693 HWND hwnd, parent, child; 8694 HRGN rgn1, rgn2; 8695 const RECT rc = {15, 15, 40, 40}; 8696 const POINT wnd_orig = {30, 20}; 8697 const POINT child_orig = {10, 5}; 8698 8699 parent = CreateWindowExA(0, "MainWindowClass", NULL, 8700 WS_VISIBLE | WS_CLIPCHILDREN, 8701 0, 0, 300, 150, NULL, NULL, GetModuleHandleA(0), 0); 8702 hwnd = CreateWindowExA(0, "MainWindowClass", NULL, 8703 WS_VISIBLE | WS_CLIPCHILDREN | WS_CHILD, 8704 0, 0, 200, 100, parent, NULL, GetModuleHandleA(0), 0); 8705 child = CreateWindowExA(0, "MainWindowClass", NULL, 8706 WS_VISIBLE | WS_CHILD, 8707 child_orig.x, child_orig.y, 100, 50, 8708 hwnd, NULL, GetModuleHandleA(0), 0); 8709 assert(parent && hwnd && child); 8710 8711 ValidateRgn(parent, NULL); 8712 ValidateRgn(hwnd, NULL); 8713 InvalidateRect(hwnd, &rc, FALSE); 8714 ValidateRgn(child, NULL); 8715 8716 rgn1 = CreateRectRgn(0, 0, 0, 0); 8717 ok(GetUpdateRgn(parent, rgn1, FALSE) == NULLREGION, 8718 "has invalid area after ValidateRgn(NULL)\n"); 8719 GetUpdateRgn(hwnd, rgn1, FALSE); 8720 rgn2 = CreateRectRgnIndirect(&rc); 8721 ok(EqualRgn(rgn1, rgn2), "assigned and retrieved update regions are different\n"); 8722 ok(GetUpdateRgn(child, rgn2, FALSE) == NULLREGION, 8723 "has invalid area after ValidateRgn(NULL)\n"); 8724 8725 SetWindowPos(hwnd, 0, wnd_orig.x, wnd_orig.y, 0, 0, 8726 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE); 8727 8728 /* parent now has non-simple update region, it consist of 8729 * two rects, that was exposed after hwnd moving ... */ 8730 SetRectRgn(rgn1, 0, 0, 200, wnd_orig.y); 8731 SetRectRgn(rgn2, 0, 0, wnd_orig.x, 100); 8732 CombineRgn(rgn1, rgn1, rgn2, RGN_OR); 8733 /* ... and mapped hwnd's invalid area, that hwnd has before moving */ 8734 SetRectRgn(rgn2, rc.left + wnd_orig.x, rc.top + wnd_orig.y, 8735 rc.right + wnd_orig.x, rc.bottom + wnd_orig.y); 8736 CombineRgn(rgn1, rgn1, rgn2, RGN_OR); 8737 GetUpdateRgn(parent, rgn2, FALSE); 8738 todo_wine 8739 ok(EqualRgn(rgn1, rgn2), "wrong update region\n"); 8740 8741 /* hwnd has the same invalid region as before moving */ 8742 SetRectRgn(rgn1, rc.left, rc.top, rc.right, rc.bottom); 8743 GetUpdateRgn(hwnd, rgn2, FALSE); 8744 ok(EqualRgn(rgn1, rgn2), "wrong update region\n"); 8745 8746 /* hwnd's invalid area maps to child during moving */ 8747 SetRectRgn(rgn1, rc.left - child_orig.x , rc.top - child_orig.y, 8748 rc.right - child_orig.x, rc.bottom - child_orig.y); 8749 GetUpdateRgn(child, rgn2, FALSE); 8750 todo_wine 8751 ok(EqualRgn(rgn1, rgn2), "wrong update region\n"); 8752 8753 DeleteObject(rgn1); 8754 DeleteObject(rgn2); 8755 DestroyWindow(parent); 8756 } 8757 8758 static void test_window_without_child_style(void) 8759 { 8760 HWND hwnd; 8761 8762 hwnd = CreateWindowExA(0, "edit", NULL, WS_VISIBLE|WS_CHILD, 8763 0, 0, 50, 50, hwndMain, NULL, 0, NULL); 8764 ok(hwnd != NULL, "CreateWindow failed\n"); 8765 8766 ok(SetWindowLongA(hwnd, GWL_STYLE, GetWindowLongA(hwnd, GWL_STYLE) & (~WS_CHILD)), 8767 "can't remove WS_CHILD style\n"); 8768 8769 SetActiveWindow(hwndMain); 8770 PostMessageW(hwnd, WM_LBUTTONUP, 0, 0); 8771 SendMessageW(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0); 8772 check_active_state(hwnd, hwnd, hwnd); 8773 flush_events(TRUE); 8774 8775 DestroyWindow(hwnd); 8776 } 8777 8778 8779 struct smresult_thread_data 8780 { 8781 HWND main_hwnd; 8782 HWND thread_hwnd; 8783 HANDLE thread_started; 8784 HANDLE thread_got_wm_app; 8785 HANDLE main_in_wm_app_1; 8786 HANDLE thread_replied; 8787 }; 8788 8789 8790 static LRESULT WINAPI smresult_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 8791 { 8792 switch (msg) 8793 { 8794 case WM_APP: 8795 { 8796 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam; 8797 8798 ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd); 8799 8800 SendNotifyMessageA(data->main_hwnd, WM_APP+1, 0, lparam); 8801 8802 /* Don't return until the main thread is processing our sent message. */ 8803 ok(WaitForSingleObject(data->main_in_wm_app_1, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8804 8805 /* Break the PeekMessage loop so we can notify the main thread after we return. */ 8806 SetEvent(data->thread_got_wm_app); 8807 8808 return 0x240408ea; 8809 } 8810 case WM_APP+1: 8811 { 8812 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam; 8813 LRESULT res; 8814 8815 ok(hwnd == data->main_hwnd, "unexpected hwnd %p\n", hwnd); 8816 8817 /* Ask the thread to reply to our WM_APP message. */ 8818 SetEvent(data->main_in_wm_app_1); 8819 8820 /* Wait until the thread has sent a reply. */ 8821 ok(WaitForSingleObject(data->thread_replied, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8822 8823 /* Send another message while we have a reply queued for the current one. */ 8824 res = SendMessageA(data->thread_hwnd, WM_APP+2, 0, lparam); 8825 ok(res == 0x449b0190, "unexpected result %lx\n", res); 8826 8827 return 0; 8828 } 8829 case WM_APP+2: 8830 { 8831 struct smresult_thread_data *data = (struct smresult_thread_data*)lparam; 8832 8833 ok(hwnd == data->thread_hwnd, "unexpected hwnd %p\n", hwnd); 8834 8835 /* Don't return until we know the main thread is processing sent messages. */ 8836 SendMessageA(data->main_hwnd, WM_NULL, 0, 0); 8837 8838 return 0x449b0190; 8839 } 8840 case WM_CLOSE: 8841 PostQuitMessage(0); 8842 break; 8843 } 8844 return DefWindowProcA(hwnd, msg, wparam, lparam); 8845 } 8846 8847 static DWORD WINAPI smresult_thread_proc(void *param) 8848 { 8849 MSG msg; 8850 struct smresult_thread_data *data = param; 8851 8852 data->thread_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW, 8853 100, 100, 200, 200, 0, 0, 0, NULL); 8854 ok(data->thread_hwnd != 0, "Failed to create overlapped window\n"); 8855 8856 SetEvent(data->thread_started); 8857 8858 /* Loop until we've processed WM_APP. */ 8859 while (WaitForSingleObject(data->thread_got_wm_app, 0) != WAIT_OBJECT_0) 8860 { 8861 if (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 8862 { 8863 TranslateMessage(&msg); 8864 DispatchMessageA(&msg); 8865 } 8866 else 8867 { 8868 MsgWaitForMultipleObjects(1, &data->thread_got_wm_app, FALSE, INFINITE, QS_SENDMESSAGE); 8869 } 8870 } 8871 8872 /* Notify the main thread that we replied to its WM_APP message. */ 8873 SetEvent(data->thread_replied); 8874 8875 while (GetMessageA(&msg, 0, 0, 0)) 8876 { 8877 TranslateMessage(&msg); 8878 DispatchMessageA(&msg); 8879 } 8880 8881 return 0; 8882 } 8883 8884 static void test_smresult(void) 8885 { 8886 WNDCLASSA cls; 8887 HANDLE hThread; 8888 DWORD tid; 8889 struct smresult_thread_data data; 8890 BOOL ret; 8891 LRESULT res; 8892 8893 cls.style = CS_DBLCLKS; 8894 cls.lpfnWndProc = smresult_wndproc; 8895 cls.cbClsExtra = 0; 8896 cls.cbWndExtra = 0; 8897 cls.hInstance = GetModuleHandleA(0); 8898 cls.hIcon = 0; 8899 cls.hCursor = LoadCursorA(0, (LPCSTR)IDC_ARROW); 8900 cls.hbrBackground = GetStockObject(WHITE_BRUSH); 8901 cls.lpszMenuName = NULL; 8902 cls.lpszClassName = "SmresultClass"; 8903 8904 ret = RegisterClassA(&cls); 8905 ok(ret, "RegisterClassA failed\n"); 8906 8907 data.thread_started = CreateEventA(NULL, TRUE, FALSE, NULL); 8908 ok(data.thread_started != NULL, "CreateEventA failed\n"); 8909 8910 data.thread_got_wm_app = CreateEventA(NULL, TRUE, FALSE, NULL); 8911 ok(data.thread_got_wm_app != NULL, "CreateEventA failed\n"); 8912 8913 data.main_in_wm_app_1 = CreateEventA(NULL, TRUE, FALSE, NULL); 8914 ok(data.main_in_wm_app_1 != NULL, "CreateEventA failed\n"); 8915 8916 data.thread_replied = CreateEventA(NULL, TRUE, FALSE, NULL); 8917 ok(data.thread_replied != NULL, "CreateEventA failed\n"); 8918 8919 data.main_hwnd = CreateWindowExA(0, "SmresultClass", "window caption text", WS_OVERLAPPEDWINDOW, 8920 100, 100, 200, 200, 0, 0, 0, NULL); 8921 8922 hThread = CreateThread(NULL, 0, smresult_thread_proc, &data, 0, &tid); 8923 ok(hThread != NULL, "CreateThread failed, error %d\n", GetLastError()); 8924 8925 ok(WaitForSingleObject(data.thread_started, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8926 8927 res = SendMessageA(data.thread_hwnd, WM_APP, 0, (LPARAM)&data); 8928 ok(res == 0x240408ea, "unexpected result %lx\n", res); 8929 8930 SendMessageA(data.thread_hwnd, WM_CLOSE, 0, 0); 8931 8932 DestroyWindow(data.main_hwnd); 8933 8934 ok(WaitForSingleObject(hThread, INFINITE) == WAIT_OBJECT_0, "WaitForSingleObject failed\n"); 8935 8936 CloseHandle(data.thread_started); 8937 CloseHandle(data.thread_got_wm_app); 8938 CloseHandle(data.main_in_wm_app_1); 8939 CloseHandle(data.thread_replied); 8940 } 8941 8942 static void test_GetMessagePos(void) 8943 { 8944 HWND button; 8945 DWORD pos; 8946 MSG msg; 8947 8948 button = CreateWindowExA(0, "button", "button", WS_VISIBLE, 8949 100, 100, 100, 100, 0, 0, 0, NULL); 8950 ok(button != 0, "CreateWindowExA failed\n"); 8951 8952 SetCursorPos(120, 140); 8953 flush_events(TRUE); 8954 pos = GetMessagePos(); 8955 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos); 8956 8957 SetCursorPos(340, 320); 8958 pos = GetMessagePos(); 8959 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos); 8960 8961 SendMessageW(button, WM_APP, 0, 0); 8962 pos = GetMessagePos(); 8963 ok(pos == MAKELONG(120, 140), "pos = %08x\n", pos); 8964 8965 PostMessageA(button, WM_APP, 0, 0); 8966 GetMessageA(&msg, button, 0, 0); 8967 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message); 8968 pos = GetMessagePos(); 8969 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos); 8970 8971 PostMessageA(button, WM_APP, 0, 0); 8972 SetCursorPos(350, 330); 8973 GetMessageA(&msg, button, 0, 0); 8974 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message); 8975 pos = GetMessagePos(); 8976 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos); 8977 8978 PostMessageA(button, WM_APP, 0, 0); 8979 SetCursorPos(320, 340); 8980 PostMessageA(button, WM_APP+1, 0, 0); 8981 pos = GetMessagePos(); 8982 ok(pos == MAKELONG(340, 320), "pos = %08x\n", pos); 8983 GetMessageA(&msg, button, 0, 0); 8984 ok(msg.message == WM_APP, "msg.message = %x\n", msg.message); 8985 pos = GetMessagePos(); 8986 ok(pos == MAKELONG(350, 330), "pos = %08x\n", pos); 8987 GetMessageA(&msg, button, 0, 0); 8988 ok(msg.message == WM_APP+1, "msg.message = %x\n", msg.message); 8989 pos = GetMessagePos(); 8990 ok(pos == MAKELONG(320, 340), "pos = %08x\n", pos); 8991 8992 SetTimer(button, 1, 250, NULL); 8993 SetCursorPos(330, 350); 8994 GetMessageA(&msg, button, 0, 0); 8995 while (msg.message == WM_PAINT) 8996 { 8997 UpdateWindow( button ); 8998 GetMessageA(&msg, button, 0, 0); 8999 } 9000 ok(msg.message == WM_TIMER, "msg.message = %x\n", msg.message); 9001 pos = GetMessagePos(); 9002 ok(pos == MAKELONG(330, 350), "pos = %08x\n", pos); 9003 KillTimer(button, 1); 9004 9005 DestroyWindow(button); 9006 } 9007 9008 #define SET_FOREGROUND_STEAL_1 0x01 9009 #define SET_FOREGROUND_SET_1 0x02 9010 #define SET_FOREGROUND_STEAL_2 0x04 9011 #define SET_FOREGROUND_SET_2 0x08 9012 #define SET_FOREGROUND_INJECT 0x10 9013 9014 struct set_foreground_thread_params 9015 { 9016 UINT msg_quit, msg_command; 9017 HWND window1, window2, thread_window; 9018 HANDLE command_executed; 9019 }; 9020 9021 static DWORD WINAPI set_foreground_thread(void *params) 9022 { 9023 struct set_foreground_thread_params *p = params; 9024 MSG msg; 9025 9026 p->thread_window = CreateWindowExA(0, "static", "thread window", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 9027 0, 0, 10, 10, 0, 0, 0, NULL); 9028 SetEvent(p->command_executed); 9029 9030 while(GetMessageA(&msg, 0, 0, 0)) 9031 { 9032 if (msg.message == p->msg_quit) 9033 break; 9034 9035 if (msg.message == p->msg_command) 9036 { 9037 if (msg.wParam & SET_FOREGROUND_STEAL_1) 9038 { 9039 SetForegroundWindow(p->thread_window); 9040 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0); 9041 } 9042 if (msg.wParam & SET_FOREGROUND_INJECT) 9043 { 9044 SendNotifyMessageA(p->window1, WM_ACTIVATEAPP, 0, 0); 9045 } 9046 if (msg.wParam & SET_FOREGROUND_SET_1) 9047 { 9048 SetForegroundWindow(p->window1); 9049 check_wnd_state(0, p->window1, 0, 0); 9050 } 9051 if (msg.wParam & SET_FOREGROUND_STEAL_2) 9052 { 9053 SetForegroundWindow(p->thread_window); 9054 check_wnd_state(p->thread_window, p->thread_window, p->thread_window, 0); 9055 } 9056 if (msg.wParam & SET_FOREGROUND_SET_2) 9057 { 9058 SetForegroundWindow(p->window2); 9059 check_wnd_state(0, p->window2, 0, 0); 9060 } 9061 9062 SetEvent(p->command_executed); 9063 continue; 9064 } 9065 9066 TranslateMessage(&msg); 9067 DispatchMessageA(&msg); 9068 } 9069 9070 DestroyWindow(p->thread_window); 9071 return 0; 9072 } 9073 9074 static void test_activateapp(HWND window1) 9075 { 9076 HWND window2, test_window; 9077 HANDLE thread; 9078 struct set_foreground_thread_params thread_params; 9079 DWORD tid; 9080 MSG msg; 9081 9082 window2 = CreateWindowExA(0, "static", "window 2", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 9083 300, 0, 10, 10, 0, 0, 0, NULL); 9084 thread_params.msg_quit = WM_USER; 9085 thread_params.msg_command = WM_USER + 1; 9086 thread_params.window1 = window1; 9087 thread_params.window2 = window2; 9088 thread_params.command_executed = CreateEventW(NULL, FALSE, FALSE, NULL); 9089 9090 thread = CreateThread(NULL, 0, set_foreground_thread, &thread_params, 0, &tid); 9091 WaitForSingleObject(thread_params.command_executed, INFINITE); 9092 9093 SetForegroundWindow(window1); 9094 check_wnd_state(window1, window1, window1, 0); 9095 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9096 9097 /* Steal foreground: WM_ACTIVATEAPP(0) is delivered. */ 9098 app_activated = app_deactivated = FALSE; 9099 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1, 0); 9100 WaitForSingleObject(thread_params.command_executed, INFINITE); 9101 test_window = GetForegroundWindow(); 9102 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n", 9103 thread_params.thread_window, test_window); 9104 /* Active and Focus window are sometimes 0 on KDE. Ignore them. 9105 * check_wnd_state(window1, thread_params.thread_window, window1, 0); */ 9106 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9107 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9108 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9109 check_wnd_state(0, thread_params.thread_window, 0, 0); 9110 test_window = GetForegroundWindow(); 9111 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n", 9112 thread_params.thread_window, test_window); 9113 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9114 /* This message is reliable on Windows and inside a virtual desktop. 9115 * It is unreliable on KDE (50/50) and never arrives on FVWM. 9116 * ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); */ 9117 9118 /* Set foreground: WM_ACTIVATEAPP (1) is delivered. */ 9119 app_activated = app_deactivated = FALSE; 9120 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1, 0); 9121 WaitForSingleObject(thread_params.command_executed, INFINITE); 9122 check_wnd_state(0, 0, 0, 0); 9123 test_window = GetForegroundWindow(); 9124 ok(!test_window, "Expected foreground window 0, got %p\n", test_window); 9125 ok(!app_activated, "Received WM_ACTIVATEAPP(!= 0), did not expect it.\n"); 9126 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9127 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9128 check_wnd_state(window1, window1, window1, 0); 9129 test_window = GetForegroundWindow(); 9130 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9131 window1, test_window); 9132 ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n"); 9133 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9134 9135 /* Steal foreground then set it back: No messages are delivered. */ 9136 app_activated = app_deactivated = FALSE; 9137 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_1, 0); 9138 WaitForSingleObject(thread_params.command_executed, INFINITE); 9139 test_window = GetForegroundWindow(); 9140 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9141 window1, test_window); 9142 check_wnd_state(window1, window1, window1, 0); 9143 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9144 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9145 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9146 test_window = GetForegroundWindow(); 9147 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9148 window1, test_window); 9149 check_wnd_state(window1, window1, window1, 0); 9150 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9151 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9152 9153 /* This is not implemented with a plain WM_ACTIVATEAPP filter. */ 9154 app_activated = app_deactivated = FALSE; 9155 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 9156 | SET_FOREGROUND_INJECT | SET_FOREGROUND_SET_1, 0); 9157 WaitForSingleObject(thread_params.command_executed, INFINITE); 9158 test_window = GetForegroundWindow(); 9159 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9160 window1, test_window); 9161 check_wnd_state(window1, window1, window1, 0); 9162 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9163 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9164 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9165 test_window = GetForegroundWindow(); 9166 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9167 window1, test_window); 9168 check_wnd_state(window1, window1, window1, 0); 9169 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9170 ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); 9171 9172 SetForegroundWindow(thread_params.thread_window); 9173 9174 /* Set foreground then remove: Both messages are delivered. */ 9175 app_activated = app_deactivated = FALSE; 9176 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_SET_1 | SET_FOREGROUND_STEAL_2, 0); 9177 WaitForSingleObject(thread_params.command_executed, INFINITE); 9178 test_window = GetForegroundWindow(); 9179 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n", 9180 thread_params.thread_window, test_window); 9181 check_wnd_state(0, thread_params.thread_window, 0, 0); 9182 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9183 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9184 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9185 test_window = GetForegroundWindow(); 9186 ok(test_window == thread_params.thread_window, "Expected foreground window %p, got %p\n", 9187 thread_params.thread_window, test_window); 9188 /* Active and focus are window1 on wine because the internal WM_WINE_SETACTIVEWINDOW(0) 9189 * message is never generated. GetCapture() returns 0 though, so we'd get a test success 9190 * in todo_wine in the line below. 9191 * todo_wine check_wnd_state(0, thread_params.thread_window, 0, 0); */ 9192 ok(app_activated, "Expected WM_ACTIVATEAPP(1), did not receive it.\n"); 9193 todo_wine ok(app_deactivated, "Expected WM_ACTIVATEAPP(0), did not receive it.\n"); 9194 9195 SetForegroundWindow(window1); 9196 test_window = GetForegroundWindow(); 9197 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9198 window1, test_window); 9199 check_wnd_state(window1, window1, window1, 0); 9200 9201 /* Switch to a different window from the same thread? No messages. */ 9202 app_activated = app_deactivated = FALSE; 9203 PostThreadMessageA(tid, thread_params.msg_command, SET_FOREGROUND_STEAL_1 | SET_FOREGROUND_SET_2, 0); 9204 WaitForSingleObject(thread_params.command_executed, INFINITE); 9205 test_window = GetForegroundWindow(); 9206 ok(test_window == window1, "Expected foreground window %p, got %p\n", 9207 window1, test_window); 9208 check_wnd_state(window1, window1, window1, 0); 9209 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9210 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9211 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg); 9212 test_window = GetForegroundWindow(); 9213 ok(test_window == window2, "Expected foreground window %p, got %p\n", 9214 window2, test_window); 9215 check_wnd_state(window2, window2, window2, 0); 9216 ok(!app_activated, "Received WM_ACTIVATEAPP(1), did not expect it.\n"); 9217 ok(!app_deactivated, "Received WM_ACTIVATEAPP(0), did not expect it.\n"); 9218 9219 PostThreadMessageA(tid, thread_params.msg_quit, 0, 0); 9220 WaitForSingleObject(thread, INFINITE); 9221 9222 CloseHandle(thread_params.command_executed); 9223 DestroyWindow(window2); 9224 } 9225 9226 static LRESULT WINAPI winproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 9227 { 9228 if(!hwnd) { 9229 int *count = (int*)lparam; 9230 (*count)++; 9231 } 9232 return 0; 9233 } 9234 9235 static LRESULT WINAPI winproc_convA(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 9236 { 9237 if(msg == WM_SETTEXT) 9238 { 9239 const char *text = (const char*)lparam; 9240 9241 ok(!wparam, "wparam = %08lx\n", wparam); 9242 ok(!strcmp(text, "text"), "WM_SETTEXT lparam = %s\n", text); 9243 return 1; 9244 } 9245 return 0; 9246 } 9247 9248 static const WCHAR textW[] = {'t','e','x','t',0}; 9249 static LRESULT WINAPI winproc_convW(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 9250 { 9251 if(msg == WM_SETTEXT) 9252 { 9253 const WCHAR *text = (const WCHAR*)lparam; 9254 9255 ok(!wparam, "wparam = %08lx\n", wparam); 9256 ok(!lstrcmpW(text, textW), "WM_SETTEXT lparam = %s\n", wine_dbgstr_w(text)); 9257 return 1; 9258 } 9259 return 0; 9260 } 9261 9262 static void test_winproc_handles(const char *argv0) 9263 { 9264 static const WCHAR winproc_testW[] = {'w','i','n','p','r','o','c','_','t','e','s','t',0}; 9265 9266 HINSTANCE hinst = GetModuleHandleA(NULL); 9267 WNDCLASSA wnd_classA; 9268 WNDCLASSW wnd_classW; 9269 int count, ret; 9270 PROCESS_INFORMATION info; 9271 STARTUPINFOA startup; 9272 char cmd[MAX_PATH]; 9273 9274 memset(&wnd_classA, 0, sizeof(wnd_classA)); 9275 wnd_classA.lpszClassName = "winproc_test"; 9276 wnd_classA.lpfnWndProc = winproc; 9277 ret = RegisterClassA(&wnd_classA); 9278 ok(ret, "RegisterClass failed with error %d\n", GetLastError()); 9279 9280 ret = GetClassInfoW(hinst, winproc_testW, &wnd_classW); 9281 ok(ret, "GetClassInfoW failed with error %d\n", GetLastError()); 9282 ok(wnd_classA.lpfnWndProc != wnd_classW.lpfnWndProc, 9283 "winproc pointers should not be identical\n"); 9284 9285 count = 0; 9286 CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count); 9287 ok(count == 1, "winproc should be called once (%d)\n", count); 9288 count = 0; 9289 CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count); 9290 ok(count == 1, "winproc should be called once (%d)\n", count); 9291 9292 ret = UnregisterClassW(winproc_testW, hinst); 9293 ok(ret, "UnregisterClass failed with error %d\n", GetLastError()); 9294 9295 /* crashes on 64-bit windows because lpfnWndProc handle is already freed */ 9296 if (sizeof(void*) == 4) 9297 { 9298 count = 0; 9299 CallWindowProcA(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count); 9300 todo_wine ok(!count, "winproc should not be called (%d)\n", count); 9301 CallWindowProcW(wnd_classW.lpfnWndProc, 0, 0, 0, (LPARAM)&count); 9302 todo_wine ok(!count, "winproc should not be called (%d)\n", count); 9303 } 9304 9305 sprintf(cmd, "%s win winproc_limit", argv0); 9306 memset(&startup, 0, sizeof(startup)); 9307 startup.cb = sizeof(startup); 9308 ok(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, 9309 &startup, &info), "CreateProcess failed.\n"); 9310 winetest_wait_child_process(info.hProcess); 9311 CloseHandle(info.hProcess); 9312 CloseHandle(info.hThread); 9313 } 9314 9315 static void test_winproc_limit(void) 9316 { 9317 WNDPROC winproc_handle; 9318 LONG_PTR ret; 9319 HWND hwnd; 9320 int i; 9321 9322 hwnd = CreateWindowExA(0, "static", "test", WS_POPUP, 0, 0, 0, 0, 0, 0, 0, 0); 9323 ok(hwnd != 0, "CreateWindowEx failed\n"); 9324 9325 ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc), 9326 "SetWindowLongPtr failed\n"); 9327 winproc_handle = (WNDPROC)GetWindowLongPtrW(hwnd, GWLP_WNDPROC); 9328 ok(winproc_handle != winproc, "winproc pointers should not be identical\n"); 9329 9330 /* run out of winproc slots */ 9331 for(i = 2; i<0xffff; i++) 9332 { 9333 ok(SetWindowLongPtrA(hwnd, GWLP_WNDPROC, i), "SetWindowLongPtr failed (%d)\n", i); 9334 if(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == i) 9335 break; 9336 } 9337 ok(i != 0xffff, "unable to run out of winproc slots\n"); 9338 9339 ret = SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convA); 9340 ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError()); 9341 ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n"); 9342 ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n"); 9343 9344 ret = SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (LONG_PTR)winproc_convW); 9345 ok(ret, "SetWindowLongPtr failed with error %d\n", GetLastError()); 9346 ok(SendMessageA(hwnd, WM_SETTEXT, 0, (LPARAM)"text"), "WM_SETTEXT failed\n"); 9347 ok(SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)textW), "WM_SETTEXT with conversion failed\n"); 9348 9349 /* Show that there's no message conversion when CallWindowProc is used */ 9350 ok(CallWindowProcA(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1, 9351 "winproc_convW returned error\n"); 9352 ok(CallWindowProcW(winproc_convW, hwnd, WM_SETTEXT, 0, (LPARAM)textW) == 1, 9353 "winproc_convW returned error\n"); 9354 9355 i = 0; 9356 CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i); 9357 ok(i == 1, "winproc should be called once (%d)\n", i); 9358 i = 0; 9359 CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i); 9360 ok(i == 1, "winproc should be called once (%d)\n", i); 9361 9362 DestroyWindow(hwnd); 9363 9364 i = 0; 9365 CallWindowProcA(winproc_handle, 0, 0, 0, (LPARAM)&i); 9366 ok(i == 1, "winproc should be called once (%d)\n", i); 9367 i = 0; 9368 CallWindowProcW(winproc_handle, 0, 0, 0, (LPARAM)&i); 9369 ok(i == 1, "winproc should be called once (%d)\n", i); 9370 } 9371 9372 static void test_deferwindowpos(void) 9373 { 9374 HDWP hdwp, hdwp2; 9375 BOOL ret; 9376 9377 hdwp = BeginDeferWindowPos(0); 9378 ok(hdwp != NULL, "got %p\n", hdwp); 9379 9380 ret = EndDeferWindowPos(NULL); 9381 ok(!ret, "got %d\n", ret); 9382 9383 hdwp2 = DeferWindowPos(NULL, NULL, NULL, 0, 0, 10, 10, 0); 9384 todo_wine 9385 ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) || 9386 broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError()); 9387 9388 hdwp2 = DeferWindowPos((HDWP)0xdead, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0); 9389 todo_wine 9390 ok(hdwp2 == NULL && ((GetLastError() == ERROR_INVALID_DWP_HANDLE) || 9391 broken(GetLastError() == ERROR_INVALID_WINDOW_HANDLE) /* before win8 */), "got %p, error %d\n", hdwp2, GetLastError()); 9392 9393 hdwp2 = DeferWindowPos(hdwp, NULL, NULL, 0, 0, 10, 10, 0); 9394 ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError()); 9395 9396 hdwp2 = DeferWindowPos(hdwp, GetDesktopWindow(), NULL, 0, 0, 10, 10, 0); 9397 ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError()); 9398 9399 hdwp2 = DeferWindowPos(hdwp, (HWND)0xdead, NULL, 0, 0, 10, 10, 0); 9400 ok(hdwp2 == NULL && GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got %p, error %d\n", hdwp2, GetLastError()); 9401 9402 ret = EndDeferWindowPos(hdwp); 9403 ok(ret, "got %d\n", ret); 9404 } 9405 9406 START_TEST(win) 9407 { 9408 char **argv; 9409 int argc = winetest_get_mainargs( &argv ); 9410 HMODULE user32 = GetModuleHandleA( "user32.dll" ); 9411 HMODULE gdi32 = GetModuleHandleA("gdi32.dll"); 9412 pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" ); 9413 pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" ); 9414 pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" ); 9415 pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" ); 9416 pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" ); 9417 pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" ); 9418 pUpdateLayeredWindowIndirect = (void *)GetProcAddress( user32, "UpdateLayeredWindowIndirect" ); 9419 pGetMonitorInfoA = (void *)GetProcAddress( user32, "GetMonitorInfoA" ); 9420 pMonitorFromPoint = (void *)GetProcAddress( user32, "MonitorFromPoint" ); 9421 pGetWindowRgnBox = (void *)GetProcAddress( user32, "GetWindowRgnBox" ); 9422 pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" ); 9423 pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" ); 9424 pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" ); 9425 pFlashWindow = (void *)GetProcAddress( user32, "FlashWindow" ); 9426 pFlashWindowEx = (void *)GetProcAddress( user32, "FlashWindowEx" ); 9427 pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" ); 9428 pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" ); 9429 pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" ); 9430 9431 if (argc==4 && !strcmp(argv[2], "create_children")) 9432 { 9433 HWND hwnd; 9434 9435 sscanf(argv[3], "%p", &hwnd); 9436 window_from_point_proc(hwnd); 9437 return; 9438 } 9439 9440 if (argc==3 && !strcmp(argv[2], "winproc_limit")) 9441 { 9442 test_winproc_limit(); 9443 return; 9444 } 9445 9446 if (!RegisterWindowClasses()) assert(0); 9447 9448 hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window", 9449 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 9450 WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE, 9451 100, 100, 200, 200, 9452 0, 0, GetModuleHandleA(NULL), NULL); 9453 assert( hwndMain ); 9454 9455 if(!SetForegroundWindow(hwndMain)) { 9456 /* workaround for foreground lock timeout */ 9457 simulate_click(101, 101); 9458 ok(SetForegroundWindow(hwndMain), "SetForegroundWindow failed\n"); 9459 } 9460 9461 SetLastError(0xdeafbeef); 9462 GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC); 9463 is_win9x = (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED); 9464 9465 hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); 9466 if (!hhook) win_skip( "Cannot set CBT hook, skipping some tests\n" ); 9467 9468 /* make sure that these tests are executed first */ 9469 test_FindWindowEx(); 9470 test_SetParent(); 9471 9472 hwndMain2 = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window 2", 9473 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | 9474 WS_MAXIMIZEBOX | WS_POPUP, 9475 100, 100, 200, 200, 9476 0, 0, GetModuleHandleA(NULL), NULL); 9477 assert( hwndMain2 ); 9478 9479 our_pid = GetWindowThreadProcessId(hwndMain, NULL); 9480 9481 /* Add the tests below this line */ 9482 test_child_window_from_point(); 9483 test_window_from_point(argv[0]); 9484 test_thick_child_size(hwndMain); 9485 test_fullscreen(); 9486 test_hwnd_message(); 9487 test_nonclient_area(hwndMain); 9488 test_params(); 9489 test_GetWindowModuleFileName(); 9490 test_capture_1(); 9491 test_capture_2(); 9492 test_capture_3(hwndMain, hwndMain2); 9493 test_capture_4(); 9494 test_rtl_layout(); 9495 test_FlashWindow(); 9496 test_FlashWindowEx(); 9497 9498 test_CreateWindow(); 9499 test_parent_owner(); 9500 test_enum_thread_windows(); 9501 9502 test_mdi(); 9503 test_icons(); 9504 test_SetWindowPos(hwndMain, hwndMain2); 9505 test_SetMenu(hwndMain); 9506 test_SetFocus(hwndMain); 9507 test_SetActiveWindow(hwndMain); 9508 test_NCRedraw(); 9509 9510 test_children_zorder(hwndMain); 9511 test_popup_zorder(hwndMain2, hwndMain, WS_POPUP); 9512 test_popup_zorder(hwndMain2, hwndMain, 0); 9513 test_GetLastActivePopup(); 9514 test_keyboard_input(hwndMain); 9515 test_mouse_input(hwndMain); 9516 test_validatergn(hwndMain); 9517 test_nccalcscroll( hwndMain); 9518 test_scrollwindow( hwndMain); 9519 test_scrollvalidate( hwndMain); 9520 test_scrolldc( hwndMain); 9521 test_scroll(); 9522 test_IsWindowUnicode(); 9523 test_vis_rgn(hwndMain); 9524 9525 test_AdjustWindowRect(); 9526 test_window_styles(); 9527 test_dialog_styles(); 9528 test_dialog_parent(); 9529 test_redrawnow(); 9530 test_csparentdc(); 9531 test_SetWindowLong(); 9532 test_set_window_style(); 9533 test_ShowWindow(); 9534 test_gettext(); 9535 test_GetUpdateRect(); 9536 test_Expose(); 9537 test_layered_window(); 9538 9539 test_SetForegroundWindow(hwndMain); 9540 test_shell_window(); 9541 test_handles( hwndMain ); 9542 test_winregion(); 9543 test_map_points(); 9544 test_update_region(); 9545 test_window_without_child_style(); 9546 test_smresult(); 9547 test_GetMessagePos(); 9548 9549 test_activateapp(hwndMain); 9550 test_winproc_handles(argv[0]); 9551 test_deferwindowpos(); 9552 9553 /* add the tests above this line */ 9554 if (hhook) UnhookWindowsHookEx(hhook); 9555 9556 DestroyWindow(hwndMain2); 9557 DestroyWindow(hwndMain); 9558 } 9559