1 /* 2 * PROJECT: ReactOS Clipboard Viewer 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Provides a view of the contents of the ReactOS clipboard. 5 * COPYRIGHT: Copyright 2015-2018 Ricardo Hanke 6 * Copyright 2015-2018 Hermes Belusca-Maito 7 */ 8 9 #include "precomp.h" 10 11 static const WCHAR szClassName[] = L"ClipBookWClass"; 12 13 CLIPBOARD_GLOBALS Globals; 14 SCROLLSTATE Scrollstate; 15 16 static void SaveClipboardToFile(void) 17 { 18 OPENFILENAMEW sfn; 19 LPWSTR c; 20 WCHAR szFileName[MAX_PATH]; 21 WCHAR szFilterMask[MAX_STRING_LEN + 10]; 22 23 ZeroMemory(&szFilterMask, sizeof(szFilterMask)); 24 c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_NT, szFilterMask, MAX_STRING_LEN) + 1; 25 wcscpy(c, L"*.clp"); 26 27 ZeroMemory(&szFileName, sizeof(szFileName)); 28 ZeroMemory(&sfn, sizeof(sfn)); 29 sfn.lStructSize = sizeof(sfn); 30 sfn.hwndOwner = Globals.hMainWnd; 31 sfn.hInstance = Globals.hInstance; 32 sfn.lpstrFilter = szFilterMask; 33 sfn.lpstrFile = szFileName; 34 sfn.nMaxFile = ARRAYSIZE(szFileName); 35 sfn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; 36 sfn.lpstrDefExt = L"clp"; 37 38 if (!GetSaveFileNameW(&sfn)) 39 return; 40 41 if (!OpenClipboard(Globals.hMainWnd)) 42 { 43 ShowLastWin32Error(Globals.hMainWnd); 44 return; 45 } 46 47 WriteClipboardFile(szFileName, CLIP_FMT_NT /* CLIP_FMT_31 */); 48 49 CloseClipboard(); 50 } 51 52 static void LoadClipboardDataFromFile(LPWSTR lpszFileName) 53 { 54 if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance, 55 STRING_DELETE_MSG, STRING_DELETE_TITLE, 56 MB_ICONWARNING | MB_YESNO) != IDYES) 57 { 58 return; 59 } 60 61 if (!OpenClipboard(Globals.hMainWnd)) 62 { 63 ShowLastWin32Error(Globals.hMainWnd); 64 return; 65 } 66 67 EmptyClipboard(); 68 ReadClipboardFile(lpszFileName); 69 70 CloseClipboard(); 71 } 72 73 static void LoadClipboardFromFile(void) 74 { 75 OPENFILENAMEW ofn; 76 LPWSTR c; 77 WCHAR szFileName[MAX_PATH]; 78 WCHAR szFilterMask[MAX_STRING_LEN + 10]; 79 80 ZeroMemory(&szFilterMask, sizeof(szFilterMask)); 81 c = szFilterMask + LoadStringW(Globals.hInstance, STRING_FORMAT_GEN, szFilterMask, MAX_STRING_LEN) + 1; 82 wcscpy(c, L"*.clp"); 83 84 ZeroMemory(&szFileName, sizeof(szFileName)); 85 ZeroMemory(&ofn, sizeof(ofn)); 86 ofn.lStructSize = sizeof(ofn); 87 ofn.hwndOwner = Globals.hMainWnd; 88 ofn.hInstance = Globals.hInstance; 89 ofn.lpstrFilter = szFilterMask; 90 ofn.lpstrFile = szFileName; 91 ofn.nMaxFile = ARRAYSIZE(szFileName); 92 ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; 93 94 if (!GetOpenFileNameW(&ofn)) 95 return; 96 97 LoadClipboardDataFromFile(szFileName); 98 } 99 100 static void LoadClipboardFromDrop(HDROP hDrop) 101 { 102 WCHAR szFileName[MAX_PATH]; 103 104 DragQueryFileW(hDrop, 0, szFileName, ARRAYSIZE(szFileName)); 105 DragFinish(hDrop); 106 107 LoadClipboardDataFromFile(szFileName); 108 } 109 110 static void SetDisplayFormat(UINT uFormat) 111 { 112 RECT rc; 113 114 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_UNCHECKED); 115 Globals.uCheckedItem = uFormat + CMD_AUTOMATIC; 116 CheckMenuItem(Globals.hMenu, Globals.uCheckedItem, MF_BYCOMMAND | MF_CHECKED); 117 118 if (uFormat == 0) 119 { 120 Globals.uDisplayFormat = GetAutomaticClipboardFormat(); 121 } 122 else 123 { 124 Globals.uDisplayFormat = uFormat; 125 } 126 127 GetClipboardDataDimensions(Globals.uDisplayFormat, &rc); 128 Scrollstate.CurrentX = Scrollstate.CurrentY = 0; 129 Scrollstate.iWheelCarryoverX = Scrollstate.iWheelCarryoverY = 0; 130 UpdateWindowScrollState(Globals.hMainWnd, rc.right, rc.bottom, &Scrollstate); 131 132 InvalidateRect(Globals.hMainWnd, NULL, TRUE); 133 } 134 135 static void InitMenuPopup(HMENU hMenu, LPARAM index) 136 { 137 if ((GetMenuItemID(hMenu, 0) == CMD_DELETE) || (GetMenuItemID(hMenu, 1) == CMD_SAVE_AS)) 138 { 139 if (CountClipboardFormats() == 0) 140 { 141 EnableMenuItem(hMenu, CMD_DELETE, MF_GRAYED); 142 EnableMenuItem(hMenu, CMD_SAVE_AS, MF_GRAYED); 143 } 144 else 145 { 146 EnableMenuItem(hMenu, CMD_DELETE, MF_ENABLED); 147 EnableMenuItem(hMenu, CMD_SAVE_AS, MF_ENABLED); 148 } 149 } 150 151 DrawMenuBar(Globals.hMainWnd); 152 } 153 154 static void UpdateDisplayMenu(void) 155 { 156 UINT uFormat; 157 HMENU hMenu; 158 WCHAR szFormatName[MAX_FMT_NAME_LEN + 1]; 159 160 hMenu = GetSubMenu(Globals.hMenu, DISPLAY_MENU_POS); 161 162 while (GetMenuItemCount(hMenu) > 1) 163 { 164 DeleteMenu(hMenu, 1, MF_BYPOSITION); 165 } 166 167 if (CountClipboardFormats() == 0) 168 return; 169 170 if (!OpenClipboard(Globals.hMainWnd)) 171 return; 172 173 AppendMenuW(hMenu, MF_SEPARATOR, 0, NULL); 174 175 /* Display the supported clipboard formats first */ 176 for (uFormat = EnumClipboardFormats(0); uFormat; 177 uFormat = EnumClipboardFormats(uFormat)) 178 { 179 if (IsClipboardFormatSupported(uFormat)) 180 { 181 RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE, 182 szFormatName, ARRAYSIZE(szFormatName)); 183 AppendMenuW(hMenu, MF_STRING, CMD_AUTOMATIC + uFormat, szFormatName); 184 } 185 } 186 187 /* Now display the unsupported clipboard formats */ 188 for (uFormat = EnumClipboardFormats(0); uFormat; 189 uFormat = EnumClipboardFormats(uFormat)) 190 { 191 if (!IsClipboardFormatSupported(uFormat)) 192 { 193 RetrieveClipboardFormatName(Globals.hInstance, uFormat, TRUE, 194 szFormatName, ARRAYSIZE(szFormatName)); 195 AppendMenuW(hMenu, MF_STRING | MF_GRAYED, 0, szFormatName); 196 } 197 } 198 199 CloseClipboard(); 200 } 201 202 static int OnCommand(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 203 { 204 switch (LOWORD(wParam)) 205 { 206 case CMD_OPEN: 207 { 208 LoadClipboardFromFile(); 209 break; 210 } 211 212 case CMD_SAVE_AS: 213 { 214 SaveClipboardToFile(); 215 break; 216 } 217 218 case CMD_EXIT: 219 { 220 PostMessageW(Globals.hMainWnd, WM_CLOSE, 0, 0); 221 break; 222 } 223 224 case CMD_DELETE: 225 { 226 if (MessageBoxRes(Globals.hMainWnd, Globals.hInstance, 227 STRING_DELETE_MSG, STRING_DELETE_TITLE, 228 MB_ICONWARNING | MB_YESNO) != IDYES) 229 { 230 break; 231 } 232 233 DeleteClipboardContent(); 234 break; 235 } 236 237 case CMD_AUTOMATIC: 238 { 239 SetDisplayFormat(0); 240 break; 241 } 242 243 case CMD_HELP: 244 { 245 HtmlHelpW(Globals.hMainWnd, L"clipbrd.chm", 0, 0); 246 break; 247 } 248 249 case CMD_ABOUT: 250 { 251 WCHAR szTitle[MAX_STRING_LEN]; 252 253 LoadStringW(Globals.hInstance, STRING_CLIPBOARD, szTitle, ARRAYSIZE(szTitle)); 254 ShellAboutW(Globals.hMainWnd, szTitle, NULL, 255 LoadIconW(Globals.hInstance, MAKEINTRESOURCEW(CLIPBRD_ICON))); 256 break; 257 } 258 259 default: 260 { 261 break; 262 } 263 } 264 return 0; 265 } 266 267 static void OnPaint(HWND hWnd, WPARAM wParam, LPARAM lParam) 268 { 269 HDC hdc; 270 PAINTSTRUCT ps; 271 COLORREF crOldBkColor, crOldTextColor; 272 RECT rc; 273 274 if (!OpenClipboard(Globals.hMainWnd)) 275 return; 276 277 hdc = BeginPaint(hWnd, &ps); 278 279 /* Erase the background if needed */ 280 if (ps.fErase) 281 FillRect(ps.hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1)); 282 283 /* Set the correct background and text colors */ 284 crOldBkColor = SetBkColor(ps.hdc, GetSysColor(COLOR_WINDOW)); 285 crOldTextColor = SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT)); 286 287 /* Realize the clipboard palette if there is one */ 288 RealizeClipboardPalette(ps.hdc); 289 290 switch (Globals.uDisplayFormat) 291 { 292 case CF_NONE: 293 { 294 /* The clipboard is empty */ 295 break; 296 } 297 298 case CF_DSPTEXT: 299 case CF_TEXT: 300 case CF_OEMTEXT: 301 case CF_UNICODETEXT: 302 { 303 DrawTextFromClipboard(Globals.uDisplayFormat, ps, Scrollstate); 304 break; 305 } 306 307 case CF_DSPBITMAP: 308 case CF_BITMAP: 309 { 310 BitBltFromClipboard(ps, Scrollstate, SRCCOPY); 311 break; 312 } 313 314 case CF_DIB: 315 case CF_DIBV5: 316 { 317 SetDIBitsToDeviceFromClipboard(Globals.uDisplayFormat, ps, Scrollstate, DIB_RGB_COLORS); 318 break; 319 } 320 321 case CF_DSPMETAFILEPICT: 322 case CF_METAFILEPICT: 323 { 324 GetClientRect(hWnd, &rc); 325 PlayMetaFileFromClipboard(hdc, &rc); 326 break; 327 } 328 329 case CF_DSPENHMETAFILE: 330 case CF_ENHMETAFILE: 331 { 332 GetClientRect(hWnd, &rc); 333 PlayEnhMetaFileFromClipboard(hdc, &rc); 334 break; 335 } 336 337 // case CF_PALETTE: 338 // TODO: Draw a palette with squares filled with colors. 339 // break; 340 341 case CF_OWNERDISPLAY: 342 { 343 HGLOBAL hglb; 344 PPAINTSTRUCT pps; 345 346 hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(ps)); 347 if (hglb) 348 { 349 pps = GlobalLock(hglb); 350 CopyMemory(pps, &ps, sizeof(ps)); 351 GlobalUnlock(hglb); 352 353 SendClipboardOwnerMessage(TRUE, WM_PAINTCLIPBOARD, 354 (WPARAM)hWnd, (LPARAM)hglb); 355 356 GlobalFree(hglb); 357 } 358 break; 359 } 360 361 case CF_HDROP: 362 { 363 GetClientRect(hWnd, &rc); 364 HDropFromClipboard(hdc, &rc); 365 break; 366 } 367 368 default: 369 { 370 GetClientRect(hWnd, &rc); 371 DrawTextFromResource(Globals.hInstance, ERROR_UNSUPPORTED_FORMAT, 372 hdc, &rc, DT_CENTER | DT_WORDBREAK | DT_NOPREFIX); 373 break; 374 } 375 } 376 377 /* Restore the original colors */ 378 SetTextColor(ps.hdc, crOldTextColor); 379 SetBkColor(ps.hdc, crOldBkColor); 380 381 EndPaint(hWnd, &ps); 382 383 CloseClipboard(); 384 } 385 386 static LRESULT WINAPI MainWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 387 { 388 switch(uMsg) 389 { 390 case WM_CREATE: 391 { 392 TEXTMETRICW tm; 393 HDC hDC = GetDC(hWnd); 394 395 /* 396 * Note that the method with GetObjectW just returns 397 * the original parameters with which the font was created. 398 */ 399 if (GetTextMetricsW(hDC, &tm)) 400 { 401 Globals.CharWidth = tm.tmMaxCharWidth; // tm.tmAveCharWidth; 402 Globals.CharHeight = tm.tmHeight + tm.tmExternalLeading; 403 } 404 ReleaseDC(hWnd, hDC); 405 406 407 Globals.hMenu = GetMenu(hWnd); 408 Globals.hWndNext = SetClipboardViewer(hWnd); 409 410 // For now, the Help dialog item is disabled because of lacking of HTML support 411 EnableMenuItem(Globals.hMenu, CMD_HELP, MF_BYCOMMAND | MF_GRAYED); 412 413 UpdateLinesToScroll(&Scrollstate); 414 415 UpdateDisplayMenu(); 416 SetDisplayFormat(0); 417 418 DragAcceptFiles(hWnd, TRUE); 419 break; 420 } 421 422 case WM_CLOSE: 423 { 424 DestroyWindow(hWnd); 425 break; 426 } 427 428 case WM_DESTROY: 429 { 430 ChangeClipboardChain(hWnd, Globals.hWndNext); 431 432 if (Globals.uDisplayFormat == CF_OWNERDISPLAY) 433 { 434 HGLOBAL hglb; 435 PRECT prc; 436 437 hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(*prc)); 438 if (hglb) 439 { 440 prc = GlobalLock(hglb); 441 SetRectEmpty(prc); 442 GlobalUnlock(hglb); 443 444 SendClipboardOwnerMessage(TRUE, WM_SIZECLIPBOARD, 445 (WPARAM)hWnd, (LPARAM)hglb); 446 447 GlobalFree(hglb); 448 } 449 } 450 451 PostQuitMessage(0); 452 break; 453 } 454 455 case WM_PAINT: 456 { 457 OnPaint(hWnd, wParam, lParam); 458 break; 459 } 460 461 case WM_KEYDOWN: 462 { 463 OnKeyScroll(hWnd, wParam, lParam, &Scrollstate); 464 break; 465 } 466 467 case WM_MOUSEWHEEL: 468 case WM_MOUSEHWHEEL: 469 { 470 OnMouseScroll(hWnd, uMsg, wParam, lParam, &Scrollstate); 471 break; 472 } 473 474 case WM_HSCROLL: 475 { 476 // NOTE: Windows uses an offset of 16 pixels 477 OnScroll(hWnd, SB_HORZ, wParam, 5, &Scrollstate); 478 break; 479 } 480 481 case WM_VSCROLL: 482 { 483 // NOTE: Windows uses an offset of 16 pixels 484 OnScroll(hWnd, SB_VERT, wParam, 5, &Scrollstate); 485 break; 486 } 487 488 case WM_SIZE: 489 { 490 RECT rc; 491 492 if (Globals.uDisplayFormat == CF_OWNERDISPLAY) 493 { 494 HGLOBAL hglb; 495 PRECT prc; 496 497 hglb = GlobalAlloc(GMEM_MOVEABLE, sizeof(*prc)); 498 if (hglb) 499 { 500 prc = GlobalLock(hglb); 501 if (wParam == SIZE_MINIMIZED) 502 SetRectEmpty(prc); 503 else 504 GetClientRect(hWnd, prc); 505 GlobalUnlock(hglb); 506 507 SendClipboardOwnerMessage(TRUE, WM_SIZECLIPBOARD, 508 (WPARAM)hWnd, (LPARAM)hglb); 509 510 GlobalFree(hglb); 511 } 512 break; 513 } 514 515 GetClipboardDataDimensions(Globals.uDisplayFormat, &rc); 516 UpdateWindowScrollState(hWnd, rc.right, rc.bottom, &Scrollstate); 517 518 // NOTE: There still are little problems drawing 519 // the background when displaying clipboard text. 520 if (!IsClipboardFormatSupported(Globals.uDisplayFormat) || 521 Globals.uDisplayFormat == CF_DSPTEXT || 522 Globals.uDisplayFormat == CF_TEXT || 523 Globals.uDisplayFormat == CF_OEMTEXT || 524 Globals.uDisplayFormat == CF_UNICODETEXT) 525 { 526 InvalidateRect(Globals.hMainWnd, NULL, TRUE); 527 } 528 else 529 { 530 InvalidateRect(Globals.hMainWnd, NULL, FALSE); 531 } 532 533 break; 534 } 535 536 case WM_CHANGECBCHAIN: 537 { 538 /* Transmit through the clipboard viewer chain */ 539 if ((HWND)wParam == Globals.hWndNext) 540 { 541 Globals.hWndNext = (HWND)lParam; 542 } 543 else if (Globals.hWndNext != NULL) 544 { 545 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam); 546 } 547 548 break; 549 } 550 551 case WM_DESTROYCLIPBOARD: 552 break; 553 554 case WM_RENDERALLFORMATS: 555 { 556 /* 557 * When the user has cleared the clipboard via the DELETE command, 558 * we (clipboard viewer) become the clipboard owner. When we are 559 * subsequently closed, this message is then sent to us so that 560 * we get a chance to render everything we can. Since we don't have 561 * anything to render, just empty the clipboard. 562 */ 563 DeleteClipboardContent(); 564 break; 565 } 566 567 case WM_RENDERFORMAT: 568 // TODO! 569 break; 570 571 case WM_DRAWCLIPBOARD: 572 { 573 UpdateDisplayMenu(); 574 SetDisplayFormat(0); 575 576 /* Pass the message to the next window in clipboard viewer chain */ 577 SendMessageW(Globals.hWndNext, uMsg, wParam, lParam); 578 break; 579 } 580 581 case WM_COMMAND: 582 { 583 if ((LOWORD(wParam) > CMD_AUTOMATIC)) 584 { 585 SetDisplayFormat(LOWORD(wParam) - CMD_AUTOMATIC); 586 } 587 else 588 { 589 OnCommand(hWnd, uMsg, wParam, lParam); 590 } 591 break; 592 } 593 594 case WM_INITMENUPOPUP: 595 { 596 InitMenuPopup((HMENU)wParam, lParam); 597 break; 598 } 599 600 case WM_DROPFILES: 601 { 602 LoadClipboardFromDrop((HDROP)wParam); 603 break; 604 } 605 606 case WM_PALETTECHANGED: 607 { 608 /* Ignore if this comes from ourselves */ 609 if ((HWND)wParam == hWnd) 610 break; 611 612 /* Fall back to WM_QUERYNEWPALETTE */ 613 } 614 615 case WM_QUERYNEWPALETTE: 616 { 617 BOOL Success; 618 HDC hDC; 619 620 if (!OpenClipboard(Globals.hMainWnd)) 621 return FALSE; 622 623 hDC = GetDC(hWnd); 624 if (!hDC) 625 { 626 CloseClipboard(); 627 return FALSE; 628 } 629 630 Success = RealizeClipboardPalette(hDC); 631 632 ReleaseDC(hWnd, hDC); 633 CloseClipboard(); 634 635 if (Success) 636 { 637 InvalidateRect(hWnd, NULL, TRUE); 638 UpdateWindow(hWnd); 639 return TRUE; 640 } 641 return FALSE; 642 } 643 644 case WM_SYSCOLORCHANGE: 645 { 646 SetDisplayFormat(Globals.uDisplayFormat); 647 break; 648 } 649 650 case WM_SETTINGCHANGE: 651 { 652 if (wParam == SPI_SETWHEELSCROLLLINES) 653 { 654 UpdateLinesToScroll(&Scrollstate); 655 } 656 break; 657 } 658 659 default: 660 { 661 return DefWindowProc(hWnd, uMsg, wParam, lParam); 662 } 663 } 664 665 return 0; 666 } 667 668 int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) 669 { 670 MSG msg; 671 HACCEL hAccel; 672 HWND hPrevWindow; 673 WNDCLASSEXW wndclass; 674 WCHAR szBuffer[MAX_STRING_LEN]; 675 676 hPrevWindow = FindWindowW(szClassName, NULL); 677 if (hPrevWindow) 678 { 679 BringWindowToFront(hPrevWindow); 680 return 0; 681 } 682 683 switch (GetUserDefaultUILanguage()) 684 { 685 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): 686 SetProcessDefaultLayout(LAYOUT_RTL); 687 break; 688 689 default: 690 break; 691 } 692 693 ZeroMemory(&Globals, sizeof(Globals)); 694 Globals.hInstance = hInstance; 695 696 ZeroMemory(&wndclass, sizeof(wndclass)); 697 wndclass.cbSize = sizeof(wndclass); 698 wndclass.lpfnWndProc = MainWndProc; 699 wndclass.hInstance = hInstance; 700 wndclass.hIcon = LoadIconW(hInstance, MAKEINTRESOURCEW(CLIPBRD_ICON)); 701 wndclass.hCursor = LoadCursorW(0, IDC_ARROW); 702 wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 703 wndclass.lpszMenuName = MAKEINTRESOURCEW(MAIN_MENU); 704 wndclass.lpszClassName = szClassName; 705 706 if (!RegisterClassExW(&wndclass)) 707 { 708 ShowLastWin32Error(NULL); 709 return 0; 710 } 711 712 ZeroMemory(&Scrollstate, sizeof(Scrollstate)); 713 714 LoadStringW(hInstance, STRING_CLIPBOARD, szBuffer, ARRAYSIZE(szBuffer)); 715 Globals.hMainWnd = CreateWindowExW(WS_EX_CLIENTEDGE | WS_EX_ACCEPTFILES, 716 szClassName, 717 szBuffer, 718 WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 719 CW_USEDEFAULT, 720 CW_USEDEFAULT, 721 CW_USEDEFAULT, 722 CW_USEDEFAULT, 723 NULL, 724 NULL, 725 Globals.hInstance, 726 NULL); 727 if (!Globals.hMainWnd) 728 { 729 ShowLastWin32Error(NULL); 730 return 0; 731 } 732 733 ShowWindow(Globals.hMainWnd, nCmdShow); 734 UpdateWindow(Globals.hMainWnd); 735 736 hAccel = LoadAcceleratorsW(Globals.hInstance, MAKEINTRESOURCEW(ID_ACCEL)); 737 if (!hAccel) 738 { 739 ShowLastWin32Error(Globals.hMainWnd); 740 } 741 742 /* If the user provided a path to a clipboard data file, try to open it */ 743 if (__argc >= 2) 744 LoadClipboardDataFromFile(__wargv[1]); 745 746 while (GetMessageW(&msg, 0, 0, 0)) 747 { 748 if (!TranslateAcceleratorW(Globals.hMainWnd, hAccel, &msg)) 749 { 750 TranslateMessage(&msg); 751 DispatchMessageW(&msg); 752 } 753 } 754 755 return (int)msg.wParam; 756 } 757