1 /* 2 * PROJECT: ReactOS Applications Manager 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: GUI classes for RAPPS 5 * COPYRIGHT: Copyright 2015 David Quintana (gigaherz@gmail.com) 6 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) 7 * Copyright 2020 He Yang (1160386205@qq.com) 8 */ 9 10 #include "rapps.h" 11 #include "rosui.h" 12 #include "crichedit.h" 13 #include "asyncinet.h" 14 #include "gui.h" 15 #include <shlobj_undoc.h> 16 #include <shlguid_undoc.h> 17 18 #include <atlbase.h> 19 #include <atlcom.h> 20 #include <atltypes.h> 21 #include <atlwin.h> 22 #include <wininet.h> 23 #include <shellutils.h> 24 #include <ui/rosctrls.h> 25 #include <gdiplus.h> 26 #include <math.h> 27 28 #define SEARCH_TIMER_ID 'SR' 29 #define TREEVIEW_ICON_SIZE 24 30 31 // **** CSideTreeView **** 32 33 CSideTreeView::CSideTreeView() 34 : CUiWindow(), 35 hImageTreeView(ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE, GetSystemColorDepth() | ILC_MASK, 0, 1)) 36 { 37 } 38 39 HTREEITEM 40 CSideTreeView::AddItem(HTREEITEM hParent, CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam) 41 { 42 return CUiWindow<CTreeView>::AddItem(hParent, const_cast<LPWSTR>(Text.GetString()), Image, SelectedImage, lParam); 43 } 44 45 HTREEITEM 46 CSideTreeView::AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex) 47 { 48 CStringW szText; 49 INT Index = 0; 50 HICON hIcon; 51 52 hIcon = (HICON)LoadImageW( 53 hInst, MAKEINTRESOURCE(IconIndex), IMAGE_ICON, TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE, LR_CREATEDIBSECTION); 54 if (hIcon) 55 { 56 Index = ImageList_AddIcon(hImageTreeView, hIcon); 57 DestroyIcon(hIcon); 58 } 59 60 szText.LoadStringW(TextIndex); 61 return AddItem(hRootItem, szText, Index, Index, TextIndex); 62 } 63 64 HIMAGELIST 65 CSideTreeView::SetImageList() 66 { 67 return CUiWindow<CTreeView>::SetImageList(hImageTreeView, TVSIL_NORMAL); 68 } 69 70 VOID 71 CSideTreeView::DestroyImageList() 72 { 73 if (hImageTreeView) 74 ImageList_Destroy(hImageTreeView); 75 } 76 77 CSideTreeView::~CSideTreeView() 78 { 79 DestroyImageList(); 80 } 81 // **** CSideTreeView **** 82 83 // **** CMainWindow **** 84 85 CMainWindow::CMainWindow(CAppDB *db, BOOL bAppwiz) : m_ClientPanel(NULL), m_Db(db), bAppwizMode(bAppwiz), SelectedEnumType(ENUM_ALL_INSTALLED) 86 { 87 } 88 89 CMainWindow::~CMainWindow() 90 { 91 LayoutCleanup(); 92 } 93 94 VOID 95 CMainWindow::InitCategoriesList() 96 { 97 HTREEITEM hRootItemAvailable; 98 99 hRootItemInstalled = m_TreeView->AddCategory(TVI_ROOT, IDS_INSTALLED, IDI_CATEGORY); 100 m_TreeView->AddCategory(hRootItemInstalled, IDS_APPLICATIONS, IDI_APPS); 101 m_TreeView->AddCategory(hRootItemInstalled, IDS_UPDATES, IDI_APPUPD); 102 103 m_TreeView->AddCategory(TVI_ROOT, IDS_SELECTEDFORINST, IDI_SELECTEDFORINST); 104 105 hRootItemAvailable = m_TreeView->AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY); 106 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_AUDIO, IDI_CAT_AUDIO); 107 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_VIDEO, IDI_CAT_VIDEO); 108 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS); 109 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_GAMES, IDI_CAT_GAMES); 110 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_INTERNET, IDI_CAT_INTERNET); 111 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_OFFICE, IDI_CAT_OFFICE); 112 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_DEVEL, IDI_CAT_DEVEL); 113 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_EDU, IDI_CAT_EDU); 114 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER); 115 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_FINANCE, IDI_CAT_FINANCE); 116 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE); 117 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_TOOLS, IDI_CAT_TOOLS); 118 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS); 119 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_LIBS, IDI_CAT_LIBS); 120 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_THEMES, IDI_CAT_THEMES); 121 m_TreeView->AddCategory(hRootItemAvailable, IDS_CAT_OTHER, IDI_CAT_OTHER); 122 123 m_TreeView->SetImageList(); 124 m_TreeView->Expand(hRootItemInstalled, TVE_EXPAND); 125 m_TreeView->Expand(hRootItemAvailable, TVE_EXPAND); 126 m_TreeView->SelectItem(bAppwizMode ? hRootItemInstalled : hRootItemAvailable); 127 } 128 129 BOOL 130 CMainWindow::CreateStatusBar() 131 { 132 m_StatusBar = new CUiWindow<CStatusBar>(); 133 m_StatusBar->m_VerticalAlignment = UiAlign_RightBtm; 134 m_StatusBar->m_HorizontalAlignment = UiAlign_Stretch; 135 m_ClientPanel->Children().Append(m_StatusBar); 136 137 return m_StatusBar->Create(m_hWnd, (HMENU)IDC_STATUSBAR) != NULL; 138 } 139 140 BOOL 141 CMainWindow::CreateTreeView() 142 { 143 m_TreeView = new CSideTreeView(); 144 m_TreeView->m_VerticalAlignment = UiAlign_Stretch; 145 m_TreeView->m_HorizontalAlignment = UiAlign_Stretch; 146 m_VSplitter->First().Append(m_TreeView); 147 148 return m_TreeView->Create(m_hWnd) != NULL; 149 } 150 151 BOOL 152 CMainWindow::CreateApplicationView() 153 { 154 m_ApplicationView = new CApplicationView(this); // pass this to ApplicationView for callback purpose 155 m_ApplicationView->m_VerticalAlignment = UiAlign_Stretch; 156 m_ApplicationView->m_HorizontalAlignment = UiAlign_Stretch; 157 m_VSplitter->Second().Append(m_ApplicationView); 158 159 return m_ApplicationView->Create(m_hWnd) != NULL; 160 } 161 162 BOOL 163 CMainWindow::CreateVSplitter() 164 { 165 m_VSplitter = new CUiSplitPanel(); 166 m_VSplitter->m_VerticalAlignment = UiAlign_Stretch; 167 m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch; 168 m_VSplitter->m_DynamicFirst = FALSE; 169 m_VSplitter->m_Horizontal = FALSE; 170 m_VSplitter->m_MinFirst = 0; 171 172 // TODO: m_MinSecond should be calculate dynamically instead of hard-coded 173 m_VSplitter->m_MinSecond = 480; 174 m_VSplitter->m_Pos = 240; 175 m_ClientPanel->Children().Append(m_VSplitter); 176 177 return m_VSplitter->Create(m_hWnd) != NULL; 178 } 179 180 BOOL 181 CMainWindow::CreateLayout() 182 { 183 BOOL b = TRUE; 184 bUpdating = TRUE; 185 186 m_ClientPanel = new CUiPanel(); 187 m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch; 188 m_ClientPanel->m_HorizontalAlignment = UiAlign_Stretch; 189 190 // Top level 191 b = b && CreateStatusBar(); 192 b = b && CreateVSplitter(); 193 194 // Inside V Splitter 195 b = b && CreateTreeView(); 196 b = b && CreateApplicationView(); 197 198 if (b) 199 { 200 RECT rBottom; 201 202 /* Size status bar */ 203 m_StatusBar->SendMessageW(WM_SIZE, 0, 0); 204 205 ::GetWindowRect(m_StatusBar->m_hWnd, &rBottom); 206 207 m_VSplitter->m_Margin.bottom = rBottom.bottom - rBottom.top; 208 } 209 210 bUpdating = FALSE; 211 return b; 212 } 213 214 VOID 215 CMainWindow::LayoutCleanup() 216 { 217 delete m_TreeView; 218 delete m_ApplicationView; 219 delete m_VSplitter; 220 delete m_StatusBar; 221 return; 222 } 223 224 BOOL 225 CMainWindow::InitControls() 226 { 227 if (CreateLayout()) 228 { 229 InitCategoriesList(); 230 UpdateStatusBarText(); 231 232 return TRUE; 233 } 234 235 return FALSE; 236 } 237 238 VOID 239 CMainWindow::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam) 240 { 241 if (wParam == SIZE_MINIMIZED) 242 return; 243 244 /* Size status bar */ 245 m_StatusBar->SendMessage(WM_SIZE, 0, 0); 246 247 RECT r = {0, 0, LOWORD(lParam), HIWORD(lParam)}; 248 HDWP hdwp = NULL; 249 INT count = m_ClientPanel->CountSizableChildren(); 250 251 hdwp = BeginDeferWindowPos(count); 252 if (hdwp) 253 { 254 hdwp = m_ClientPanel->OnParentSize(r, hdwp); 255 if (hdwp) 256 { 257 EndDeferWindowPos(hdwp); 258 } 259 } 260 } 261 262 BOOL 263 CMainWindow::RemoveSelectedAppFromRegistry() 264 { 265 if (!IsInstalledEnum(SelectedEnumType)) 266 return FALSE; 267 268 CStringW szMsgText, szMsgTitle; 269 270 if (!szMsgText.LoadStringW(IDS_APP_REG_REMOVE) || !szMsgTitle.LoadStringW(IDS_INFORMATION)) 271 return FALSE; 272 273 if (MessageBoxW(szMsgText, szMsgTitle, MB_YESNO | MB_ICONQUESTION) == IDYES) 274 { 275 CAppInfo *InstalledApp = (CAppInfo *)m_ApplicationView->GetFocusedItemData(); 276 if (!InstalledApp) 277 return FALSE; 278 279 return m_Db->RemoveInstalledAppFromRegistry(InstalledApp); 280 } 281 282 return FALSE; 283 } 284 285 BOOL 286 CMainWindow::UninstallSelectedApp(BOOL bModify) 287 { 288 if (!IsInstalledEnum(SelectedEnumType)) 289 return FALSE; 290 291 CAppInfo *InstalledApp = (CAppInfo *)m_ApplicationView->GetFocusedItemData(); 292 if (!InstalledApp) 293 return FALSE; 294 295 return InstalledApp->UninstallApplication(bModify); 296 } 297 298 BOOL 299 CMainWindow::ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId) 300 { 301 theResult = 0; 302 switch (Msg) 303 { 304 case WM_CREATE: 305 if (!InitControls()) 306 ::PostMessageW(hwnd, WM_CLOSE, 0, 0); 307 break; 308 309 case WM_DESTROY: 310 { 311 ShowWindow(SW_HIDE); 312 SaveSettings(hwnd, &SettingsInfo); 313 314 FreeLogs(); 315 316 delete m_ClientPanel; 317 318 PostQuitMessage(0); 319 return 0; 320 } 321 322 case WM_COMMAND: 323 OnCommand(wParam, lParam); 324 break; 325 326 case WM_NOTIFY: 327 { 328 LPNMHDR data = (LPNMHDR)lParam; 329 330 switch (data->code) 331 { 332 case TVN_SELCHANGED: 333 { 334 if (data->hwndFrom == m_TreeView->m_hWnd) 335 { 336 switch (((LPNMTREEVIEW)lParam)->itemNew.lParam) 337 { 338 case IDS_INSTALLED: 339 UpdateApplicationsList(ENUM_ALL_INSTALLED); 340 break; 341 342 case IDS_APPLICATIONS: 343 UpdateApplicationsList(ENUM_INSTALLED_APPLICATIONS); 344 break; 345 346 case IDS_UPDATES: 347 UpdateApplicationsList(ENUM_UPDATES); 348 break; 349 350 case IDS_AVAILABLEFORINST: 351 UpdateApplicationsList(ENUM_ALL_AVAILABLE); 352 break; 353 354 case IDS_CAT_AUDIO: 355 UpdateApplicationsList(ENUM_CAT_AUDIO); 356 break; 357 358 case IDS_CAT_DEVEL: 359 UpdateApplicationsList(ENUM_CAT_DEVEL); 360 break; 361 362 case IDS_CAT_DRIVERS: 363 UpdateApplicationsList(ENUM_CAT_DRIVERS); 364 break; 365 366 case IDS_CAT_EDU: 367 UpdateApplicationsList(ENUM_CAT_EDU); 368 break; 369 370 case IDS_CAT_ENGINEER: 371 UpdateApplicationsList(ENUM_CAT_ENGINEER); 372 break; 373 374 case IDS_CAT_FINANCE: 375 UpdateApplicationsList(ENUM_CAT_FINANCE); 376 break; 377 378 case IDS_CAT_GAMES: 379 UpdateApplicationsList(ENUM_CAT_GAMES); 380 break; 381 382 case IDS_CAT_GRAPHICS: 383 UpdateApplicationsList(ENUM_CAT_GRAPHICS); 384 break; 385 386 case IDS_CAT_INTERNET: 387 UpdateApplicationsList(ENUM_CAT_INTERNET); 388 break; 389 390 case IDS_CAT_LIBS: 391 UpdateApplicationsList(ENUM_CAT_LIBS); 392 break; 393 394 case IDS_CAT_OFFICE: 395 UpdateApplicationsList(ENUM_CAT_OFFICE); 396 break; 397 398 case IDS_CAT_OTHER: 399 UpdateApplicationsList(ENUM_CAT_OTHER); 400 break; 401 402 case IDS_CAT_SCIENCE: 403 UpdateApplicationsList(ENUM_CAT_SCIENCE); 404 break; 405 406 case IDS_CAT_TOOLS: 407 UpdateApplicationsList(ENUM_CAT_TOOLS); 408 break; 409 410 case IDS_CAT_VIDEO: 411 UpdateApplicationsList(ENUM_CAT_VIDEO); 412 break; 413 414 case IDS_CAT_THEMES: 415 UpdateApplicationsList(ENUM_CAT_THEMES); 416 break; 417 418 case IDS_SELECTEDFORINST: 419 UpdateApplicationsList(ENUM_CAT_SELECTED); 420 break; 421 } 422 } 423 } 424 break; 425 } 426 } 427 break; 428 429 case WM_SIZE: 430 OnSize(hwnd, wParam, lParam); 431 break; 432 433 case WM_SIZING: 434 { 435 LPRECT pRect = (LPRECT)lParam; 436 437 if (pRect->right - pRect->left < 565) 438 pRect->right = pRect->left + 565; 439 440 if (pRect->bottom - pRect->top < 300) 441 pRect->bottom = pRect->top + 300; 442 443 return TRUE; 444 } 445 446 case WM_SYSCOLORCHANGE: 447 { 448 /* Forward WM_SYSCOLORCHANGE to common controls */ 449 m_ApplicationView->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam); 450 m_TreeView->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam); 451 } 452 break; 453 454 case WM_TIMER: 455 if (wParam == SEARCH_TIMER_ID) 456 { 457 ::KillTimer(hwnd, SEARCH_TIMER_ID); 458 459 UpdateApplicationsList(SelectedEnumType); 460 } 461 break; 462 } 463 464 return FALSE; 465 } 466 467 VOID 468 CMainWindow::ShowAboutDlg() 469 { 470 CStringW szApp; 471 CStringW szAuthors; 472 473 szApp.LoadStringW(IDS_APPTITLE); 474 szAuthors.LoadStringW(IDS_APP_AUTHORS); 475 ShellAboutW(m_hWnd, szApp, szAuthors, 476 LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN))); 477 } 478 479 VOID 480 CMainWindow::OnCommand(WPARAM wParam, LPARAM lParam) 481 { 482 const BOOL bReload = TRUE; 483 WORD wCommand = LOWORD(wParam); 484 485 if (!lParam) 486 { 487 switch (wCommand) 488 { 489 case ID_SETTINGS: 490 CreateSettingsDlg(m_hWnd); 491 break; 492 493 case ID_EXIT: 494 PostMessageW(WM_CLOSE, 0, 0); 495 break; 496 497 case ID_SEARCH: 498 m_ApplicationView->SetFocusOnSearchBar(); 499 break; 500 501 case ID_INSTALL: 502 if (IsAvailableEnum(SelectedEnumType)) 503 { 504 if (!m_Selected.IsEmpty()) 505 { 506 if (DownloadListOfApplications(m_Selected, FALSE)) 507 { 508 m_Selected.RemoveAll(); 509 UpdateApplicationsList(SelectedEnumType); 510 } 511 } 512 else 513 { 514 CAppInfo *App = (CAppInfo *)m_ApplicationView->GetFocusedItemData(); 515 if (App) 516 { 517 InstallApplication(App); 518 } 519 } 520 } 521 break; 522 523 case ID_UNINSTALL: 524 if (UninstallSelectedApp(FALSE)) 525 UpdateApplicationsList(SelectedEnumType, bReload); 526 break; 527 528 case ID_MODIFY: 529 if (UninstallSelectedApp(TRUE)) 530 UpdateApplicationsList(SelectedEnumType, bReload); 531 break; 532 533 case ID_REGREMOVE: 534 if (RemoveSelectedAppFromRegistry()) 535 UpdateApplicationsList(SelectedEnumType, bReload); 536 break; 537 538 case ID_REFRESH: 539 UpdateApplicationsList(SelectedEnumType); 540 break; 541 542 case ID_RESETDB: 543 m_Db->RemoveCached(); 544 UpdateApplicationsList(SelectedEnumType, bReload); 545 break; 546 547 case ID_HELP: 548 MessageBoxW(L"Help not implemented yet", NULL, MB_OK); 549 break; 550 551 case ID_ABOUT: 552 ShowAboutDlg(); 553 break; 554 555 case ID_CHECK_ALL: 556 m_ApplicationView->CheckAll(); 557 break; 558 559 case ID_ACTIVATE_APPWIZ: 560 if (hRootItemInstalled) 561 m_TreeView->SelectItem(hRootItemInstalled); 562 break; 563 } 564 } 565 } 566 567 VOID 568 CMainWindow::UpdateStatusBarText() 569 { 570 if (m_StatusBar) 571 { 572 CStringW szBuffer; 573 574 szBuffer.Format(IDS_APPS_COUNT, m_ApplicationView->GetItemCount(), m_Selected.GetCount()); 575 m_StatusBar->SetText(szBuffer); 576 } 577 } 578 579 VOID 580 CMainWindow::AddApplicationsToView(CAtlList<CAppInfo *> &List) 581 { 582 POSITION CurrentListPosition = List.GetHeadPosition(); 583 while (CurrentListPosition) 584 { 585 CAppInfo *Info = List.GetNext(CurrentListPosition); 586 if (szSearchPattern.IsEmpty() || SearchPatternMatch(Info->szDisplayName, szSearchPattern) || 587 SearchPatternMatch(Info->szComments, szSearchPattern)) 588 { 589 BOOL bSelected = m_Selected.Find(Info) != NULL; 590 m_ApplicationView->AddApplication(Info, bSelected); 591 } 592 } 593 } 594 595 VOID 596 CMainWindow::UpdateApplicationsList(AppsCategories EnumType, BOOL bReload) 597 { 598 bUpdating = TRUE; 599 600 if (SelectedEnumType != EnumType) 601 SelectedEnumType = EnumType; 602 603 if (bReload) 604 m_Selected.RemoveAll(); 605 606 m_ApplicationView->SetRedraw(FALSE); 607 if (IsInstalledEnum(EnumType)) 608 { 609 if (bReload) 610 m_Db->UpdateInstalled(); 611 612 // set the display type of application-view. this will remove all the item in application-view too. 613 m_ApplicationView->SetDisplayAppType(AppViewTypeInstalledApps); 614 615 CAtlList<CAppInfo *> List; 616 m_Db->GetApps(List, EnumType); 617 AddApplicationsToView(List); 618 } 619 else if (IsAvailableEnum(EnumType)) 620 { 621 if (bReload) 622 m_Db->UpdateAvailable(); 623 624 // set the display type of application-view. this will remove all the item in application-view too. 625 m_ApplicationView->SetDisplayAppType(AppViewTypeAvailableApps); 626 627 // enum available softwares 628 if (EnumType == ENUM_CAT_SELECTED) 629 { 630 AddApplicationsToView(m_Selected); 631 } 632 else 633 { 634 CAtlList<CAppInfo *> List; 635 m_Db->GetApps(List, EnumType); 636 AddApplicationsToView(List); 637 } 638 } 639 else 640 { 641 ATLASSERT(0 && "This should be unreachable!"); 642 } 643 m_ApplicationView->SetRedraw(TRUE); 644 m_ApplicationView->RedrawWindow(0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN); // force the child window to repaint 645 UpdateStatusBarText(); 646 647 CStringW text; 648 if (m_ApplicationView->GetItemCount() == 0 && !szSearchPattern.IsEmpty()) 649 { 650 text.LoadString(IDS_NO_SEARCH_RESULTS); 651 } 652 m_ApplicationView->SetWatermark(text); 653 654 bUpdating = FALSE; 655 } 656 657 ATL::CWndClassInfo & 658 CMainWindow::GetWndClassInfo() 659 { 660 DWORD csStyle = CS_VREDRAW | CS_HREDRAW; 661 static ATL::CWndClassInfo wc = { 662 {sizeof(WNDCLASSEX), csStyle, StartWindowProc, 0, 0, NULL, 663 LoadIconW(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN)), LoadCursorW(NULL, IDC_ARROW), 664 (HBRUSH)(COLOR_BTNFACE + 1), MAKEINTRESOURCEW(IDR_MAINMENU), szWindowClass, NULL}, 665 NULL, 666 NULL, 667 IDC_ARROW, 668 TRUE, 669 0, 670 _T("")}; 671 return wc; 672 } 673 674 HWND 675 CMainWindow::Create() 676 { 677 CStringW szWindowName; 678 szWindowName.LoadStringW(IDS_APPTITLE); 679 680 RECT r = { 681 (SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT), 682 (SettingsInfo.bSaveWndPos ? SettingsInfo.Top : CW_USEDEFAULT), 683 (SettingsInfo.bSaveWndPos ? SettingsInfo.Width : 680), (SettingsInfo.bSaveWndPos ? SettingsInfo.Height : 450)}; 684 r.right += r.left; 685 r.bottom += r.top; 686 687 return CWindowImpl::Create( 688 NULL, r, szWindowName.GetString(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE); 689 } 690 691 // this function is called when a item of application-view is checked/unchecked 692 // CallbackParam is the param passed to application-view when adding the item (the one getting focus now). 693 VOID 694 CMainWindow::ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam) 695 { 696 if (bUpdating) 697 return; 698 699 CAppInfo *Info = (CAppInfo *)CallbackParam; 700 701 if (bChecked) 702 { 703 m_Selected.AddTail(Info); 704 } 705 else 706 { 707 POSITION Pos = m_Selected.Find(Info); 708 ATLASSERT(Pos != NULL); 709 710 if (Pos != NULL) 711 { 712 m_Selected.RemoveAt(Pos); 713 } 714 } 715 716 UpdateStatusBarText(); 717 } 718 719 // this function is called when one or more application(s) should be installed 720 // if Info is not zero, this app should be installed. otherwise those checked apps should be installed 721 BOOL 722 CMainWindow::InstallApplication(CAppInfo *Info) 723 { 724 if (Info) 725 { 726 if (DownloadApplication(Info)) 727 { 728 UpdateApplicationsList(SelectedEnumType); 729 return TRUE; 730 } 731 } 732 733 return FALSE; 734 } 735 736 BOOL 737 CMainWindow::SearchTextChanged(CStringW &SearchText) 738 { 739 if (szSearchPattern == SearchText) 740 { 741 return FALSE; 742 } 743 744 szSearchPattern = SearchText; 745 746 DWORD dwDelay = 0; 747 SystemParametersInfoW(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0); 748 SetTimer(SEARCH_TIMER_ID, dwDelay); 749 750 return TRUE; 751 } 752 753 void 754 CMainWindow::HandleTabOrder(int direction) 755 { 756 ATL::CSimpleArray<HWND> TabOrderHwndList; 757 758 m_TreeView->AppendTabOrderWindow(direction, TabOrderHwndList); 759 m_ApplicationView->AppendTabOrderWindow(direction, TabOrderHwndList); 760 761 if (TabOrderHwndList.GetSize() == 0) 762 { 763 // in case the list is empty 764 return; 765 } 766 767 int FocusIndex; 768 769 if ((FocusIndex = TabOrderHwndList.Find(GetFocus())) == -1) 770 { 771 FocusIndex = 0; // focus the first window in the list 772 } 773 else 774 { 775 FocusIndex += direction; 776 FocusIndex += 777 TabOrderHwndList.GetSize(); // FocusIndex might be negative. we don't want to mod a negative number 778 FocusIndex %= TabOrderHwndList.GetSize(); 779 } 780 781 ::SetFocus(TabOrderHwndList[FocusIndex]); 782 return; 783 } 784 // **** CMainWindow **** 785 786 VOID 787 MainWindowLoop(CMainWindow *wnd, INT nShowCmd) 788 { 789 HACCEL KeyBrd; 790 MSG Msg; 791 792 hMainWnd = wnd->Create(); 793 if (!hMainWnd) 794 return; 795 796 /* Maximize it if we must */ 797 wnd->ShowWindow((SettingsInfo.bSaveWndPos && SettingsInfo.Maximized) ? SW_MAXIMIZE : nShowCmd); 798 wnd->UpdateWindow(); 799 800 /* Load the menu hotkeys */ 801 KeyBrd = LoadAcceleratorsW(NULL, MAKEINTRESOURCEW(HOTKEYS)); 802 803 /* Message Loop */ 804 while (GetMessageW(&Msg, NULL, 0, 0)) 805 { 806 if (!TranslateAcceleratorW(hMainWnd, KeyBrd, &Msg)) 807 { 808 if (Msg.message == WM_CHAR && Msg.wParam == VK_TAB) 809 { 810 // Move backwards if shift is held down 811 int direction = (GetKeyState(VK_SHIFT) & 0x8000) ? -1 : 1; 812 813 wnd->HandleTabOrder(direction); 814 continue; 815 } 816 817 TranslateMessage(&Msg); 818 DispatchMessageW(&Msg); 819 } 820 } 821 } 822