Reactos
at master 1304 lines 36 kB view raw
1/* 2 * PROJECT: ReactOS api tests 3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) 4 * PURPOSE: Test for SHAppBarMessage 5 * COPYRIGHT: Copyright 2020-2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 6 */ 7 8#include "shelltest.h" 9#include <windowsx.h> 10#include <shlwapi.h> 11#include <stdio.h> 12 13/* Based on https://github.com/katahiromz/AppBarSample */ 14 15//#define VERBOSE 16 17#define IDT_AUTOHIDE 1 18#define IDT_AUTOUNHIDE 2 19 20#define ID_ACTION 100 21#define ID_QUIT 999 22 23#define APPBAR_CALLBACK (WM_USER + 100) 24 25#define LEFT_DOWN() mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0); 26#define LEFT_UP() mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0); 27#define MOVE(x, y) SetCursorPos((x), (y)) 28 29#define INTERVAL 250 30#define LONG_INTERVAL 2500 31 32static const TCHAR s_szName[] = TEXT("AppBarSample"); 33static RECT s_rcPrimaryMonitor; 34static RECT s_rcWorkArea; 35static RECT s_rcTaskBar; 36static HWND s_hwnd1 = NULL; 37static HWND s_hwnd2 = NULL; 38 39#ifdef VERBOSE 40static LPCSTR MessageOfAppBar(DWORD dwMessage) 41{ 42 static char s_buf[32]; 43 switch (dwMessage) 44 { 45 case ABM_NEW: return "ABM_NEW"; 46 case ABM_REMOVE: return "ABM_REMOVE"; 47 case ABM_QUERYPOS: return "ABM_QUERYPOS"; 48 case ABM_SETPOS: return "ABM_SETPOS"; 49 case ABM_GETSTATE: return "ABM_GETSTATE"; 50 case ABM_GETTASKBARPOS: return "ABM_GETTASKBARPOS"; 51 case ABM_ACTIVATE: return "ABM_ACTIVATE"; 52 case ABM_GETAUTOHIDEBAR: return "ABM_GETAUTOHIDEBAR"; 53 case ABM_SETAUTOHIDEBAR: return "ABM_SETAUTOHIDEBAR"; 54 case ABM_WINDOWPOSCHANGED: return "ABM_WINDOWPOSCHANGED"; 55 } 56 wsprintfA(s_buf, "%lu", dwMessage); 57 return s_buf; 58} 59 60static UINT WINAPI 61SHAppBarMessageWrap(DWORD dwMessage, PAPPBARDATA pData) 62{ 63 trace("SHAppBarMessage entered (dwMessage=%s, rc=(%ld, %ld, %ld, %ld))\n", 64 MessageOfAppBar(dwMessage), 65 pData->rc.left, pData->rc.top, pData->rc.right, pData->rc.bottom); 66 UINT ret = SHAppBarMessage(dwMessage, pData); 67 trace("SHAppBarMessage leaved (dwMessage=%s, rc=(%ld, %ld, %ld, %ld))\n", 68 MessageOfAppBar(dwMessage), 69 pData->rc.left, pData->rc.top, pData->rc.right, pData->rc.bottom); 70 return ret; 71} 72#define SHAppBarMessage SHAppBarMessageWrap 73 74#undef ARRAYSIZE 75#define ARRAYSIZE _countof 76 77void appbar_tprintf(const TCHAR *fmt, ...) 78{ 79 TCHAR szText[512]; 80 va_list va; 81 va_start(va, fmt); 82 wvsprintf(szText, fmt, va); 83#ifdef UNICODE 84 printf("%ls", szText); 85#else 86 printf("%s", szText); 87#endif 88 va_end(va); 89} 90 91#define MSGDUMP_TPRINTF appbar_tprintf 92#include "msgdump.h" 93 94#endif // def VERBOSE 95 96void SlideWindow(HWND hwnd, LPRECT prc) 97{ 98#define SLIDE_HIDE 400 99#define SLIDE_SHOW 150 100 RECT rcOld, rcNew = *prc; 101 GetWindowRect(hwnd, &rcOld); 102 103 BOOL fShow = (rcNew.bottom - rcNew.top > rcOld.bottom - rcOld.top) || 104 (rcNew.right - rcNew.left > rcOld.right - rcOld.left); 105 106 INT dx = (rcNew.right - rcOld.right) + (rcNew.left - rcOld.left); 107 INT dy = (rcNew.bottom - rcOld.bottom) + (rcNew.top - rcOld.top); 108 109 LONG dt = SLIDE_HIDE; 110 if (fShow) 111 { 112 dt = SLIDE_SHOW; 113 rcOld = rcNew; 114 OffsetRect(&rcOld, -dx, -dy); 115 SetWindowPos(hwnd, NULL, rcOld.left, rcOld.top, 116 rcOld.right - rcOld.left, rcOld.bottom - rcOld.top, 117 SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME); 118 } 119 120 HANDLE hThread = GetCurrentThread(); 121 INT priority = GetThreadPriority(hThread); 122 SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); 123 124 LONG t, t0 = GetTickCount(); 125 while ((t = GetTickCount()) < t0 + dt) 126 { 127 INT x = rcOld.left + dx * (t - t0) / dt; 128 INT y = rcOld.top + dy * (t - t0) / dt; 129 SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 130 131 UpdateWindow(hwnd); 132 UpdateWindow(GetDesktopWindow()); 133 } 134 135 SetThreadPriority(hThread, priority); 136 SetWindowPos(hwnd, NULL, rcNew.left, rcNew.top, 137 rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, 138 SWP_NOZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME); 139#undef SLIDE_HIDE 140#undef SLIDE_SHOW 141} 142 143class Window 144{ 145public: 146 Window(INT cx, INT cy, BOOL fAutoHide = FALSE) 147 : m_hwnd(NULL) 148 , m_fAutoHide(fAutoHide) 149 , m_cxWidth(cx) 150 , m_cyHeight(cy) 151 { 152 } 153 154 virtual ~Window() { } 155 156 static BOOL DoRegisterClass(HINSTANCE hInstance) 157 { 158 WNDCLASS wc; 159 ZeroMemory(&wc, sizeof(wc)); 160 wc.lpfnWndProc = Window::WindowProc; 161 wc.hInstance = hInstance; 162 wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); 163 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 164 wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); 165 wc.lpszClassName = s_szName; 166 return !!RegisterClass(&wc); 167 } 168 169 static HWND DoCreateMainWnd(HINSTANCE hInstance, LPCTSTR pszText, INT cx, INT cy, 170 DWORD style = WS_POPUP | WS_THICKFRAME | WS_CLIPCHILDREN, 171 DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST, 172 BOOL fAutoHide = FALSE) 173 { 174 Window *this_ = new Window(cx, cy, fAutoHide); 175 HWND hwnd = CreateWindowEx(exstyle, s_szName, pszText, style, 176 CW_USEDEFAULT, CW_USEDEFAULT, 50, 50, 177 NULL, NULL, hInstance, this_); 178 ShowWindow(hwnd, SW_SHOWNORMAL); 179 UpdateWindow(hwnd); 180 return hwnd; 181 } 182 183 static Window *GetAppbarData(HWND hwnd) 184 { 185 return (Window *)GetWindowLongPtr(hwnd, GWLP_USERDATA); 186 } 187 188 virtual LRESULT CALLBACK 189 WindowProcDx(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 190 { 191#ifdef VERBOSE 192 MD_msgdump(hwnd, uMsg, wParam, lParam); 193#endif 194 switch (uMsg) 195 { 196 HANDLE_MSG(hwnd, WM_CREATE, OnCreate); 197 HANDLE_MSG(hwnd, WM_COMMAND, OnCommand); 198 HANDLE_MSG(hwnd, WM_ACTIVATE, OnActivate); 199 HANDLE_MSG(hwnd, WM_WINDOWPOSCHANGED, OnWindowPosChanged); 200 HANDLE_MSG(hwnd, WM_SIZE, OnSize); 201 HANDLE_MSG(hwnd, WM_MOVE, OnMove); 202 HANDLE_MSG(hwnd, WM_NCDESTROY, OnNCDestroy); 203 HANDLE_MSG(hwnd, WM_TIMER, OnTimer); 204 HANDLE_MSG(hwnd, WM_NCHITTEST, OnNCHitTest); 205 HANDLE_MSG(hwnd, WM_LBUTTONDOWN, OnLButtonDown); 206 HANDLE_MSG(hwnd, WM_MOUSEMOVE, OnMouseMove); 207 HANDLE_MSG(hwnd, WM_LBUTTONUP, OnLButtonUp); 208 HANDLE_MSG(hwnd, WM_RBUTTONDOWN, OnRButtonDown); 209 HANDLE_MSG(hwnd, WM_KEYDOWN, OnKey); 210 HANDLE_MSG(hwnd, WM_PAINT, OnPaint); 211 212 case APPBAR_CALLBACK: 213 OnAppBarCallback(hwnd, uMsg, wParam, lParam); 214 break; 215 216 default: 217 return DefWindowProc(hwnd, uMsg, wParam, lParam); 218 } 219 return 0; 220 } 221 222 static LRESULT CALLBACK 223 WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 224 { 225 Window *this_ = GetAppbarData(hwnd); 226 if (uMsg == WM_CREATE) 227 { 228 LPCREATESTRUCT pCS = (LPCREATESTRUCT)lParam; 229 this_ = (Window *)pCS->lpCreateParams; 230 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)this_); 231 } 232 if (this_) 233 return this_->WindowProcDx(hwnd, uMsg, wParam, lParam); 234 return DefWindowProc(hwnd, uMsg, wParam, lParam); 235 } 236 237protected: 238 HWND m_hwnd; 239 BOOL m_fAutoHide; 240 BOOL m_fOnTop; 241 BOOL m_fHiding; 242 UINT m_uSide; 243 LONG m_cxWidth; 244 LONG m_cyHeight; 245 LONG m_cxSave; 246 LONG m_cySave; 247 BOOL m_fAppBarRegd; 248 BOOL m_fMoving; 249 BOOL m_bDragged; 250 POINT m_ptDragOn; 251 RECT m_rcAppBar; 252 RECT m_rcDrag; 253 BOOL m_bGotFullScreen; 254 255 void OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) 256 { 257 HANDLE hThread; 258 switch (id) 259 { 260 case ID_ACTION: 261 PostMessageW(s_hwnd2, WM_COMMAND, ID_ACTION + 1, 0); 262 break; 263 case ID_ACTION + 1: 264 hThread = CreateThread(NULL, 0, ActionThreadFunc, this, 0, NULL); 265 if (!hThread) 266 { 267 skip("failed to create thread\n"); 268 PostMessageW(s_hwnd1, WM_CLOSE, 0, 0); 269 PostMessageW(s_hwnd2, WM_CLOSE, 0, 0); 270 return; 271 } 272 CloseHandle(hThread); 273 break; 274 case ID_QUIT: 275 DestroyWindow(s_hwnd1); 276 DestroyWindow(s_hwnd2); 277 PostQuitMessage(0); 278 break; 279 } 280 } 281 282 void OnPaint(HWND hwnd) 283 { 284 PAINTSTRUCT ps; 285 286 TCHAR szText[64]; 287 GetWindowText(hwnd, szText, 64); 288 289 RECT rc; 290 GetClientRect(hwnd, &rc); 291 292 if (HDC hdc = BeginPaint(hwnd, &ps)) 293 { 294 DrawText(hdc, szText, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); 295 EndPaint(hwnd, &ps); 296 } 297 } 298 299 void OnRButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags) 300 { 301 m_fAutoHide = !m_fAutoHide; 302 AppBar_SetAutoHide(hwnd, m_fAutoHide); 303 } 304 305 void OnKey(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags) 306 { 307 if (vk == VK_ESCAPE) 308 DestroyWindow(hwnd); 309 } 310 311 void OnAppBarCallback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 312 { 313 static HWND s_hwndZOrder = NULL; 314 315 switch (wParam) 316 { 317 case ABN_STATECHANGE: 318 break; 319 320 case ABN_FULLSCREENAPP: 321 m_bGotFullScreen = TRUE; 322 if (lParam) 323 { 324 s_hwndZOrder = GetWindow(hwnd, GW_HWNDPREV); 325 SetWindowPos(hwnd, HWND_BOTTOM, 0, 0, 0, 0, 326 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 327 } 328 else 329 { 330 SetWindowPos(hwnd, m_fOnTop ? HWND_TOPMOST : s_hwndZOrder, 331 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 332 s_hwndZOrder = NULL; 333 } 334 break; 335 336 case ABN_POSCHANGED: 337 { 338 APPBARDATA abd = { sizeof(abd), hwnd }; 339 AppBar_PosChanged(&abd); 340 } 341 break; 342 } 343 } 344 345 BOOL AppBar_Register(HWND hwnd) 346 { 347 APPBARDATA abd = { sizeof(abd), hwnd, APPBAR_CALLBACK }; 348 m_fAppBarRegd = (BOOL)SHAppBarMessage(ABM_NEW, &abd); 349 return m_fAppBarRegd; 350 } 351 352 BOOL AppBar_UnRegister(HWND hwnd) 353 { 354 APPBARDATA abd = { sizeof(abd), hwnd }; 355 m_fAppBarRegd = !SHAppBarMessage(ABM_REMOVE, &abd); 356 return !m_fAppBarRegd; 357 } 358 359 BOOL AppBar_GetTaskBarPos(HWND hwnd, PRECT prc) 360 { 361 APPBARDATA abd = { sizeof(abd), hwnd }; 362 363 if (!SHAppBarMessage(ABM_GETTASKBARPOS, &abd)) 364 return FALSE; 365 *prc = abd.rc; 366 return TRUE; 367 } 368 369 HWND AppBar_GetAutoHideBar(HWND hwnd, UINT uSide) 370 { 371 APPBARDATA abd = { sizeof(abd), hwnd }; 372 abd.uEdge = uSide; 373 374 return (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd); 375 } 376 377 BOOL AppBar_SetAutoHide(HWND hwnd, BOOL fHide) 378 { 379 if (fHide) 380 return AppBar_AutoHide(hwnd); 381 else 382 return AppBar_NoAutoHide(hwnd); 383 } 384 385 BOOL AppBar_AutoHide(HWND hwnd) 386 { 387 APPBARDATA abd = { sizeof(abd), hwnd }; 388 abd.uEdge = m_uSide; 389 390 HWND hwndAutoHide = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd); 391 if (hwndAutoHide) 392 return FALSE; 393 394 abd.lParam = TRUE; 395 if (!(BOOL)SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) 396 return FALSE; 397 398 m_fAutoHide = TRUE; 399 m_cxSave = m_cxWidth; 400 m_cySave = m_cyHeight; 401 402 RECT rc = m_rcAppBar; 403 switch (m_uSide) 404 { 405 case ABE_TOP: 406 rc.bottom = rc.top + 2; 407 break; 408 case ABE_BOTTOM: 409 rc.top = rc.bottom - 2; 410 break; 411 case ABE_LEFT: 412 rc.right = rc.left + 2; 413 break; 414 case ABE_RIGHT: 415 rc.left = rc.right - 2; 416 break; 417 } 418 419 AppBar_QueryPos(hwnd, &rc); 420 abd.rc = rc; 421 SHAppBarMessage(ABM_SETPOS, &abd); 422 rc = abd.rc; 423 424 m_fHiding = TRUE; 425 SlideWindow(hwnd, &rc); 426 427 AppBar_SetAutoHideTimer(hwnd); 428 return TRUE; 429 } 430 431 BOOL AppBar_NoAutoHide(HWND hwnd) 432 { 433 APPBARDATA abd = { sizeof(abd), hwnd }; 434 abd.uEdge = m_uSide; 435 HWND hwndAutoHide = (HWND)SHAppBarMessage(ABM_GETAUTOHIDEBAR, &abd); 436 if (hwndAutoHide != hwnd) 437 return FALSE; 438 439 abd.lParam = FALSE; 440 if (!(BOOL)SHAppBarMessage(ABM_SETAUTOHIDEBAR, &abd)) 441 return FALSE; 442 443 m_fAutoHide = FALSE; 444 m_cxWidth = m_cxSave; 445 m_cyHeight = m_cySave; 446 AppBar_SetSide(hwnd, m_uSide); 447 return TRUE; 448 } 449 450 BOOL AppBar_SetSide(HWND hwnd, UINT uSide) 451 { 452 HMONITOR hMon = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); 453 MONITORINFO mi = { sizeof(mi) }; 454 ::GetMonitorInfo(hMon, &mi); 455 RECT rc = mi.rcWork; 456 457 BOOL fAutoHide = FALSE; 458 if (m_fAutoHide) 459 { 460 fAutoHide = m_fAutoHide; 461 SetWindowRedraw(GetDesktopWindow(), FALSE); 462 AppBar_SetAutoHide(hwnd, FALSE); 463 m_fHiding = FALSE; 464 } 465 466 switch (uSide) 467 { 468 case ABE_TOP: 469 rc.bottom = rc.top + m_cyHeight; 470 break; 471 case ABE_BOTTOM: 472 rc.top = rc.bottom - m_cyHeight; 473 break; 474 case ABE_LEFT: 475 rc.right = rc.left + m_cxWidth; 476 break; 477 case ABE_RIGHT: 478 rc.left = rc.right - m_cxWidth; 479 break; 480 } 481 482 APPBARDATA abd = { sizeof(abd), hwnd }; 483 AppBar_QuerySetPos(uSide, &rc, &abd, TRUE); 484 485 if (fAutoHide) 486 { 487 AppBar_SetAutoHide(hwnd, TRUE); 488 m_fHiding = TRUE; 489 490 SetWindowRedraw(GetDesktopWindow(), TRUE); 491 RedrawWindow(GetDesktopWindow(), NULL, NULL, 492 RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN); 493 } 494 495 return TRUE; 496 } 497 498 void AppBar_SetAlwaysOnTop(HWND hwnd, BOOL fOnTop) 499 { 500 SetWindowPos(hwnd, (fOnTop ? HWND_TOPMOST : HWND_NOTOPMOST), 501 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 502 m_fOnTop = fOnTop; 503 } 504 505 void AppBar_Hide(HWND hwnd) 506 { 507 if (!m_fAutoHide) 508 return; 509 510 RECT rc = m_rcAppBar; 511 switch (m_uSide) 512 { 513 case ABE_TOP: 514 rc.bottom = rc.top + 2; 515 break; 516 case ABE_BOTTOM: 517 rc.top = rc.bottom - 2; 518 break; 519 case ABE_LEFT: 520 rc.right = rc.left + 2; 521 break; 522 case ABE_RIGHT: 523 rc.left = rc.right - 2; 524 break; 525 } 526 527 m_fHiding = TRUE; 528 SlideWindow(hwnd, &rc); 529 } 530 531 void AppBar_UnHide(HWND hwnd) 532 { 533 SlideWindow(hwnd, &m_rcAppBar); 534 m_fHiding = FALSE; 535 536 AppBar_SetAutoHideTimer(hwnd); 537 } 538 539 void AppBar_SetAutoHideTimer(HWND hwnd) 540 { 541 if (m_fAutoHide) 542 { 543 SetTimer(hwnd, IDT_AUTOHIDE, 500, NULL); 544 } 545 } 546 547 void AppBar_SetAutoUnhideTimer(HWND hwnd) 548 { 549 if (m_fAutoHide && m_fHiding) 550 { 551 SetTimer(hwnd, IDT_AUTOUNHIDE, 50, NULL); 552 } 553 } 554 555 void AppBar_Size(HWND hwnd) 556 { 557 if (m_fAppBarRegd) 558 { 559 APPBARDATA abd = { sizeof(abd), hwnd }; 560 561 RECT rc; 562 GetWindowRect(hwnd, &rc); 563 AppBar_QuerySetPos(m_uSide, &rc, &abd, TRUE); 564 } 565 } 566 567 void AppBar_QueryPos(HWND hwnd, LPRECT lprc) 568 { 569 APPBARDATA abd = { sizeof(abd), hwnd }; 570 abd.rc = *lprc; 571 abd.uEdge = m_uSide; 572 573 INT cx = 0, cy = 0; 574 if (ABE_LEFT == abd.uEdge || ABE_RIGHT == abd.uEdge) 575 { 576 cx = abd.rc.right - abd.rc.left; 577 abd.rc.top = 0; 578 abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN); 579 } 580 else 581 { 582 cy = abd.rc.bottom - abd.rc.top; 583 abd.rc.left = 0; 584 abd.rc.right = GetSystemMetrics(SM_CXSCREEN); 585 } 586 587 SHAppBarMessage(ABM_QUERYPOS, &abd); 588 589 switch (abd.uEdge) 590 { 591 case ABE_LEFT: 592 abd.rc.right = abd.rc.left + cx; 593 break; 594 case ABE_RIGHT: 595 abd.rc.left = abd.rc.right - cx; 596 break; 597 case ABE_TOP: 598 abd.rc.bottom = abd.rc.top + cy; 599 break; 600 case ABE_BOTTOM: 601 abd.rc.top = abd.rc.bottom - cy; 602 break; 603 } 604 605 *lprc = abd.rc; 606 } 607 608 void AppBar_QuerySetPos(UINT uEdge, LPRECT lprc, PAPPBARDATA pabd, BOOL fMove) 609 { 610 pabd->rc = *lprc; 611 pabd->uEdge = uEdge; 612 m_uSide = uEdge; 613 614 AppBar_QueryPos(pabd->hWnd, &pabd->rc); 615 616 SHAppBarMessage(ABM_SETPOS, pabd); 617 618 if (fMove) 619 { 620 RECT rc = pabd->rc; 621 MoveWindow(pabd->hWnd, rc.left, rc.top, 622 rc.right - rc.left, rc.bottom - rc.top, TRUE); 623 } 624 625 if (!m_fAutoHide) 626 { 627 m_rcAppBar = pabd->rc; 628 } 629 } 630 631 void AppBar_PosChanged(PAPPBARDATA pabd) 632 { 633 RECT rc; 634 SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); 635 636 if (m_fAutoHide) 637 { 638 m_rcAppBar = rc; 639 switch (m_uSide) 640 { 641 case ABE_TOP: 642 m_rcAppBar.bottom = m_rcAppBar.top + m_cySave; 643 break; 644 case ABE_BOTTOM: 645 m_rcAppBar.top = m_rcAppBar.bottom - m_cySave; 646 break; 647 case ABE_LEFT: 648 m_rcAppBar.right = m_rcAppBar.left + m_cxSave; 649 break; 650 case ABE_RIGHT: 651 m_rcAppBar.left = m_rcAppBar.right - m_cxSave; 652 break; 653 } 654 } 655 656 RECT rcWindow; 657 GetWindowRect(pabd->hWnd, &rcWindow); 658 INT cx = rcWindow.right - rcWindow.left; 659 INT cy = rcWindow.bottom - rcWindow.top; 660 switch (m_uSide) 661 { 662 case ABE_TOP: 663 rc.bottom = rc.top + cy; 664 break; 665 case ABE_BOTTOM: 666 rc.top = rc.bottom - cy; 667 break; 668 case ABE_LEFT: 669 rc.right = rc.left + cx; 670 break; 671 case ABE_RIGHT: 672 rc.left = rc.right - cx; 673 break; 674 } 675 AppBar_QuerySetPos(m_uSide, &rc, pabd, TRUE); 676 } 677 678 BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpCreateStruct) 679 { 680 m_hwnd = hwnd; 681 m_fOnTop = TRUE; 682 m_uSide = ABE_TOP; 683 684 m_fAppBarRegd = FALSE; 685 m_fMoving = FALSE; 686 m_cxSave = m_cxWidth; 687 m_cySave = m_cyHeight; 688 m_bDragged = FALSE; 689 690 AppBar_Register(hwnd); 691 AppBar_SetSide(hwnd, ABE_TOP); 692 693 trace("OnCreate(%p) done\n", hwnd); 694 return TRUE; 695 } 696 697 void OnActivate(HWND hwnd, UINT state, HWND hwndActDeact, BOOL fMinimized) 698 { 699 APPBARDATA abd = { sizeof(abd), hwnd }; 700 SHAppBarMessage(ABM_ACTIVATE, &abd); 701 702 switch (state) 703 { 704 case WA_ACTIVE: 705 case WA_CLICKACTIVE: 706 AppBar_UnHide(hwnd); 707 KillTimer(hwnd, IDT_AUTOHIDE); 708 break; 709 710 case WA_INACTIVE: 711 AppBar_Hide(hwnd); 712 break; 713 } 714 } 715 716 void OnWindowPosChanged(HWND hwnd, const LPWINDOWPOS lpwpos) 717 { 718 APPBARDATA abd = { sizeof(abd), hwnd }; 719 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd); 720 721 FORWARD_WM_WINDOWPOSCHANGED(hwnd, lpwpos, DefWindowProc); 722 } 723 724 void OnSize(HWND hwnd, UINT state, int cx, int cy) 725 { 726 RECT rcWindow; 727 728 if (m_fMoving || (m_fAutoHide && m_fHiding)) 729 return; 730 731 if (!m_fHiding) 732 { 733 if (!m_fAutoHide) 734 AppBar_Size(hwnd); 735 736 GetWindowRect(hwnd, &rcWindow); 737 m_rcAppBar = rcWindow; 738 739 if (m_uSide == ABE_TOP || m_uSide == ABE_BOTTOM) 740 m_cyHeight = m_cySave = rcWindow.bottom - rcWindow.top; 741 else 742 m_cxWidth = m_cxSave = rcWindow.right - rcWindow.left; 743 } 744 745 InvalidateRect(hwnd, NULL, TRUE); 746 } 747 748 void OnMove(HWND hwnd, int x, int y) 749 { 750 if (m_fMoving || m_fAutoHide) 751 return; 752 753 if (!m_fHiding) 754 AppBar_Size(hwnd); 755 } 756 757 void OnNCDestroy(HWND hwnd) 758 { 759 AppBar_UnRegister(hwnd); 760 761 m_hwnd = NULL; 762 SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); 763 delete this; 764 } 765 766 void OnTimer(HWND hwnd, UINT id) 767 { 768 POINT pt; 769 RECT rc; 770 HWND hwndActive; 771 772 switch (id) 773 { 774 case IDT_AUTOHIDE: 775 if (m_fAutoHide && !m_fHiding && !m_fMoving) 776 { 777 GetCursorPos(&pt); 778 GetWindowRect(hwnd, &rc); 779 hwndActive = GetForegroundWindow(); 780 781 if (!PtInRect(&rc, pt) && 782 hwndActive != hwnd && 783 hwndActive != NULL && 784 GetWindowOwner(hwndActive) != hwnd) 785 { 786 KillTimer(hwnd, id); 787 AppBar_Hide(hwnd); 788 } 789 } 790 break; 791 792 case IDT_AUTOUNHIDE: 793 KillTimer(hwnd, id); 794 795 if (m_fAutoHide && m_fHiding) 796 { 797 GetCursorPos(&pt); 798 GetWindowRect(hwnd, &rc); 799 if (PtInRect(&rc, pt)) 800 { 801 AppBar_UnHide(hwnd); 802 } 803 } 804 break; 805 } 806 } 807 808 UINT OnNCHitTest(HWND hwnd, int x, int y) 809 { 810 AppBar_SetAutoUnhideTimer(hwnd); 811 812 UINT uHitTest = FORWARD_WM_NCHITTEST(hwnd, x, y, DefWindowProc); 813 814 if (m_uSide == ABE_TOP && uHitTest == HTBOTTOM) 815 return HTBOTTOM; 816 817 if (m_uSide == ABE_BOTTOM && uHitTest == HTTOP) 818 return HTTOP; 819 820 if (m_uSide == ABE_LEFT && uHitTest == HTRIGHT) 821 return HTRIGHT; 822 823 if (m_uSide == ABE_RIGHT && uHitTest == HTLEFT) 824 return HTLEFT; 825 826 return HTCLIENT; 827 } 828 829 void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags) 830 { 831 m_fMoving = TRUE; 832 m_bDragged = FALSE; 833 SetCapture(hwnd); 834 GetCursorPos(&m_ptDragOn); 835 } 836 837 void OnMouseMove(HWND hwnd, int x, int y, UINT keyFlags) 838 { 839 if (!m_fMoving) 840 return; 841 842 POINT pt; 843 GetCursorPos(&pt); 844 if (labs(pt.x - m_ptDragOn.x) > GetSystemMetrics(SM_CXDRAG) || 845 labs(pt.y - m_ptDragOn.y) > GetSystemMetrics(SM_CYDRAG)) 846 { 847 m_bDragged = TRUE; 848 } 849 850 INT cxScreen = GetSystemMetrics(SM_CXSCREEN); 851 INT cyScreen = GetSystemMetrics(SM_CYSCREEN); 852 853 DWORD dx, dy; 854 UINT ix, iy; 855 if (pt.x < cxScreen / 2) 856 { 857 dx = pt.x; 858 ix = ABE_LEFT; 859 } 860 else 861 { 862 dx = cxScreen - pt.x; 863 ix = ABE_RIGHT; 864 } 865 866 if (pt.y < cyScreen / 2) 867 { 868 dy = pt.y; 869 iy = ABE_TOP; 870 } 871 else 872 { 873 dy = cyScreen - pt.y; 874 iy = ABE_BOTTOM; 875 } 876 877 if (cxScreen * dy > cyScreen * dx) 878 { 879 m_rcDrag.top = 0; 880 m_rcDrag.bottom = cyScreen; 881 if (ix == ABE_LEFT) 882 { 883 m_uSide = ABE_LEFT; 884 m_rcDrag.left = 0; 885 m_rcDrag.right = m_rcDrag.left + m_cxWidth; 886 } 887 else 888 { 889 m_uSide = ABE_RIGHT; 890 m_rcDrag.right = cxScreen; 891 m_rcDrag.left = m_rcDrag.right - m_cxWidth; 892 } 893 } 894 else 895 { 896 m_rcDrag.left = 0; 897 m_rcDrag.right = cxScreen; 898 if (iy == ABE_TOP) 899 { 900 m_uSide = ABE_TOP; 901 m_rcDrag.top = 0; 902 m_rcDrag.bottom = m_rcDrag.top + m_cyHeight; 903 } 904 else 905 { 906 m_uSide = ABE_BOTTOM; 907 m_rcDrag.bottom = cyScreen; 908 m_rcDrag.top = m_rcDrag.bottom - m_cyHeight; 909 } 910 } 911 912 AppBar_QueryPos(hwnd, &m_rcDrag); 913 914 if (m_bDragged) 915 { 916 MoveWindow(hwnd, m_rcDrag.left, m_rcDrag.top, 917 m_rcDrag.right - m_rcDrag.left, 918 m_rcDrag.bottom - m_rcDrag.top, 919 TRUE); 920 } 921 } 922 923 void OnLButtonUp(HWND hwnd, int x, int y, UINT keyFlags) 924 { 925 if (!m_fMoving) 926 return; 927 928 OnMouseMove(hwnd, x, y, keyFlags); 929 930 m_rcAppBar = m_rcDrag; 931 932 ReleaseCapture(); 933 934 if (m_fAutoHide) 935 { 936 switch (m_uSide) 937 { 938 case ABE_TOP: 939 m_rcDrag.bottom = m_rcDrag.top + 2; 940 break; 941 case ABE_BOTTOM: 942 m_rcDrag.top = m_rcDrag.bottom - 2; 943 break; 944 case ABE_LEFT: 945 m_rcDrag.right = m_rcDrag.left + 2; 946 break; 947 case ABE_RIGHT: 948 m_rcDrag.left = m_rcDrag.right - 2; 949 break; 950 } 951 } 952 953 if (m_bDragged) 954 { 955 if (m_fAutoHide) 956 { 957 AppBar_AutoHide(hwnd); 958 } 959 else 960 { 961 APPBARDATA abd = { sizeof(abd), hwnd }; 962 AppBar_QuerySetPos(m_uSide, &m_rcDrag, &abd, FALSE); 963 } 964 } 965 966 m_fMoving = FALSE; 967 } 968 969 void GetWorkArea(LPRECT prc) const 970 { 971 SystemParametersInfoW(SPI_GETWORKAREA, 0, prc, 0); 972 } 973 974 void Quit() 975 { 976 PostMessage(s_hwnd1, WM_COMMAND, ID_QUIT, 0); 977 PostMessage(s_hwnd2, WM_COMMAND, ID_QUIT, 0); 978 } 979 980public: 981 void DoAction() 982 { 983 trace("DoAction\n"); 984 985 TEST_Main(); 986 TEST_Dragging(); 987 TEST_AutoHide(); 988 TEST_FullScreen(); 989 990 Quit(); 991 } 992 993 void TEST_Main() 994 { 995 trace("TEST_Main\n"); 996 Sleep(INTERVAL); 997 998 POINT pt; 999 RECT rc1, rc2, rcWork; 1000 1001 BOOL ret = AppBar_GetTaskBarPos(s_hwnd1, &rc1); 1002 ok_int(ret, TRUE); 1003 ok_int(EqualRect(&rc1, &s_rcTaskBar), TRUE); 1004 1005 GetWindowRect(s_hwnd1, &rc1); 1006 GetWindowRect(s_hwnd2, &rc2); 1007 GetWorkArea(&rcWork); 1008 ok_long(rc1.left, s_rcWorkArea.left); 1009 ok_long(rc1.top, s_rcWorkArea.top); 1010 ok_long(rc1.right, s_rcWorkArea.right); 1011 ok_long(rc1.bottom, s_rcWorkArea.top + 80); 1012 ok_long(rc2.left, s_rcWorkArea.left); 1013 ok_long(rc2.top, s_rcWorkArea.top + 80); 1014 ok_long(rc2.right, s_rcWorkArea.right); 1015 ok_long(rc2.bottom, s_rcWorkArea.top + 110); 1016 ok_long(rcWork.left, s_rcWorkArea.left); 1017 ok_long(rcWork.top, s_rcWorkArea.top + 110); 1018 ok_long(rcWork.right, s_rcWorkArea.right); 1019 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1020 PostMessageW(s_hwnd1, WM_CLOSE, 0, 0); 1021 Sleep(LONG_INTERVAL); 1022 1023 GetWindowRect(s_hwnd2, &rc2); 1024 GetWorkArea(&rcWork); 1025 ok_long(rc2.left, s_rcWorkArea.left); 1026 ok_long(rc2.top, s_rcWorkArea.top); 1027 ok_long(rc2.right, s_rcWorkArea.right); 1028 ok_long(rc2.bottom, s_rcWorkArea.top + 30); 1029 ok_long(rcWork.left, s_rcWorkArea.left); 1030 ok_long(rcWork.top, s_rcWorkArea.top + 30); 1031 ok_long(rcWork.right, s_rcWorkArea.right); 1032 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1033 AppBar_SetSide(s_hwnd2, ABE_LEFT); 1034 Sleep(INTERVAL); 1035 1036 GetWindowRect(s_hwnd2, &rc2); 1037 GetWorkArea(&rcWork); 1038 ok_long(rc2.left, s_rcWorkArea.left); 1039 ok_long(rc2.top, s_rcWorkArea.top); 1040 ok_long(rc2.right, s_rcWorkArea.left + 30); 1041 ok_long(rcWork.left, s_rcWorkArea.left + 30); 1042 ok_long(rcWork.top, s_rcWorkArea.top); 1043 ok_long(rcWork.right, s_rcWorkArea.right); 1044 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1045 AppBar_SetSide(s_hwnd2, ABE_TOP); 1046 Sleep(INTERVAL); 1047 1048 GetWindowRect(s_hwnd2, &rc2); 1049 GetWorkArea(&rcWork); 1050 ok_long(rc2.left, s_rcWorkArea.left); 1051 ok_long(rc2.top, s_rcWorkArea.top); 1052 ok_long(rc2.right, s_rcWorkArea.right); 1053 ok_long(rc2.bottom, s_rcWorkArea.top + 30); 1054 ok_long(rcWork.left, s_rcWorkArea.left); 1055 ok_long(rcWork.top, s_rcWorkArea.top + 30); 1056 ok_long(rcWork.right, s_rcWorkArea.right); 1057 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1058 AppBar_SetSide(s_hwnd2, ABE_RIGHT); 1059 Sleep(INTERVAL); 1060 1061 GetWindowRect(s_hwnd2, &rc2); 1062 GetWorkArea(&rcWork); 1063 ok_long(rc2.left, s_rcWorkArea.right - 30); 1064 ok_long(rc2.top, s_rcWorkArea.top); 1065 ok_long(rc2.right, s_rcWorkArea.right); 1066 ok_long(rcWork.left, s_rcWorkArea.left); 1067 ok_long(rcWork.top, s_rcWorkArea.top); 1068 ok_long(rcWork.right, s_rcWorkArea.right - 30); 1069 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1070 Sleep(INTERVAL); 1071 1072 GetWindowRect(s_hwnd2, &rc2); 1073 pt.x = (rc2.left + rc2.right) / 2; 1074 pt.y = (rc2.top + rc2.bottom) / 2; 1075 MOVE(pt.x, pt.y); 1076 LEFT_DOWN(); 1077 MOVE(pt.x + 64, pt.y + 64); 1078 Sleep(INTERVAL); 1079 1080 pt.x = s_rcWorkArea.left + 80; 1081 pt.y = (s_rcWorkArea.top + s_rcWorkArea.bottom) / 2; 1082 MOVE(pt.x, pt.y); 1083 LEFT_UP(); 1084 Sleep(INTERVAL); 1085 1086 GetWindowRect(s_hwnd2, &rc2); 1087 GetWorkArea(&rcWork); 1088 ok_long(rc2.left, s_rcWorkArea.left); 1089 ok_long(rc2.top, s_rcWorkArea.top); 1090 ok_long(rc2.right, s_rcWorkArea.left + 30); 1091 ok_long(rcWork.left, s_rcWorkArea.left + 30); 1092 ok_long(rcWork.top, s_rcWorkArea.top); 1093 ok_long(rcWork.right, s_rcWorkArea.right); 1094 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1095 Sleep(INTERVAL); 1096 } 1097 1098 void TEST_Dragging() 1099 { 1100 trace("TEST_Dragging\n"); 1101 1102 RECT rc, rcWork; 1103 POINT pt; 1104 1105 GetWindowRect(s_hwnd2, &rc); 1106 pt.x = (rc.left + rc.right) / 2; 1107 pt.y = (rc.top + rc.bottom) / 2; 1108 MOVE(pt.x, pt.y); 1109 LEFT_DOWN(); 1110 Sleep(INTERVAL); 1111 1112 pt.x = (s_rcWorkArea.left + s_rcWorkArea.right) / 2; 1113 pt.y = s_rcWorkArea.top; 1114 MOVE(pt.x, pt.y); 1115 Sleep(INTERVAL); 1116 1117 pt.x = s_rcWorkArea.right - 1; 1118 pt.y = (s_rcWorkArea.top + s_rcWorkArea.bottom) / 2; 1119 MOVE(pt.x, pt.y); 1120 LEFT_UP(); 1121 Sleep(LONG_INTERVAL); 1122 1123 GetWindowRect(s_hwnd2, &rc); 1124 GetWorkArea(&rcWork); 1125 ok_long(rc.left, s_rcWorkArea.right - 30); 1126 ok_long(rc.top, s_rcWorkArea.top); 1127 ok_long(rc.right, s_rcWorkArea.right); 1128 ok_long(rcWork.left, s_rcWorkArea.left); 1129 ok_long(rcWork.top, s_rcWorkArea.top); 1130 ok_long(rcWork.right, s_rcWorkArea.right - 30); 1131 ok_long(rcWork.bottom, s_rcWorkArea.bottom); 1132 } 1133 1134 void TEST_AutoHide() 1135 { 1136 trace("TEST_AutoHide\n"); 1137 1138 RECT rc; 1139 1140 m_cxWidth = 80; 1141 m_cyHeight = 40; 1142 AppBar_SetSide(s_hwnd2, ABE_TOP); 1143 AppBar_AutoHide(s_hwnd2); 1144 HWND hwndRet = AppBar_GetAutoHideBar(s_hwnd2, ABE_TOP); 1145 ok_ptr(hwndRet, s_hwnd2); 1146 Sleep(LONG_INTERVAL); 1147 1148 GetWindowRect(s_hwnd2, &rc); 1149 ok_long(rc.left, s_rcWorkArea.left); 1150 ok_long(rc.top, s_rcWorkArea.top); 1151 ok_long(rc.right, s_rcWorkArea.right); 1152 ok_long(rc.bottom, s_rcWorkArea.top + 2); 1153 1154 MOVE((s_rcWorkArea.left + s_rcWorkArea.right) / 2, s_rcWorkArea.top); 1155 LEFT_DOWN(); 1156 LEFT_UP(); 1157 Sleep(LONG_INTERVAL); 1158 1159 GetWindowRect(s_hwnd2, &rc); 1160 ok_long(rc.left, s_rcWorkArea.left); 1161 ok_long(rc.top, s_rcWorkArea.top); 1162 ok_long(rc.right, s_rcWorkArea.right); 1163 ok_long(rc.bottom, s_rcWorkArea.top + 40); 1164 1165 MOVE((s_rcWorkArea.left + s_rcWorkArea.right) / 2, s_rcWorkArea.bottom - 1); 1166 LEFT_DOWN(); 1167 LEFT_UP(); 1168 Sleep(LONG_INTERVAL); 1169 1170 GetWindowRect(s_hwnd2, &rc); 1171 ok_long(rc.left, s_rcWorkArea.left); 1172 ok_long(rc.top, s_rcWorkArea.top); 1173 ok_long(rc.right, s_rcWorkArea.right); 1174 ok_long(rc.bottom, s_rcWorkArea.top + 2); 1175 1176 SetForegroundWindow(s_hwnd2); 1177 Sleep(LONG_INTERVAL); 1178 1179 GetWindowRect(s_hwnd2, &rc); 1180 ok_long(rc.left, s_rcWorkArea.left); 1181 ok_long(rc.top, s_rcWorkArea.top); 1182 ok_long(rc.right, s_rcWorkArea.right); 1183 ok_long(rc.bottom, s_rcWorkArea.top + 40); 1184 1185 AppBar_SetSide(s_hwnd2, ABE_RIGHT); 1186 AppBar_AutoHide(s_hwnd2); 1187 SetForegroundWindow(s_hwnd2); 1188 hwndRet = AppBar_GetAutoHideBar(s_hwnd2, ABE_RIGHT); 1189 ok_ptr(hwndRet, s_hwnd2); 1190 1191 GetWindowRect(s_hwnd2, &rc); 1192 ok_long(rc.left, s_rcWorkArea.right - 2); 1193 ok_long(rc.top, s_rcWorkArea.top); 1194 ok_long(rc.right, s_rcWorkArea.right); 1195 ok_long(rc.bottom, s_rcWorkArea.bottom); 1196 1197 MOVE(s_rcWorkArea.left, (s_rcWorkArea.top + s_rcWorkArea.bottom) / 2); 1198 Sleep(LONG_INTERVAL); 1199 1200 GetWindowRect(s_hwnd2, &rc); 1201 ok_long(rc.left, s_rcWorkArea.right - 2); 1202 ok_long(rc.top, s_rcWorkArea.top); 1203 ok_long(rc.right, s_rcWorkArea.right); 1204 ok_long(rc.bottom, s_rcWorkArea.bottom); 1205 } 1206 1207 void TEST_FullScreen() 1208 { 1209 trace("TEST_FullScreen\n"); 1210 RECT rc = s_rcPrimaryMonitor; 1211 m_bGotFullScreen = FALSE; 1212 MoveWindow(s_hwnd2, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); 1213 Sleep(LONG_INTERVAL); 1214 ok_int(m_bGotFullScreen, TRUE); 1215 MoveWindow(s_hwnd2, rc.left, rc.top, 100, 100, TRUE); 1216 } 1217 1218 static DWORD WINAPI ActionThreadFunc(LPVOID args) 1219 { 1220 Window *this_ = (Window *)args; 1221 this_->DoAction(); 1222 return 0; 1223 } 1224}; 1225 1226START_TEST(SHAppBarMessage) 1227{ 1228 HINSTANCE hInstance = GetModuleHandle(NULL); 1229 1230 // Check Taskbar 1231 HWND hTrayWnd = FindWindowW(L"Shell_TrayWnd", NULL); 1232 if (!IsWindowVisible(hTrayWnd)) 1233 { 1234 skip("Taskbar not found\n"); 1235 return; 1236 } 1237 1238 // Taskbar 1239 RECT rc; 1240 GetWindowRect(hTrayWnd, &rc); 1241 s_rcTaskBar = rc; 1242 trace("s_rcTaskBar: %ld, %ld, %ld, %ld\n", rc.left, rc.top, rc.right, rc.bottom); 1243 1244 // Work area 1245 SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, FALSE); 1246 s_rcWorkArea = rc; 1247 trace("s_rcWorkArea: %ld, %ld, %ld, %ld\n", rc.left, rc.top, rc.right, rc.bottom); 1248 1249 // Primary monitor 1250 SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); 1251 s_rcPrimaryMonitor = rc; 1252 trace("s_rcPrimaryMonitor: %ld, %ld, %ld, %ld\n", rc.left, rc.top, rc.right, rc.bottom); 1253 1254 if (s_rcTaskBar.left > s_rcPrimaryMonitor.left || 1255 s_rcTaskBar.right < s_rcPrimaryMonitor.right || 1256 s_rcTaskBar.bottom < s_rcPrimaryMonitor.bottom) 1257 { 1258 // Taskbar must be bottom in this testcase 1259 skip("Taskbar was not bottom\n"); 1260 return; 1261 } 1262 1263 if (!Window::DoRegisterClass(hInstance)) 1264 { 1265 skip("Window::DoRegisterClass failed\n"); 1266 return; 1267 } 1268 1269 trace("SM_CMONITORS: %d\n", GetSystemMetrics(SM_CMONITORS)); 1270 if (GetSystemMetrics(SM_CMONITORS) != 1) 1271 { 1272 skip("Multi-monitor not supported yet\n"); 1273 return; 1274 } 1275 1276 HWND hwnd1 = Window::DoCreateMainWnd(hInstance, TEXT("Test1"), 80, 80, 1277 WS_POPUP | WS_THICKFRAME | WS_CLIPCHILDREN); 1278 if (!hwnd1) 1279 { 1280 skip("CreateWindowExW failed\n"); 1281 return; 1282 } 1283 1284 HWND hwnd2 = Window::DoCreateMainWnd(hInstance, TEXT("Test2"), 30, 30, 1285 WS_POPUP | WS_BORDER | WS_CLIPCHILDREN); 1286 if (!hwnd2) 1287 { 1288 skip("CreateWindowExW failed\n"); 1289 return; 1290 } 1291 1292 s_hwnd1 = hwnd1; 1293 s_hwnd2 = hwnd2; 1294 1295 PostMessageW(hwnd1, WM_COMMAND, ID_ACTION, 0); 1296 1297 // message loop 1298 MSG msg; 1299 while (GetMessage(&msg, NULL, 0, 0)) 1300 { 1301 TranslateMessage(&msg); 1302 DispatchMessage(&msg); 1303 } 1304}