1 /* 2 * PROJECT: ReactOS Applications Manager 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Application view class and other classes used by it 5 * COPYRIGHT: Copyright 2020 He Yang (1160386205@qq.com) 6 */ 7 8 #include "rapps.h" 9 #include "appview.h" 10 #include "gui.h" 11 #include <windowsx.h> 12 13 14 // **** CMainToolbar **** 15 16 VOID CMainToolbar::AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex) 17 { 18 HICON hImage; 19 20 if (!(hImage = (HICON)LoadImageW(hInst, 21 MAKEINTRESOURCE(ImageIndex), 22 IMAGE_ICON, 23 m_iToolbarHeight, 24 m_iToolbarHeight, 25 0))) 26 { 27 /* TODO: Error message */ 28 } 29 30 ImageList_AddIcon(hImageList, hImage); 31 DeleteObject(hImage); 32 } 33 34 HIMAGELIST CMainToolbar::InitImageList() 35 { 36 HIMAGELIST hImageList; 37 38 /* Create the toolbar icon image list */ 39 hImageList = ImageList_Create(m_iToolbarHeight,//GetSystemMetrics(SM_CXSMICON), 40 m_iToolbarHeight,//GetSystemMetrics(SM_CYSMICON), 41 ILC_MASK | GetSystemColorDepth(), 42 1, 1); 43 if (!hImageList) 44 { 45 /* TODO: Error message */ 46 return NULL; 47 } 48 49 AddImageToImageList(hImageList, IDI_INSTALL); 50 AddImageToImageList(hImageList, IDI_UNINSTALL); 51 AddImageToImageList(hImageList, IDI_MODIFY); 52 AddImageToImageList(hImageList, IDI_CHECK_ALL); 53 AddImageToImageList(hImageList, IDI_REFRESH); 54 AddImageToImageList(hImageList, IDI_UPDATE_DB); 55 AddImageToImageList(hImageList, IDI_SETTINGS); 56 AddImageToImageList(hImageList, IDI_EXIT); 57 58 return hImageList; 59 } 60 61 CMainToolbar::CMainToolbar() : m_iToolbarHeight(24) 62 { 63 } 64 65 VOID CMainToolbar::OnGetDispInfo(LPTOOLTIPTEXT lpttt) 66 { 67 UINT idButton = (UINT)lpttt->hdr.idFrom; 68 69 switch (idButton) 70 { 71 case ID_EXIT: 72 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT); 73 break; 74 75 case ID_INSTALL: 76 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL); 77 break; 78 79 case ID_UNINSTALL: 80 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL); 81 break; 82 83 case ID_MODIFY: 84 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY); 85 break; 86 87 case ID_SETTINGS: 88 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS); 89 break; 90 91 case ID_REFRESH: 92 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH); 93 break; 94 95 case ID_RESETDB: 96 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB); 97 break; 98 } 99 } 100 101 HWND CMainToolbar::Create(HWND hwndParent) 102 { 103 /* Create buttons */ 104 TBBUTTON Buttons[] = 105 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */ 106 { 0, ID_TOOLBAR_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR)szInstallBtn }, 107 { 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR)szUninstallBtn }, 108 { 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR)szModifyBtn }, 109 { 3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR)szSelectAll }, 110 { -1, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 }, 111 { 4, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 }, 112 { 5, ID_RESETDB, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 } 113 }; 114 115 LoadStringW(hInst, IDS_INSTALL, szInstallBtn, _countof(szInstallBtn)); 116 LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, _countof(szUninstallBtn)); 117 LoadStringW(hInst, IDS_MODIFY, szModifyBtn, _countof(szModifyBtn)); 118 LoadStringW(hInst, IDS_SELECT_ALL, szSelectAll, _countof(szSelectAll)); 119 120 m_hWnd = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, 121 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST, 122 0, 0, 0, 0, 123 hwndParent, 124 0, hInst, NULL); 125 126 if (!m_hWnd) 127 { 128 /* TODO: Show error message */ 129 return FALSE; 130 } 131 132 SendMessageW(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS); 133 SetButtonStructSize(); 134 135 /* Set image list */ 136 HIMAGELIST hImageList = InitImageList(); 137 138 if (!hImageList) 139 { 140 /* TODO: Show error message */ 141 return FALSE; 142 } 143 144 ImageList_Destroy(SetImageList(hImageList)); 145 146 AddButtons(_countof(Buttons), Buttons); 147 148 /* Remember ideal width to use as a max width of buttons */ 149 SIZE size; 150 GetIdealSize(FALSE, &size); 151 m_dButtonsWidthMax = size.cx; 152 153 return m_hWnd; 154 } 155 156 VOID CMainToolbar::HideButtonCaption() 157 { 158 DWORD dCurrentExStyle = (DWORD)SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0); 159 SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle | TBSTYLE_EX_MIXEDBUTTONS); 160 } 161 162 VOID CMainToolbar::ShowButtonCaption() 163 { 164 DWORD dCurrentExStyle = (DWORD)SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0); 165 SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle & ~TBSTYLE_EX_MIXEDBUTTONS); 166 } 167 168 DWORD CMainToolbar::GetMaxButtonsWidth() const 169 { 170 return m_dButtonsWidthMax; 171 } 172 // **** CMainToolbar **** 173 174 175 // **** CSearchBar **** 176 177 CSearchBar::CSearchBar() : m_Width(180), m_Height(22) 178 { 179 } 180 181 VOID CSearchBar::SetText(LPCWSTR lpszText) 182 { 183 SendMessageW(SB_SETTEXT, SBT_NOBORDERS, (LPARAM)lpszText); 184 } 185 186 HWND CSearchBar::Create(HWND hwndParent) 187 { 188 ATL::CStringW szBuf; 189 m_hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL, 190 WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL, 191 0, 0, m_Width, m_Height, 192 hwndParent, (HMENU)NULL, 193 hInst, 0); 194 195 SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0); 196 szBuf.LoadStringW(IDS_SEARCH_TEXT); 197 SetWindowTextW(szBuf); 198 return m_hWnd; 199 } 200 // **** CSearchBar **** 201 202 203 // **** CComboBox **** 204 205 CComboBox::CComboBox() : m_Width(80), m_Height(22) 206 { 207 } 208 209 HWND CComboBox::Create(HWND hwndParent) 210 { 211 m_hWnd = CreateWindowW(WC_COMBOBOX, L"", 212 CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 213 0, 0, m_Width, m_Height, hwndParent, NULL, 0, 214 NULL); 215 216 SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0); 217 218 for (int i = 0; i < (int)_countof(m_TypeStringID); i++) 219 { 220 ATL::CStringW szBuf; 221 szBuf.LoadStringW(m_TypeStringID[i]); 222 SendMessageW(CB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szBuf); 223 } 224 225 SendMessageW(CB_SETCURSEL, m_DefaultSelectType, 0); // select the first item 226 227 return m_hWnd; 228 } 229 // **** CComboBox **** 230 231 232 // **** CAppRichEdit **** 233 234 VOID CAppRichEdit::LoadAndInsertText(UINT uStringID, 235 const ATL::CStringW &szText, 236 DWORD StringFlags, 237 DWORD TextFlags) 238 { 239 ATL::CStringW szLoadedText; 240 if (!szText.IsEmpty() && szLoadedText.LoadStringW(uStringID)) 241 { 242 InsertText(szLoadedText, StringFlags); 243 InsertText(szText, TextFlags); 244 } 245 } 246 247 VOID CAppRichEdit::LoadAndInsertText(UINT uStringID, 248 DWORD StringFlags) 249 { 250 ATL::CStringW szLoadedText; 251 if (szLoadedText.LoadStringW(uStringID)) 252 { 253 InsertText(L"\n", 0); 254 InsertText(szLoadedText, StringFlags); 255 InsertText(L"\n", 0); 256 } 257 } 258 259 VOID CAppRichEdit::InsertVersionInfo(CAvailableApplicationInfo *Info) 260 { 261 if (Info->IsInstalled()) 262 { 263 if (Info->HasInstalledVersion()) 264 { 265 if (Info->HasUpdate()) 266 LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE, CFE_ITALIC); 267 else 268 LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC); 269 270 LoadAndInsertText(IDS_AINFO_VERSION, Info->m_szInstalledVersion, CFE_BOLD, 0); 271 } 272 else 273 { 274 LoadAndInsertText(IDS_STATUS_INSTALLED, CFE_ITALIC); 275 } 276 } 277 else 278 { 279 LoadAndInsertText(IDS_STATUS_NOTINSTALLED, CFE_ITALIC); 280 } 281 282 LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION, Info->m_szVersion, CFE_BOLD, 0); 283 } 284 285 VOID CAppRichEdit::InsertLicenseInfo(CAvailableApplicationInfo *Info) 286 { 287 ATL::CStringW szLicense; 288 switch (Info->m_LicenseType) 289 { 290 case LICENSE_OPENSOURCE: 291 szLicense.LoadStringW(IDS_LICENSE_OPENSOURCE); 292 break; 293 case LICENSE_FREEWARE: 294 szLicense.LoadStringW(IDS_LICENSE_FREEWARE); 295 break; 296 case LICENSE_TRIAL: 297 szLicense.LoadStringW(IDS_LICENSE_TRIAL); 298 break; 299 default: 300 LoadAndInsertText(IDS_AINFO_LICENSE, Info->m_szLicense, CFE_BOLD, 0); 301 return; 302 } 303 304 szLicense += L" (" + Info->m_szLicense + L")"; 305 LoadAndInsertText(IDS_AINFO_LICENSE, szLicense, CFE_BOLD, 0); 306 } 307 308 VOID CAppRichEdit::InsertLanguageInfo(CAvailableApplicationInfo *Info) 309 { 310 if (!Info->HasLanguageInfo()) 311 { 312 return; 313 } 314 315 const INT nTranslations = Info->m_LanguageLCIDs.GetSize(); 316 ATL::CStringW szLangInfo; 317 ATL::CStringW szLoadedTextAvailability; 318 ATL::CStringW szLoadedAInfoText; 319 320 szLoadedAInfoText.LoadStringW(IDS_AINFO_LANGUAGES); 321 322 if (Info->HasNativeLanguage()) 323 { 324 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION); 325 if (nTranslations > 1) 326 { 327 ATL::CStringW buf; 328 buf.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER); 329 szLangInfo.Format(buf, nTranslations - 1); 330 } 331 else 332 { 333 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE); 334 szLangInfo = L" (" + szLangInfo + L")"; 335 } 336 } 337 else if (Info->HasEnglishLanguage()) 338 { 339 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION); 340 if (nTranslations > 1) 341 { 342 ATL::CStringW buf; 343 buf.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER); 344 szLangInfo.Format(buf, nTranslations - 1); 345 } 346 else 347 { 348 szLangInfo.LoadStringW(IDS_LANGUAGE_SINGLE); 349 szLangInfo = L" (" + szLangInfo + L")"; 350 } 351 } 352 else 353 { 354 szLoadedTextAvailability.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION); 355 } 356 357 InsertText(szLoadedAInfoText, CFE_BOLD); 358 InsertText(szLoadedTextAvailability, NULL); 359 InsertText(szLangInfo, CFE_ITALIC); 360 } 361 362 BOOL CAppRichEdit::ShowAvailableAppInfo(CAvailableApplicationInfo *Info) 363 { 364 if (!Info) return FALSE; 365 366 SetText(Info->m_szName, CFE_BOLD); 367 InsertVersionInfo(Info); 368 InsertLicenseInfo(Info); 369 InsertLanguageInfo(Info); 370 371 LoadAndInsertText(IDS_AINFO_SIZE, Info->m_szSize, CFE_BOLD, 0); 372 LoadAndInsertText(IDS_AINFO_URLSITE, Info->m_szUrlSite, CFE_BOLD, CFE_LINK); 373 LoadAndInsertText(IDS_AINFO_DESCRIPTION, Info->m_szDesc, CFE_BOLD, 0); 374 LoadAndInsertText(IDS_AINFO_URLDOWNLOAD, Info->m_szUrlDownload, CFE_BOLD, CFE_LINK); 375 LoadAndInsertText(IDS_AINFO_PACKAGE_NAME, Info->m_szPkgName, CFE_BOLD, 0); 376 377 return TRUE; 378 } 379 380 inline VOID CAppRichEdit::InsertTextWithString(UINT StringID, DWORD StringFlags, const ATL::CStringW &Text, DWORD TextFlags) 381 { 382 if (!Text.IsEmpty()) 383 { 384 LoadAndInsertText(StringID, Text, StringFlags, TextFlags); 385 } 386 } 387 388 BOOL CAppRichEdit::ShowInstalledAppInfo(CInstalledApplicationInfo *Info) 389 { 390 if (!Info) return FALSE; 391 392 SetText(Info->szDisplayName, CFE_BOLD); 393 InsertText(L"\n", 0); 394 395 InsertTextWithString(IDS_INFO_VERSION, CFE_BOLD, Info->szDisplayVersion, 0); 396 InsertTextWithString(IDS_INFO_PUBLISHER, CFE_BOLD, Info->szPublisher, 0); 397 InsertTextWithString(IDS_INFO_REGOWNER, CFE_BOLD, Info->szRegOwner, 0); 398 InsertTextWithString(IDS_INFO_PRODUCTID, CFE_BOLD, Info->szProductID, 0); 399 InsertTextWithString(IDS_INFO_HELPLINK, CFE_BOLD, Info->szHelpLink, CFM_LINK); 400 InsertTextWithString(IDS_INFO_HELPPHONE, CFE_BOLD, Info->szHelpTelephone, 0); 401 InsertTextWithString(IDS_INFO_README, CFE_BOLD, Info->szReadme, 0); 402 InsertTextWithString(IDS_INFO_CONTACT, CFE_BOLD, Info->szContact, 0); 403 InsertTextWithString(IDS_INFO_UPDATEINFO, CFE_BOLD, Info->szURLUpdateInfo, CFM_LINK); 404 InsertTextWithString(IDS_INFO_INFOABOUT, CFE_BOLD, Info->szURLInfoAbout, CFM_LINK); 405 InsertTextWithString(IDS_INFO_COMMENTS, CFE_BOLD, Info->szComments, 0); 406 InsertTextWithString(IDS_INFO_INSTALLDATE, CFE_BOLD, Info->szInstallDate, 0); 407 InsertTextWithString(IDS_INFO_INSTLOCATION, CFE_BOLD, Info->szInstallLocation, 0); 408 InsertTextWithString(IDS_INFO_INSTALLSRC, CFE_BOLD, Info->szInstallSource, 0); 409 InsertTextWithString(IDS_INFO_UNINSTALLSTR, CFE_BOLD, Info->szUninstallString, 0); 410 InsertTextWithString(IDS_INFO_MODIFYPATH, CFE_BOLD, Info->szModifyPath, 0); 411 412 return TRUE; 413 } 414 415 VOID CAppRichEdit::SetWelcomeText() 416 { 417 ATL::CStringW szText; 418 419 szText.LoadStringW(IDS_WELCOME_TITLE); 420 SetText(szText, CFE_BOLD); 421 422 szText.LoadStringW(IDS_WELCOME_TEXT); 423 InsertText(szText, 0); 424 425 szText.LoadStringW(IDS_WELCOME_URL); 426 InsertText(szText, CFM_LINK); 427 } 428 // **** CAppRichEdit **** 429 430 431 int ScrnshotDownloadCallback( 432 pASYNCINET AsyncInet, 433 ASYNC_EVENT Event, 434 WPARAM wParam, 435 LPARAM lParam, 436 VOID *Extension 437 ) 438 { 439 ScrnshotDownloadParam *DownloadParam = (ScrnshotDownloadParam *)Extension; 440 switch (Event) 441 { 442 case ASYNCINET_DATA: 443 DWORD BytesWritten; 444 WriteFile(DownloadParam->hFile, (LPCVOID)wParam, (DWORD)lParam, &BytesWritten, NULL); 445 break; 446 case ASYNCINET_COMPLETE: 447 CloseHandle(DownloadParam->hFile); 448 SendMessage(DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, (WPARAM)ERROR_SUCCESS, (LPARAM)DownloadParam); 449 break; 450 case ASYNCINET_CANCELLED: 451 CloseHandle(DownloadParam->hFile); 452 SendMessage(DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, (WPARAM)ERROR_CANCELLED, (LPARAM)DownloadParam); 453 break; 454 case ASYNCINET_ERROR: 455 CloseHandle(DownloadParam->hFile); 456 SendMessage(DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, wParam, (LPARAM)DownloadParam); 457 break; 458 default: 459 ATLASSERT(FALSE); 460 break; 461 } 462 return 0; 463 } 464 465 466 // **** CAppScrnshotPreview **** 467 468 BOOL CAppScrnshotPreview::ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId) 469 { 470 theResult = 0; 471 switch (Msg) 472 { 473 case WM_CREATE: 474 hBrokenImgIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_BROKEN_IMAGE), IMAGE_ICON, BrokenImgSize, BrokenImgSize, 0); 475 break; 476 case WM_SIZE: 477 { 478 if (BrokenImgSize != min(min(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), BROKENIMG_ICON_SIZE)) 479 { 480 BrokenImgSize = min(min(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), BROKENIMG_ICON_SIZE); 481 482 if (hBrokenImgIcon) 483 { 484 DeleteObject(hBrokenImgIcon); 485 hBrokenImgIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_BROKEN_IMAGE), IMAGE_ICON, BrokenImgSize, BrokenImgSize, 0); 486 } 487 } 488 break; 489 } 490 case WM_RAPPS_DOWNLOAD_COMPLETE: 491 { 492 ScrnshotDownloadParam *DownloadParam = (ScrnshotDownloadParam *)lParam; 493 AsyncInetRelease(AsyncInet); 494 AsyncInet = NULL; 495 switch (wParam) 496 { 497 case ERROR_SUCCESS: 498 if (ContentID == DownloadParam->ID) 499 { 500 DisplayFile(DownloadParam->DownloadFileName); 501 // send a message to trigger resizing 502 ::SendMessageW(::GetParent(m_hWnd), WM_RAPPS_RESIZE_CHILDREN, 0, 0); 503 InvalidateRect(0, 0); 504 TempImagePath = DownloadParam->DownloadFileName; // record tmp file path in order to delete it when cleanup 505 } 506 else 507 { 508 // the picture downloaded is already outdated. delete it. 509 DeleteFileW(DownloadParam->DownloadFileName); 510 } 511 break; 512 case ERROR_CANCELLED: 513 DeleteFileW(DownloadParam->DownloadFileName); 514 break; 515 default: 516 DisplayFailed(); 517 // send a message to trigger resizing 518 ::SendMessageW(::GetParent(m_hWnd), WM_RAPPS_RESIZE_CHILDREN, 0, 0); 519 InvalidateRect(0, 0); 520 DeleteFileW(DownloadParam->DownloadFileName); 521 break; 522 } 523 delete DownloadParam; 524 break; 525 } 526 case WM_PAINT: 527 { 528 PAINTSTRUCT ps; 529 HDC hdc = BeginPaint(&ps); 530 CRect rect; 531 GetClientRect(&rect); 532 533 PaintOnDC(hdc, 534 rect.Width(), 535 rect.Height(), 536 ps.fErase); 537 538 EndPaint(&ps); 539 break; 540 } 541 case WM_PRINTCLIENT: 542 { 543 if (lParam & PRF_CHECKVISIBLE) 544 { 545 if (!IsWindowVisible()) break; 546 } 547 CRect rect; 548 GetClientRect(&rect); 549 550 PaintOnDC((HDC)wParam, 551 rect.Width(), 552 rect.Height(), 553 lParam & PRF_ERASEBKGND); 554 break; 555 } 556 case WM_ERASEBKGND: 557 { 558 return TRUE; // do not erase to avoid blinking 559 } 560 case WM_TIMER: 561 { 562 switch (wParam) 563 { 564 case TIMER_LOADING_ANIMATION: 565 LoadingAnimationFrame++; 566 LoadingAnimationFrame %= (LOADING_ANIMATION_PERIOD * LOADING_ANIMATION_FPS); 567 HDC hdc = GetDC(); 568 CRect rect; 569 GetClientRect(&rect); 570 571 PaintOnDC(hdc, 572 rect.Width(), 573 rect.Height(), 574 TRUE); 575 ReleaseDC(hdc); 576 } 577 break; 578 } 579 case WM_DESTROY: 580 { 581 PreviousDisplayCleanup(); 582 DeleteObject(hBrokenImgIcon); 583 hBrokenImgIcon = NULL; 584 break; 585 } 586 } 587 return FALSE; 588 } 589 590 VOID CAppScrnshotPreview::DisplayLoading() 591 { 592 SetStatus(SCRNSHOT_PREV_LOADING); 593 if (bLoadingTimerOn) 594 { 595 KillTimer(TIMER_LOADING_ANIMATION); 596 } 597 LoadingAnimationFrame = 0; 598 bLoadingTimerOn = TRUE; 599 SetTimer(TIMER_LOADING_ANIMATION, 1000 / LOADING_ANIMATION_FPS, 0); 600 } 601 602 VOID CAppScrnshotPreview::DisplayFailed() 603 { 604 InterlockedIncrement64(&ContentID); 605 SetStatus(SCRNSHOT_PREV_FAILED); 606 PreviousDisplayCleanup(); 607 } 608 609 BOOL CAppScrnshotPreview::DisplayFile(LPCWSTR lpszFileName) 610 { 611 PreviousDisplayCleanup(); 612 SetStatus(SCRNSHOT_PREV_IMAGE); 613 pImage = Bitmap::FromFile(lpszFileName, 0); 614 if (pImage->GetLastStatus() != Ok) 615 { 616 DisplayFailed(); 617 return FALSE; 618 } 619 return TRUE; 620 } 621 622 VOID CAppScrnshotPreview::SetStatus(SCRNSHOT_STATUS Status) 623 { 624 ScrnshotPrevStauts = Status; 625 } 626 627 VOID CAppScrnshotPreview::PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd) 628 { 629 // use an off screen dc to avoid blinking 630 HDC hdcMem = CreateCompatibleDC(hdc); 631 HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height); 632 SelectObject(hdcMem, hBitmap); 633 634 if (bDrawBkgnd) 635 { 636 HBRUSH hOldBrush = (HBRUSH)SelectObject(hdcMem, (HGDIOBJ)GetSysColorBrush(COLOR_BTNFACE)); 637 PatBlt(hdcMem, 0, 0, width, height, PATCOPY); 638 SelectObject(hdcMem, hOldBrush); 639 } 640 641 switch (ScrnshotPrevStauts) 642 { 643 case SCRNSHOT_PREV_EMPTY: 644 { 645 646 } 647 break; 648 649 case SCRNSHOT_PREV_LOADING: 650 { 651 Graphics graphics(hdcMem); 652 Color color(255, 0, 0); 653 SolidBrush dotBrush(Color(255, 100, 100, 100)); 654 655 graphics.SetSmoothingMode(SmoothingMode::SmoothingModeAntiAlias); 656 657 // Paint three dot 658 float DotWidth = GetLoadingDotWidth(width, height); 659 graphics.FillEllipse((Brush *)(&dotBrush), 660 (REAL)width / 2.0 - min(width, height) * 2.0 / 16.0 - DotWidth / 2.0, 661 (REAL)height / 2.0 - GetFrameDotShift(LoadingAnimationFrame + LOADING_ANIMATION_FPS / 4, width, height) - DotWidth / 2.0, 662 DotWidth, 663 DotWidth); 664 665 graphics.FillEllipse((Brush *)(&dotBrush), 666 (REAL)width / 2.0 - DotWidth / 2.0, 667 (REAL)height / 2.0 - GetFrameDotShift(LoadingAnimationFrame, width, height) - DotWidth / 2.0, 668 DotWidth, 669 DotWidth); 670 671 graphics.FillEllipse((Brush *)(&dotBrush), 672 (REAL)width / 2.0 + min(width, height) * 2.0 / 16.0 - DotWidth / 2.0, 673 (REAL)height / 2.0 - GetFrameDotShift(LoadingAnimationFrame - LOADING_ANIMATION_FPS / 4, width, height) - DotWidth / 2.0, 674 DotWidth, 675 DotWidth); 676 } 677 break; 678 679 case SCRNSHOT_PREV_IMAGE: 680 { 681 if (pImage) 682 { 683 // always draw entire image inside the window. 684 Graphics graphics(hdcMem); 685 float ZoomRatio = min(((float)width / (float)pImage->GetWidth()), ((float)height / (float)pImage->GetHeight())); 686 float ZoomedImgWidth = ZoomRatio * (float)pImage->GetWidth(); 687 float ZoomedImgHeight = ZoomRatio * (float)pImage->GetHeight(); 688 689 graphics.DrawImage(pImage, 690 ((float)width - ZoomedImgWidth) / 2.0, ((float)height - ZoomedImgHeight) / 2.0, 691 ZoomedImgWidth, ZoomedImgHeight); 692 } 693 } 694 break; 695 696 case SCRNSHOT_PREV_FAILED: 697 { 698 DrawIconEx(hdcMem, 699 (width - BrokenImgSize) / 2, 700 (height - BrokenImgSize) / 2, 701 hBrokenImgIcon, 702 BrokenImgSize, 703 BrokenImgSize, 704 NULL, 705 NULL, 706 DI_NORMAL | DI_COMPAT); 707 } 708 break; 709 } 710 711 // copy the content form off-screen dc to hdc 712 BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY); 713 DeleteDC(hdcMem); 714 DeleteObject(hBitmap); 715 } 716 717 float CAppScrnshotPreview::GetLoadingDotWidth(int width, int height) 718 { 719 return min(width, height) / 20.0; 720 } 721 722 float CAppScrnshotPreview::GetFrameDotShift(int Frame, int width, int height) 723 { 724 return min(width, height) * 725 (1.0 / 16.0) * 726 (2.0 / (2.0 - sqrt(3.0))) * 727 (max(sin((float)Frame * 2 * PI / (LOADING_ANIMATION_PERIOD * LOADING_ANIMATION_FPS)), sqrt(3.0) / 2.0) - sqrt(3.0) / 2.0); 728 } 729 730 ATL::CWndClassInfo &CAppScrnshotPreview::GetWndClassInfo() 731 { 732 DWORD csStyle = CS_VREDRAW | CS_HREDRAW; 733 static ATL::CWndClassInfo wc = 734 { 735 { 736 sizeof(WNDCLASSEX), 737 csStyle, 738 StartWindowProc, 739 0, 740 0, 741 NULL, 742 0, 743 LoadCursorW(NULL, IDC_ARROW), 744 (HBRUSH)(COLOR_BTNFACE + 1), 745 0, 746 L"RAppsScrnshotPreview", 747 NULL 748 }, 749 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 750 }; 751 return wc; 752 } 753 754 HWND CAppScrnshotPreview::Create(HWND hParent) 755 { 756 RECT r = { 0,0,0,0 }; 757 758 return CWindowImpl::Create(hParent, r, L"", WS_CHILD | WS_VISIBLE); 759 } 760 761 VOID CAppScrnshotPreview::PreviousDisplayCleanup() 762 { 763 if (bLoadingTimerOn) 764 { 765 KillTimer(TIMER_LOADING_ANIMATION); 766 bLoadingTimerOn = FALSE; 767 } 768 LoadingAnimationFrame = 0; 769 if (pImage) 770 { 771 delete pImage; 772 pImage = NULL; 773 } 774 if (AsyncInet) 775 { 776 AsyncInetCancel(AsyncInet); 777 } 778 if (!TempImagePath.IsEmpty()) 779 { 780 DeleteFileW(TempImagePath.GetString()); 781 TempImagePath.Empty(); 782 } 783 } 784 785 VOID CAppScrnshotPreview::DisplayEmpty() 786 { 787 InterlockedIncrement64(&ContentID); 788 SetStatus(SCRNSHOT_PREV_EMPTY); 789 PreviousDisplayCleanup(); 790 } 791 792 BOOL CAppScrnshotPreview::DisplayImage(LPCWSTR lpszLocation) 793 { 794 LONGLONG ID = InterlockedIncrement64(&ContentID); 795 PreviousDisplayCleanup(); 796 797 if (PathIsURLW(lpszLocation)) 798 { 799 DisplayLoading(); 800 801 ScrnshotDownloadParam *DownloadParam = new ScrnshotDownloadParam; 802 if (!DownloadParam) return FALSE; 803 804 DownloadParam->hwndNotify = m_hWnd; 805 DownloadParam->ID = ID; 806 // generate a filename 807 ATL::CStringW ScrnshotFolder = CAvailableApps::m_Strings.szAppsPath; 808 PathAppendW(ScrnshotFolder.GetBuffer(MAX_PATH), L"screenshots"); 809 ScrnshotFolder.ReleaseBuffer(); 810 811 if (!PathIsDirectoryW(ScrnshotFolder.GetString())) 812 { 813 CreateDirectoryW(ScrnshotFolder.GetString(), NULL); 814 } 815 816 if (!GetTempFileNameW(ScrnshotFolder.GetString(), L"img", 817 0, DownloadParam->DownloadFileName.GetBuffer(MAX_PATH))) 818 { 819 DownloadParam->DownloadFileName.ReleaseBuffer(); 820 delete DownloadParam; 821 DisplayFailed(); 822 return FALSE; 823 } 824 DownloadParam->DownloadFileName.ReleaseBuffer(); 825 826 DownloadParam->hFile = CreateFileW(DownloadParam->DownloadFileName.GetString(), 827 GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 828 if (DownloadParam->hFile == INVALID_HANDLE_VALUE) 829 { 830 delete DownloadParam; 831 DisplayFailed(); 832 return FALSE; 833 } 834 835 AsyncInet = AsyncInetDownload(0, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, lpszLocation, TRUE, ScrnshotDownloadCallback, DownloadParam); 836 if (!AsyncInet) 837 { 838 CloseHandle(DownloadParam->hFile); 839 DeleteFileW(DownloadParam->DownloadFileName.GetBuffer()); 840 delete DownloadParam; 841 DisplayFailed(); 842 return FALSE; 843 } 844 return TRUE; 845 } 846 else 847 { 848 return DisplayFile(lpszLocation); 849 } 850 } 851 852 int CAppScrnshotPreview::GetRequestedWidth(int Height) // calculate requested window width by given height 853 { 854 switch (ScrnshotPrevStauts) 855 { 856 case SCRNSHOT_PREV_EMPTY: 857 return 0; 858 case SCRNSHOT_PREV_LOADING: 859 return 200; 860 case SCRNSHOT_PREV_IMAGE: 861 if (pImage) 862 { 863 // return the width needed to display image inside the window. 864 // and always keep window w/h ratio inside [ 1/SCRNSHOT_MAX_ASPECT_RAT, SCRNSHOT_MAX_ASPECT_RAT ] 865 return (int)floor((float)Height * 866 max(min((float)pImage->GetWidth() / (float)pImage->GetHeight(), (float)SCRNSHOT_MAX_ASPECT_RAT), 1.0 / (float)SCRNSHOT_MAX_ASPECT_RAT)); 867 } 868 return 0; 869 case SCRNSHOT_PREV_FAILED: 870 return 200; 871 default: 872 return 0; 873 } 874 } 875 876 CAppScrnshotPreview::~CAppScrnshotPreview() 877 { 878 PreviousDisplayCleanup(); 879 } 880 // **** CAppScrnshotPreview **** 881 882 883 // **** CAppInfoDisplay **** 884 885 BOOL CAppInfoDisplay::ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId) 886 { 887 theResult = 0; 888 switch (message) 889 { 890 case WM_CREATE: 891 { 892 RichEdit = new CAppRichEdit(); 893 RichEdit->Create(hwnd); 894 895 ScrnshotPrev = new CAppScrnshotPreview(); 896 ScrnshotPrev->Create(hwnd); 897 break; 898 } 899 case WM_SIZE: 900 { 901 ResizeChildren(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); 902 break; 903 } 904 case WM_RAPPS_RESIZE_CHILDREN: 905 { 906 ResizeChildren(); 907 break; 908 } 909 case WM_COMMAND: 910 { 911 OnCommand(wParam, lParam); 912 break; 913 } 914 case WM_NOTIFY: 915 { 916 NMHDR *NotifyHeader = (NMHDR *)lParam; 917 if (NotifyHeader->hwndFrom == RichEdit->m_hWnd) 918 { 919 switch (NotifyHeader->code) 920 { 921 case EN_LINK: 922 OnLink((ENLINK *)lParam); 923 break; 924 } 925 } 926 break; 927 } 928 } 929 930 return FALSE; 931 } 932 933 VOID CAppInfoDisplay::ResizeChildren() 934 { 935 CRect rect; 936 GetWindowRect(&rect); 937 ResizeChildren(rect.Width(), rect.Height()); 938 } 939 940 VOID CAppInfoDisplay::ResizeChildren(int Width, int Height) 941 { 942 int ScrnshotWidth = ScrnshotPrev->GetRequestedWidth(Height); 943 944 // make sure richedit always have room to display 945 ScrnshotWidth = min(ScrnshotWidth, Width - INFO_DISPLAY_PADDING - RICHEDIT_MIN_WIDTH); 946 947 DWORD dwError = ERROR_SUCCESS; 948 HDWP hDwp = BeginDeferWindowPos(2); 949 950 if (hDwp) 951 { 952 hDwp = ::DeferWindowPos(hDwp, ScrnshotPrev->m_hWnd, NULL, 953 0, 0, ScrnshotWidth, Height, 0); 954 955 if (hDwp) 956 { 957 // hide the padding if scrnshot window width == 0 958 int RicheditPosX = ScrnshotWidth ? (ScrnshotWidth + INFO_DISPLAY_PADDING) : 0; 959 960 hDwp = ::DeferWindowPos(hDwp, RichEdit->m_hWnd, NULL, 961 RicheditPosX, 0, Width - RicheditPosX, Height, 0); 962 963 if (hDwp) 964 { 965 EndDeferWindowPos(hDwp); 966 } 967 else 968 { 969 dwError = GetLastError(); 970 } 971 } 972 else 973 { 974 dwError = GetLastError(); 975 } 976 } 977 else 978 { 979 dwError = GetLastError(); 980 } 981 982 983 #if DBG 984 ATLASSERT(dwError == ERROR_SUCCESS); 985 #endif 986 987 UpdateWindow(); 988 } 989 990 VOID CAppInfoDisplay::OnLink(ENLINK *Link) 991 { 992 switch (Link->msg) 993 { 994 case WM_LBUTTONUP: 995 case WM_RBUTTONUP: 996 { 997 if (pLink) HeapFree(GetProcessHeap(), 0, pLink); 998 999 pLink = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, 1000 (max(Link->chrg.cpMin, Link->chrg.cpMax) - 1001 min(Link->chrg.cpMin, Link->chrg.cpMax) + 1) * sizeof(WCHAR)); 1002 if (!pLink) 1003 { 1004 /* TODO: Error message */ 1005 return; 1006 } 1007 1008 RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax); 1009 RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM)pLink); 1010 1011 ShowPopupMenuEx(m_hWnd, m_hWnd, IDR_LINKMENU, -1); 1012 } 1013 break; 1014 } 1015 } 1016 1017 ATL::CWndClassInfo &CAppInfoDisplay::GetWndClassInfo() 1018 { 1019 DWORD csStyle = CS_VREDRAW | CS_HREDRAW; 1020 static ATL::CWndClassInfo wc = 1021 { 1022 { 1023 sizeof(WNDCLASSEX), 1024 csStyle, 1025 StartWindowProc, 1026 0, 1027 0, 1028 NULL, 1029 NULL, 1030 NULL, 1031 (HBRUSH)(COLOR_BTNFACE + 1), 1032 NULL, 1033 L"RAppsAppInfo", 1034 NULL 1035 }, 1036 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 1037 }; 1038 return wc; 1039 } 1040 1041 HWND CAppInfoDisplay::Create(HWND hwndParent) 1042 { 1043 RECT r = { 0,0,0,0 }; 1044 1045 return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); 1046 } 1047 1048 BOOL CAppInfoDisplay::ShowAvailableAppInfo(CAvailableApplicationInfo *Info) 1049 { 1050 ATL::CStringW ScrnshotLocation; 1051 if (Info->RetrieveScrnshot(0, ScrnshotLocation)) 1052 { 1053 ScrnshotPrev->DisplayImage(ScrnshotLocation); 1054 } 1055 else 1056 { 1057 ScrnshotPrev->DisplayEmpty(); 1058 } 1059 ResizeChildren(); 1060 return RichEdit->ShowAvailableAppInfo(Info); 1061 } 1062 1063 BOOL CAppInfoDisplay::ShowInstalledAppInfo(CInstalledApplicationInfo *Info) 1064 { 1065 ScrnshotPrev->DisplayEmpty(); 1066 ResizeChildren(); 1067 return RichEdit->ShowInstalledAppInfo(Info); 1068 } 1069 1070 VOID CAppInfoDisplay::SetWelcomeText() 1071 { 1072 ScrnshotPrev->DisplayEmpty(); 1073 ResizeChildren(); 1074 RichEdit->SetWelcomeText(); 1075 } 1076 1077 VOID CAppInfoDisplay::OnCommand(WPARAM wParam, LPARAM lParam) 1078 { 1079 WORD wCommand = LOWORD(wParam); 1080 1081 switch (wCommand) 1082 { 1083 case ID_OPEN_LINK: 1084 1085 ShellExecuteW(m_hWnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE); 1086 HeapFree(GetProcessHeap(), 0, pLink); 1087 pLink = NULL; 1088 break; 1089 1090 case ID_COPY_LINK: 1091 CopyTextToClipboard(pLink); 1092 HeapFree(GetProcessHeap(), 0, pLink); 1093 pLink = NULL; 1094 break; 1095 1096 } 1097 } 1098 1099 CAppInfoDisplay::~CAppInfoDisplay() 1100 { 1101 delete RichEdit; 1102 delete ScrnshotPrev; 1103 } 1104 // **** CAppInfoDisplay **** 1105 1106 1107 // **** CAppsListView **** 1108 1109 CAppsListView::CAppsListView() : 1110 bHasCheckboxes(FALSE), 1111 nLastHeaderID(-1) 1112 { 1113 } 1114 1115 VOID CAppsListView::SetCheckboxesVisible(BOOL bIsVisible) 1116 { 1117 if (bIsVisible) 1118 { 1119 SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT); 1120 } 1121 else 1122 { 1123 SetExtendedListViewStyle(LVS_EX_FULLROWSELECT); 1124 } 1125 1126 bHasCheckboxes = bIsVisible; 1127 } 1128 1129 VOID CAppsListView::ColumnClick(LPNMLISTVIEW pnmv) 1130 { 1131 HWND hHeader; 1132 HDITEMW hColumn; 1133 INT nHeaderID = pnmv->iSubItem; 1134 1135 if ((GetWindowLongPtr(GWL_STYLE) & ~LVS_NOSORTHEADER) == 0) 1136 return; 1137 1138 hHeader = (HWND)SendMessage(LVM_GETHEADER, 0, 0); 1139 ZeroMemory(&hColumn, sizeof(hColumn)); 1140 1141 /* If the sorting column changed, remove the sorting style from the old column */ 1142 if ((nLastHeaderID != -1) && (nLastHeaderID != nHeaderID)) 1143 { 1144 bIsAscending = TRUE; // also reset sorting method to ascending 1145 hColumn.mask = HDI_FORMAT; 1146 Header_GetItem(hHeader, nLastHeaderID, &hColumn); 1147 hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN); 1148 Header_SetItem(hHeader, nLastHeaderID, &hColumn); 1149 } 1150 1151 /* Set the sorting style to the new column */ 1152 hColumn.mask = HDI_FORMAT; 1153 Header_GetItem(hHeader, nHeaderID, &hColumn); 1154 1155 hColumn.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP); 1156 hColumn.fmt |= (bIsAscending ? HDF_SORTUP : HDF_SORTDOWN); 1157 Header_SetItem(hHeader, nHeaderID, &hColumn); 1158 1159 /* Sort the list, using the current values of nHeaderID and bIsAscending */ 1160 SortContext ctx = { this, nHeaderID }; 1161 SortItems(s_CompareFunc, &ctx); 1162 1163 /* Save new values */ 1164 nLastHeaderID = nHeaderID; 1165 bIsAscending = !bIsAscending; 1166 } 1167 1168 BOOL CAppsListView::AddColumn(INT Index, ATL::CStringW &Text, INT Width, INT Format) 1169 { 1170 return AddColumn(Index, const_cast<LPWSTR>(Text.GetString()), Width, Format); 1171 } 1172 1173 int CAppsListView::AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format) 1174 { 1175 LVCOLUMNW Column; 1176 1177 ZeroMemory(&Column, sizeof(Column)); 1178 1179 Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM; 1180 Column.iSubItem = Index; 1181 Column.pszText = lpText; 1182 Column.cx = Width; 1183 Column.fmt = Format; 1184 1185 return SendMessage(LVM_INSERTCOLUMN, Index, (LPARAM)(&Column)); 1186 } 1187 1188 void CAppsListView::DeleteColumn(INT Index) 1189 { 1190 SendMessage(LVM_DELETECOLUMN, Index, 0); 1191 return; 1192 } 1193 1194 INT CAppsListView::AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam) 1195 { 1196 LVITEMW Item; 1197 1198 ZeroMemory(&Item, sizeof(Item)); 1199 1200 Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE; 1201 Item.pszText = const_cast<LPWSTR>(lpText); 1202 Item.lParam = lParam; 1203 Item.iItem = ItemIndex; 1204 Item.iImage = IconIndex; 1205 1206 if (IconIndex >= 0) 1207 { 1208 Item.iImage = IconIndex; 1209 Item.mask |= LVIF_IMAGE; 1210 } 1211 return InsertItem(&Item); 1212 } 1213 1214 HIMAGELIST CAppsListView::GetImageList(int iImageList) 1215 { 1216 return (HIMAGELIST)SendMessage(LVM_GETIMAGELIST, iImageList, 0); 1217 } 1218 1219 INT CALLBACK CAppsListView::s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 1220 { 1221 SortContext *ctx = ((SortContext *)lParamSort); 1222 return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem); 1223 } 1224 1225 INT CAppsListView::CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem) 1226 { 1227 ATL::CStringW Item1, Item2; 1228 LVFINDINFOW IndexInfo; 1229 INT Index; 1230 1231 IndexInfo.flags = LVFI_PARAM; 1232 1233 IndexInfo.lParam = lParam1; 1234 Index = FindItem(-1, &IndexInfo); 1235 GetItemText(Index, iSubItem, Item1.GetBuffer(MAX_STR_LEN), MAX_STR_LEN); 1236 Item1.ReleaseBuffer(); 1237 1238 IndexInfo.lParam = lParam2; 1239 Index = FindItem(-1, &IndexInfo); 1240 GetItemText(Index, iSubItem, Item2.GetBuffer(MAX_STR_LEN), MAX_STR_LEN); 1241 Item2.ReleaseBuffer(); 1242 1243 return bIsAscending ? Item1.Compare(Item2) : Item2.Compare(Item1); 1244 } 1245 1246 HWND CAppsListView::Create(HWND hwndParent) 1247 { 1248 RECT r = { 205, 28, 465, 250 }; 1249 DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE; 1250 1251 HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE); 1252 1253 if (hwnd) 1254 { 1255 SetCheckboxesVisible(FALSE); 1256 } 1257 1258 m_hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE, 1259 LISTVIEW_ICON_SIZE, 1260 GetSystemColorDepth() | ILC_MASK, 1261 0, 1); 1262 1263 // currently, this two Imagelist is the same one. 1264 SetImageList(m_hImageListView, LVSIL_SMALL); 1265 SetImageList(m_hImageListView, LVSIL_NORMAL); 1266 1267 return hwnd; 1268 } 1269 1270 BOOL CAppsListView::GetCheckState(INT item) 1271 { 1272 return (BOOL)(GetItemState(item, LVIS_STATEIMAGEMASK) >> 12) - 1; 1273 } 1274 1275 VOID CAppsListView::SetCheckState(INT item, BOOL fCheck) 1276 { 1277 if (bHasCheckboxes) 1278 { 1279 SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK); 1280 } 1281 } 1282 1283 VOID CAppsListView::CheckAll() 1284 { 1285 if (bHasCheckboxes) 1286 { 1287 if (CheckedItemCount == ItemCount) 1288 { 1289 // clear all 1290 SetCheckState(-1, FALSE); 1291 } 1292 else 1293 { 1294 // check all 1295 SetCheckState(-1, TRUE); 1296 } 1297 } 1298 } 1299 1300 PVOID CAppsListView::GetFocusedItemData() 1301 { 1302 INT item = GetSelectionMark(); 1303 if (item == -1) 1304 { 1305 return (PVOID)0; 1306 } 1307 return (PVOID)GetItemData(item); 1308 } 1309 1310 BOOL CAppsListView::SetDisplayAppType(APPLICATION_VIEW_TYPE AppType) 1311 { 1312 if (!DeleteAllItems()) return FALSE; 1313 ApplicationViewType = AppType; 1314 1315 bIsAscending = TRUE; 1316 1317 ItemCount = 0; 1318 CheckedItemCount = 0; 1319 1320 // delete old columns 1321 while (ColumnCount) 1322 { 1323 DeleteColumn(--ColumnCount); 1324 } 1325 1326 ImageList_RemoveAll(m_hImageListView); 1327 1328 // add new columns 1329 ATL::CStringW szText; 1330 switch (AppType) 1331 { 1332 case AppViewTypeInstalledApps: 1333 1334 /* Add columns to ListView */ 1335 szText.LoadStringW(IDS_APP_NAME); 1336 AddColumn(ColumnCount++, szText, 250, LVCFMT_LEFT); 1337 1338 szText.LoadStringW(IDS_APP_INST_VERSION); 1339 AddColumn(ColumnCount++, szText, 90, LVCFMT_RIGHT); 1340 1341 szText.LoadStringW(IDS_APP_DESCRIPTION); 1342 AddColumn(ColumnCount++, szText, 300, LVCFMT_LEFT); 1343 1344 // disable checkboxes 1345 SetCheckboxesVisible(FALSE); 1346 break; 1347 1348 case AppViewTypeAvailableApps: 1349 1350 /* Add columns to ListView */ 1351 szText.LoadStringW(IDS_APP_NAME); 1352 AddColumn(ColumnCount++, szText, 250, LVCFMT_LEFT); 1353 1354 szText.LoadStringW(IDS_APP_INST_VERSION); 1355 AddColumn(ColumnCount++, szText, 90, LVCFMT_RIGHT); 1356 1357 szText.LoadStringW(IDS_APP_DESCRIPTION); 1358 AddColumn(ColumnCount++, szText, 300, LVCFMT_LEFT); 1359 1360 // enable checkboxes 1361 SetCheckboxesVisible(TRUE); 1362 break; 1363 1364 case AppViewTypeEmpty: 1365 default: 1366 break; 1367 } 1368 1369 1370 return TRUE; 1371 } 1372 1373 BOOL CAppsListView::SetViewMode(DWORD ViewMode) 1374 { 1375 return SendMessage(LVM_SETVIEW, (WPARAM)ViewMode, 0) == 1; 1376 } 1377 1378 BOOL CAppsListView::AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID CallbackParam) 1379 { 1380 if (ApplicationViewType != AppViewTypeInstalledApps) 1381 { 1382 return FALSE; 1383 } 1384 1385 HICON hIcon = (HICON)LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN)); 1386 1387 int IconIndex = ImageList_AddIcon(m_hImageListView, hIcon); 1388 DestroyIcon(hIcon); 1389 1390 int Index = AddItem(ItemCount, IconIndex, InstAppInfo->szDisplayName, (LPARAM)CallbackParam); 1391 SetItemText(Index, 1, InstAppInfo->szDisplayVersion.IsEmpty() ? L"---" : InstAppInfo->szDisplayVersion); 1392 SetItemText(Index, 2, InstAppInfo->szComments.IsEmpty() ? L"---" : InstAppInfo->szComments); 1393 1394 ItemCount++; 1395 return TRUE; 1396 } 1397 1398 BOOL CAppsListView::AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID CallbackParam) 1399 { 1400 if (ApplicationViewType != AppViewTypeAvailableApps) 1401 { 1402 return FALSE; 1403 } 1404 1405 /* Load icon from file */ 1406 HICON hIcon = NULL; 1407 ATL::CStringW szIconPath; 1408 if (AvlbAppInfo->RetrieveIcon(szIconPath)) 1409 { 1410 hIcon = (HICON)LoadImageW(NULL, 1411 szIconPath.GetString(), 1412 IMAGE_ICON, 1413 LISTVIEW_ICON_SIZE, 1414 LISTVIEW_ICON_SIZE, 1415 LR_LOADFROMFILE); 1416 } 1417 1418 if (!hIcon || GetLastError() != ERROR_SUCCESS) 1419 { 1420 /* Load default icon */ 1421 hIcon = (HICON)LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN)); 1422 } 1423 1424 int IconIndex = ImageList_AddIcon(m_hImageListView, hIcon); 1425 DestroyIcon(hIcon); 1426 1427 int Index = AddItem(ItemCount, IconIndex, AvlbAppInfo->m_szName, (LPARAM)CallbackParam); 1428 1429 if (InitCheckState) 1430 { 1431 SetCheckState(Index, TRUE); 1432 } 1433 1434 SetItemText(Index, 1, AvlbAppInfo->m_szVersion); 1435 SetItemText(Index, 2, AvlbAppInfo->m_szDesc); 1436 1437 ItemCount++; 1438 return TRUE; 1439 } 1440 1441 // this function is called when parent window receiving an notification about checkstate changing 1442 VOID CAppsListView::ItemCheckStateNotify(int iItem, BOOL bCheck) 1443 { 1444 if (bCheck) 1445 { 1446 CheckedItemCount++; 1447 } 1448 else 1449 { 1450 CheckedItemCount--; 1451 } 1452 } 1453 // **** CAppsListView **** 1454 1455 1456 // **** CApplicationView **** 1457 1458 BOOL CApplicationView::ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId) 1459 { 1460 theResult = 0; 1461 switch (message) 1462 { 1463 case WM_CREATE: 1464 { 1465 BOOL bSuccess = TRUE; 1466 m_Panel = new CUiPanel(); 1467 m_Panel->m_VerticalAlignment = UiAlign_Stretch; 1468 m_Panel->m_HorizontalAlignment = UiAlign_Stretch; 1469 1470 bSuccess &= CreateToolbar(); 1471 bSuccess &= CreateSearchBar(); 1472 bSuccess &= CreateComboBox(); 1473 bSuccess &= CreateHSplitter(); 1474 bSuccess &= CreateListView(); 1475 bSuccess &= CreateAppInfoDisplay(); 1476 1477 m_Toolbar->AutoSize(); 1478 1479 RECT rTop; 1480 1481 ::GetWindowRect(m_Toolbar->m_hWnd, &rTop); 1482 m_HSplitter->m_Margin.top = rTop.bottom - rTop.top; 1483 if (!bSuccess) 1484 { 1485 return -1; // creation failure 1486 } 1487 } 1488 break; 1489 1490 case WM_NOTIFY: 1491 { 1492 LPNMHDR pNotifyHeader = (LPNMHDR)lParam; 1493 if (pNotifyHeader->hwndFrom == m_ListView->GetWindow()) 1494 { 1495 switch (pNotifyHeader->code) 1496 { 1497 case LVN_ITEMCHANGED: 1498 { 1499 LPNMLISTVIEW pnic = (LPNMLISTVIEW)lParam; 1500 1501 /* Check if this is a valid item 1502 * (technically, it can be also an unselect) */ 1503 INT ItemIndex = pnic->iItem; 1504 if (ItemIndex == -1 || 1505 ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom)) 1506 { 1507 break; 1508 } 1509 1510 /* Check if the focus has been moved to another item */ 1511 if ((pnic->uChanged & LVIF_STATE) && 1512 (pnic->uNewState & LVIS_FOCUSED) && 1513 !(pnic->uOldState & LVIS_FOCUSED)) 1514 { 1515 ItemGetFocus((LPVOID)pnic->lParam); 1516 } 1517 1518 /* Check if the item is checked/unchecked */ 1519 if (pnic->uChanged & LVIF_STATE) 1520 { 1521 int iOldState = STATEIMAGETOINDEX(pnic->uOldState); 1522 int iNewState = STATEIMAGETOINDEX(pnic->uNewState); 1523 1524 if (iOldState == STATEIMAGE_UNCHECKED && iNewState == STATEIMAGE_CHECKED) 1525 { 1526 // this item is just checked 1527 m_ListView->ItemCheckStateNotify(pnic->iItem, TRUE); 1528 ItemCheckStateChanged(TRUE, (LPVOID)pnic->lParam); 1529 } 1530 else if (iOldState == STATEIMAGE_CHECKED && iNewState == STATEIMAGE_UNCHECKED) 1531 { 1532 // this item is just unchecked 1533 m_ListView->ItemCheckStateNotify(pnic->iItem, FALSE); 1534 ItemCheckStateChanged(FALSE, (LPVOID)pnic->lParam); 1535 } 1536 } 1537 } 1538 break; 1539 1540 case LVN_COLUMNCLICK: 1541 { 1542 LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam; 1543 1544 m_ListView->ColumnClick(pnmv); 1545 } 1546 break; 1547 1548 case NM_DBLCLK: 1549 { 1550 LPNMITEMACTIVATE Item = (LPNMITEMACTIVATE)lParam; 1551 if (Item->iItem != -1) 1552 { 1553 /* this won't do anything if the program is already installed */ 1554 1555 if (ApplicationViewType == AppViewTypeAvailableApps) 1556 { 1557 m_MainWindow->InstallApplication((CAvailableApplicationInfo *)m_ListView->GetItemData(Item->iItem)); 1558 } 1559 } 1560 } 1561 break; 1562 1563 case NM_RCLICK: 1564 { 1565 if (((LPNMLISTVIEW)lParam)->iItem != -1) 1566 { 1567 ShowPopupMenuEx(m_hWnd, m_hWnd, 0, ID_INSTALL); 1568 } 1569 } 1570 break; 1571 } 1572 } 1573 else if (pNotifyHeader->hwndFrom == m_Toolbar->GetWindow()) 1574 { 1575 switch (pNotifyHeader->code) 1576 { 1577 case TTN_GETDISPINFO: 1578 m_Toolbar->OnGetDispInfo((LPTOOLTIPTEXT)lParam); 1579 break; 1580 } 1581 } 1582 } 1583 break; 1584 1585 case WM_SYSCOLORCHANGE: 1586 { 1587 /* Forward WM_SYSCOLORCHANGE to common controls */ 1588 m_ListView->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam); 1589 m_ListView->SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE)); 1590 m_Toolbar->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam); 1591 m_ComboBox->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam); 1592 } 1593 break; 1594 1595 case WM_SIZE: 1596 { 1597 OnSize(hwnd, wParam, lParam); 1598 break; 1599 } 1600 1601 case WM_COMMAND: 1602 { 1603 OnCommand(wParam, lParam); 1604 } 1605 break; 1606 } 1607 return FALSE; 1608 } 1609 1610 BOOL CApplicationView::CreateToolbar() 1611 { 1612 m_Toolbar = new CMainToolbar(); 1613 m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop; 1614 m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch; 1615 m_Panel->Children().Append(m_Toolbar); 1616 1617 return m_Toolbar->Create(m_hWnd) != NULL; 1618 } 1619 1620 BOOL CApplicationView::CreateSearchBar() 1621 { 1622 m_SearchBar = new CUiWindow<CSearchBar>(); 1623 m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop; 1624 m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm; 1625 m_SearchBar->m_Margin.top = 4; 1626 m_SearchBar->m_Margin.right = TOOLBAR_PADDING; 1627 1628 return m_SearchBar->Create(m_Toolbar->m_hWnd) != NULL; 1629 } 1630 1631 BOOL CApplicationView::CreateComboBox() 1632 { 1633 m_ComboBox = new CUiWindow<CComboBox>(); 1634 m_ComboBox->m_VerticalAlignment = UiAlign_LeftTop; 1635 m_ComboBox->m_HorizontalAlignment = UiAlign_RightBtm; 1636 m_ComboBox->m_Margin.top = 4; 1637 1638 return m_ComboBox->Create(m_Toolbar->m_hWnd) != NULL; 1639 } 1640 1641 BOOL CApplicationView::CreateHSplitter() 1642 { 1643 m_HSplitter = new CUiSplitPanel(); 1644 m_HSplitter->m_VerticalAlignment = UiAlign_Stretch; 1645 m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch; 1646 m_HSplitter->m_DynamicFirst = TRUE; 1647 m_HSplitter->m_Horizontal = TRUE; 1648 m_HSplitter->m_Pos = INT_MAX; //set INT_MAX to use lowest possible position (m_MinSecond) 1649 m_HSplitter->m_MinFirst = 10; 1650 m_HSplitter->m_MinSecond = 140; 1651 m_Panel->Children().Append(m_HSplitter); 1652 1653 return m_HSplitter->Create(m_hWnd) != NULL; 1654 } 1655 1656 BOOL CApplicationView::CreateListView() 1657 { 1658 m_ListView = new CAppsListView(); 1659 m_ListView->m_VerticalAlignment = UiAlign_Stretch; 1660 m_ListView->m_HorizontalAlignment = UiAlign_Stretch; 1661 m_HSplitter->First().Append(m_ListView); 1662 1663 return m_ListView->Create(m_hWnd) != NULL; 1664 } 1665 1666 BOOL CApplicationView::CreateAppInfoDisplay() 1667 { 1668 m_AppsInfo = new CAppInfoDisplay(); 1669 m_AppsInfo->m_VerticalAlignment = UiAlign_Stretch; 1670 m_AppsInfo->m_HorizontalAlignment = UiAlign_Stretch; 1671 m_HSplitter->Second().Append(m_AppsInfo); 1672 1673 return m_AppsInfo->Create(m_hWnd) != NULL; 1674 } 1675 1676 VOID CApplicationView::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam) 1677 { 1678 if (wParam == SIZE_MINIMIZED) 1679 return; 1680 1681 /* Size tool bar */ 1682 m_Toolbar->AutoSize(); 1683 1684 /* Automatically hide captions */ 1685 DWORD dToolbarTreshold = m_Toolbar->GetMaxButtonsWidth(); 1686 DWORD dSearchbarMargin = (LOWORD(lParam) - m_SearchBar->m_Width - m_ComboBox->m_Width - TOOLBAR_PADDING * 2); 1687 1688 if (dSearchbarMargin > dToolbarTreshold) 1689 { 1690 m_Toolbar->ShowButtonCaption(); 1691 } 1692 else if (dSearchbarMargin < dToolbarTreshold) 1693 { 1694 m_Toolbar->HideButtonCaption(); 1695 1696 } 1697 1698 RECT r = { 0, 0, LOWORD(lParam), HIWORD(lParam) }; 1699 HDWP hdwp = NULL; 1700 INT count = m_Panel->CountSizableChildren(); 1701 1702 hdwp = BeginDeferWindowPos(count); 1703 if (hdwp) 1704 { 1705 hdwp = m_Panel->OnParentSize(r, hdwp); 1706 if (hdwp) 1707 { 1708 EndDeferWindowPos(hdwp); 1709 } 1710 } 1711 1712 count = m_SearchBar->CountSizableChildren(); 1713 hdwp = BeginDeferWindowPos(count); 1714 if (hdwp) 1715 { 1716 hdwp = m_SearchBar->OnParentSize(r, hdwp); 1717 if (hdwp) 1718 { 1719 EndDeferWindowPos(hdwp); 1720 } 1721 } 1722 1723 m_ComboBox->m_Margin.right = m_SearchBar->m_Width + m_SearchBar->m_Margin.right + TOOLBAR_PADDING; 1724 count = m_ComboBox->CountSizableChildren(); 1725 hdwp = BeginDeferWindowPos(count); 1726 if (hdwp) 1727 { 1728 hdwp = m_ComboBox->OnParentSize(r, hdwp); 1729 if (hdwp) 1730 { 1731 EndDeferWindowPos(hdwp); 1732 } 1733 } 1734 } 1735 1736 VOID CApplicationView::OnCommand(WPARAM wParam, LPARAM lParam) 1737 { 1738 if (lParam) 1739 { 1740 if ((HWND)lParam == m_SearchBar->GetWindow()) 1741 { 1742 ATL::CStringW szBuf; 1743 switch (HIWORD(wParam)) 1744 { 1745 case EN_SETFOCUS: 1746 { 1747 ATL::CStringW szWndText; 1748 1749 szBuf.LoadStringW(IDS_SEARCH_TEXT); 1750 m_SearchBar->GetWindowTextW(szWndText); 1751 if (szBuf == szWndText) 1752 { 1753 m_SearchBar->SetWindowTextW(L""); 1754 } 1755 } 1756 break; 1757 1758 case EN_KILLFOCUS: 1759 { 1760 m_SearchBar->GetWindowTextW(szBuf); 1761 if (szBuf.IsEmpty()) 1762 { 1763 szBuf.LoadStringW(IDS_SEARCH_TEXT); 1764 m_SearchBar->SetWindowTextW(szBuf.GetString()); 1765 } 1766 } 1767 break; 1768 1769 case EN_CHANGE: 1770 { 1771 ATL::CStringW szWndText; 1772 1773 szBuf.LoadStringW(IDS_SEARCH_TEXT); 1774 m_SearchBar->GetWindowTextW(szWndText); 1775 if (szBuf == szWndText) 1776 { 1777 szWndText = L""; 1778 m_MainWindow->SearchTextChanged(szWndText); 1779 } 1780 else 1781 { 1782 m_MainWindow->SearchTextChanged(szWndText); 1783 } 1784 } 1785 break; 1786 } 1787 1788 return; 1789 } 1790 else if ((HWND)lParam == m_ComboBox->GetWindow()) 1791 { 1792 int NotifyCode = HIWORD(wParam); 1793 switch (NotifyCode) 1794 { 1795 case CBN_SELCHANGE: 1796 int CurrSelection = m_ComboBox->SendMessageW(CB_GETCURSEL); 1797 1798 int ViewModeList[] = { LV_VIEW_DETAILS, LV_VIEW_LIST, LV_VIEW_TILE }; 1799 ATLASSERT(CurrSelection < (int)_countof(ViewModeList)); 1800 if (!m_ListView->SetViewMode(ViewModeList[CurrSelection])) 1801 { 1802 MessageBoxW(L"View mode invalid or unimplemented"); 1803 } 1804 break; 1805 } 1806 1807 return; 1808 } 1809 else if ((HWND)lParam == m_Toolbar->GetWindow()) 1810 { 1811 // the message is sent from Toolbar. fall down to continue process 1812 } 1813 else 1814 { 1815 return; 1816 } 1817 } 1818 1819 // the LOWORD of wParam contains a Menu or Control ID 1820 WORD wCommand = LOWORD(wParam); 1821 1822 switch (wCommand) 1823 { 1824 case ID_INSTALL: 1825 m_MainWindow->InstallApplication((CAvailableApplicationInfo *)GetFocusedItemData()); 1826 break; 1827 1828 case ID_TOOLBAR_INSTALL: 1829 m_MainWindow->SendMessageW(WM_COMMAND, ID_INSTALL, 0); 1830 break; 1831 1832 case ID_UNINSTALL: 1833 m_MainWindow->SendMessageW(WM_COMMAND, ID_UNINSTALL, 0); 1834 break; 1835 1836 case ID_MODIFY: 1837 m_MainWindow->SendMessageW(WM_COMMAND, ID_MODIFY, 0); 1838 break; 1839 1840 case ID_REGREMOVE: 1841 m_MainWindow->SendMessageW(WM_COMMAND, ID_REGREMOVE, 0); 1842 break; 1843 1844 case ID_REFRESH: 1845 m_MainWindow->SendMessageW(WM_COMMAND, ID_REFRESH, 0); 1846 break; 1847 1848 case ID_RESETDB: 1849 m_MainWindow->SendMessageW(WM_COMMAND, ID_RESETDB, 0); 1850 break; 1851 } 1852 } 1853 1854 CApplicationView::CApplicationView(CMainWindow *MainWindow) 1855 : m_MainWindow(MainWindow) 1856 { 1857 } 1858 1859 CApplicationView::~CApplicationView() 1860 { 1861 delete m_Toolbar; 1862 delete m_SearchBar; 1863 delete m_ListView; 1864 delete m_AppsInfo; 1865 delete m_HSplitter; 1866 } 1867 1868 ATL::CWndClassInfo &CApplicationView::GetWndClassInfo() 1869 { 1870 DWORD csStyle = CS_VREDRAW | CS_HREDRAW; 1871 static ATL::CWndClassInfo wc = 1872 { 1873 { 1874 sizeof(WNDCLASSEX), 1875 csStyle, 1876 StartWindowProc, 1877 0, 1878 0, 1879 NULL, 1880 NULL, 1881 NULL, 1882 (HBRUSH)(COLOR_BTNFACE + 1), 1883 NULL, 1884 L"RAppsApplicationView", 1885 NULL 1886 }, 1887 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 1888 }; 1889 return wc; 1890 } 1891 1892 HWND CApplicationView::Create(HWND hwndParent) 1893 { 1894 RECT r = { 0,0,0,0 }; 1895 1896 HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0); 1897 1898 return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, menu); 1899 } 1900 1901 BOOL CApplicationView::SetDisplayAppType(APPLICATION_VIEW_TYPE AppType) 1902 { 1903 if (!m_ListView->SetDisplayAppType(AppType)) 1904 { 1905 return FALSE; 1906 } 1907 ApplicationViewType = AppType; 1908 m_AppsInfo->SetWelcomeText(); 1909 1910 HMENU hMenu = ::GetMenu(m_hWnd); 1911 switch (AppType) 1912 { 1913 case AppViewTypeEmpty: 1914 default: 1915 EnableMenuItem(hMenu, ID_REGREMOVE, MF_GRAYED); 1916 EnableMenuItem(hMenu, ID_INSTALL, MF_GRAYED); 1917 EnableMenuItem(hMenu, ID_UNINSTALL, MF_GRAYED); 1918 EnableMenuItem(hMenu, ID_MODIFY, MF_GRAYED); 1919 1920 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE); 1921 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE); 1922 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE); 1923 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE); 1924 break; 1925 1926 case AppViewTypeInstalledApps: 1927 EnableMenuItem(hMenu, ID_REGREMOVE, MF_ENABLED); 1928 EnableMenuItem(hMenu, ID_INSTALL, MF_GRAYED); 1929 EnableMenuItem(hMenu, ID_UNINSTALL, MF_ENABLED); 1930 EnableMenuItem(hMenu, ID_MODIFY, MF_ENABLED); 1931 1932 // TODO: instead of disable these button, I would rather remove them. 1933 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE); 1934 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE); 1935 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE); 1936 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE); 1937 break; 1938 1939 case AppViewTypeAvailableApps: 1940 EnableMenuItem(hMenu, ID_REGREMOVE, MF_GRAYED); 1941 EnableMenuItem(hMenu, ID_INSTALL, MF_ENABLED); 1942 EnableMenuItem(hMenu, ID_UNINSTALL, MF_GRAYED); 1943 EnableMenuItem(hMenu, ID_MODIFY, MF_GRAYED); 1944 1945 // TODO: instead of disable these button, I would rather remove them. 1946 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE); 1947 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, TRUE); 1948 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE); 1949 m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, FALSE); 1950 break; 1951 } 1952 return TRUE; 1953 } 1954 1955 BOOL CApplicationView::AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID param) 1956 { 1957 if (ApplicationViewType != AppViewTypeInstalledApps) 1958 { 1959 return FALSE; 1960 } 1961 return m_ListView->AddInstalledApplication(InstAppInfo, param); 1962 } 1963 1964 BOOL CApplicationView::AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID param) 1965 { 1966 if (ApplicationViewType != AppViewTypeAvailableApps) 1967 { 1968 return FALSE; 1969 } 1970 return m_ListView->AddAvailableApplication(AvlbAppInfo, InitCheckState, param); 1971 } 1972 1973 void CApplicationView::CheckAll() 1974 { 1975 m_ListView->CheckAll(); 1976 return; 1977 } 1978 1979 PVOID CApplicationView::GetFocusedItemData() 1980 { 1981 return m_ListView->GetFocusedItemData(); 1982 } 1983 1984 int CApplicationView::GetItemCount() 1985 { 1986 return m_ListView->GetItemCount(); 1987 } 1988 1989 VOID CApplicationView::AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList) 1990 { 1991 m_Toolbar->AppendTabOrderWindow(Direction, TabOrderList); 1992 m_ComboBox->AppendTabOrderWindow(Direction, TabOrderList); 1993 m_SearchBar->AppendTabOrderWindow(Direction, TabOrderList); 1994 m_ListView->AppendTabOrderWindow(Direction, TabOrderList); 1995 m_AppsInfo->AppendTabOrderWindow(Direction, TabOrderList); 1996 1997 return; 1998 } 1999 2000 // this function is called when a item of listview get focus. 2001 // CallbackParam is the param passed to listview when adding the item (the one getting focus now). 2002 BOOL CApplicationView::ItemGetFocus(LPVOID CallbackParam) 2003 { 2004 switch (ApplicationViewType) 2005 { 2006 case AppViewTypeInstalledApps: 2007 return m_AppsInfo->ShowInstalledAppInfo((CInstalledApplicationInfo *)CallbackParam); 2008 2009 case AppViewTypeAvailableApps: 2010 return m_AppsInfo->ShowAvailableAppInfo((CAvailableApplicationInfo *)CallbackParam); 2011 2012 case AppViewTypeEmpty: 2013 default: 2014 m_AppsInfo->SetWelcomeText(); 2015 return FALSE; 2016 } 2017 } 2018 2019 // this function is called when a item of listview is checked/unchecked 2020 // CallbackParam is the param passed to listview when adding the item (the one getting focus now). 2021 BOOL CApplicationView::ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam) 2022 { 2023 m_MainWindow->ItemCheckStateChanged(bChecked, CallbackParam); 2024 return TRUE; 2025 } 2026 // **** CApplicationView **** 2027 2028