2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/gui.cpp
5 * PURPOSE: GUI classes for RAPPS
6 * COPYRIGHT: Copyright 2015 David Quintana (gigaherz@gmail.com)
7 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
13 #include "crichedit.h"
15 #include <shlobj_undoc.h>
16 #include <shlguid_undoc.h>
22 #include <shellutils.h>
25 #define SEARCH_TIMER_ID 'SR'
26 #define LISTVIEW_ICON_SIZE 24
27 #define TREEVIEW_ICON_SIZE 24
29 HWND hListView
= NULL
;
31 INT
GetSystemColorDepth()
36 pDevMode
.dmSize
= sizeof(pDevMode
);
37 pDevMode
.dmDriverExtra
= 0;
39 if (!EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &pDevMode
))
41 /* TODO: Error message */
45 switch (pDevMode
.dmBitsPerPel
)
47 case 32: ColorDepth
= ILC_COLOR32
; break;
48 case 24: ColorDepth
= ILC_COLOR24
; break;
49 case 16: ColorDepth
= ILC_COLOR16
; break;
50 case 8: ColorDepth
= ILC_COLOR8
; break;
51 case 4: ColorDepth
= ILC_COLOR4
; break;
52 default: ColorDepth
= ILC_COLOR
; break;
59 public CUiWindow
<CRichEdit
>
62 VOID
LoadAndInsertText(UINT uStringID
,
63 const ATL::CStringW
& szText
,
67 ATL::CStringW szLoadedText
;
68 if (!szText
.IsEmpty() && szLoadedText
.LoadStringW(uStringID
))
70 InsertText(szLoadedText
, StringFlags
);
71 InsertText(szText
, TextFlags
);
75 VOID
LoadAndInsertText(UINT uStringID
,
78 ATL::CStringW szLoadedText
;
79 if (szLoadedText
.LoadStringW(uStringID
))
82 InsertText(szLoadedText
, StringFlags
);
87 VOID
InsertVersionInfo(CAvailableApplicationInfo
* Info
)
89 if (Info
->IsInstalled())
91 if (Info
->HasInstalledVersion())
93 if (Info
->HasUpdate())
94 LoadAndInsertText(IDS_STATUS_UPDATE_AVAILABLE
, CFE_ITALIC
);
96 LoadAndInsertText(IDS_STATUS_INSTALLED
, CFE_ITALIC
);
98 LoadAndInsertText(IDS_AINFO_VERSION
, Info
->m_szInstalledVersion
, CFE_BOLD
, 0);
102 LoadAndInsertText(IDS_STATUS_INSTALLED
, CFE_ITALIC
);
107 LoadAndInsertText(IDS_STATUS_NOTINSTALLED
, CFE_ITALIC
);
110 LoadAndInsertText(IDS_AINFO_AVAILABLEVERSION
, Info
->m_szVersion
, CFE_BOLD
, 0);
113 VOID
InsertLicenseInfo(CAvailableApplicationInfo
* Info
)
115 ATL::CStringW szLicense
;
116 switch (Info
->m_LicenseType
)
118 case LICENSE_OPENSOURCE
:
119 szLicense
.LoadStringW(IDS_LICENSE_OPENSOURCE
);
121 case LICENSE_FREEWARE
:
122 szLicense
.LoadStringW(IDS_LICENSE_FREEWARE
);
125 szLicense
.LoadStringW(IDS_LICENSE_TRIAL
);
128 LoadAndInsertText(IDS_AINFO_LICENSE
, Info
->m_szLicense
, CFE_BOLD
, 0);
132 szLicense
+= L
" (" + Info
->m_szLicense
+ L
")";
133 LoadAndInsertText(IDS_AINFO_LICENSE
, szLicense
, CFE_BOLD
, 0);
136 VOID
InsertLanguageInfo(CAvailableApplicationInfo
* Info
)
138 if (!Info
->HasLanguageInfo())
143 const INT nTranslations
= Info
->m_LanguageLCIDs
.GetSize();
144 ATL::CStringW szLangInfo
;
145 ATL::CStringW szLoadedTextAvailability
;
146 ATL::CStringW szLoadedAInfoText
;
148 szLoadedAInfoText
.LoadStringW(IDS_AINFO_LANGUAGES
);
150 if (Info
->HasNativeLanguage())
152 szLoadedTextAvailability
.LoadStringW(IDS_LANGUAGE_AVAILABLE_TRANSLATION
);
153 if (nTranslations
> 1)
156 buf
.LoadStringW(IDS_LANGUAGE_MORE_PLACEHOLDER
);
157 szLangInfo
.Format(buf
, nTranslations
- 1);
161 szLangInfo
.LoadStringW(IDS_LANGUAGE_SINGLE
);
162 szLangInfo
= L
" (" + szLangInfo
+ L
")";
165 else if (Info
->HasEnglishLanguage())
167 szLoadedTextAvailability
.LoadStringW(IDS_LANGUAGE_ENGLISH_TRANSLATION
);
168 if (nTranslations
> 1)
171 buf
.LoadStringW(IDS_LANGUAGE_AVAILABLE_PLACEHOLDER
);
172 szLangInfo
.Format(buf
, nTranslations
- 1);
176 szLangInfo
.LoadStringW(IDS_LANGUAGE_SINGLE
);
177 szLangInfo
= L
" (" + szLangInfo
+ L
")";
182 szLoadedTextAvailability
.LoadStringW(IDS_LANGUAGE_NO_TRANSLATION
);
185 InsertText(szLoadedAInfoText
, CFE_BOLD
);
186 InsertText(szLoadedTextAvailability
, NULL
);
187 InsertText(szLangInfo
, CFE_ITALIC
);
191 BOOL
ShowAvailableAppInfo(CAvailableApplicationInfo
* Info
)
193 if (!Info
) return FALSE
;
195 SetText(Info
->m_szName
, CFE_BOLD
);
196 InsertVersionInfo(Info
);
197 InsertLicenseInfo(Info
);
198 InsertLanguageInfo(Info
);
200 LoadAndInsertText(IDS_AINFO_SIZE
, Info
->m_szSize
, CFE_BOLD
, 0);
201 LoadAndInsertText(IDS_AINFO_URLSITE
, Info
->m_szUrlSite
, CFE_BOLD
, CFE_LINK
);
202 LoadAndInsertText(IDS_AINFO_DESCRIPTION
, Info
->m_szDesc
, CFE_BOLD
, 0);
203 LoadAndInsertText(IDS_AINFO_URLDOWNLOAD
, Info
->m_szUrlDownload
, CFE_BOLD
, CFE_LINK
);
208 BOOL
ShowInstalledAppInfo(PINSTALLED_INFO Info
)
210 ATL::CStringW szText
;
211 ATL::CStringW szInfo
;
213 if (!Info
|| !Info
->hSubKey
)
216 Info
->GetApplicationString(L
"DisplayName", szText
);
217 SetText(szText
, CFE_BOLD
);
218 InsertText(L
"\n", 0);
220 #define GET_INFO(a, b, c, d) \
221 if (Info->GetApplicationString(a, szInfo)) \
223 LoadAndInsertText(b, szInfo, c, d); \
226 GET_INFO(L
"DisplayVersion", IDS_INFO_VERSION
, CFE_BOLD
, 0);
227 GET_INFO(L
"Publisher", IDS_INFO_PUBLISHER
, CFE_BOLD
, 0);
228 GET_INFO(L
"RegOwner", IDS_INFO_REGOWNER
, CFE_BOLD
, 0);
229 GET_INFO(L
"ProductID", IDS_INFO_PRODUCTID
, CFE_BOLD
, 0);
230 GET_INFO(L
"HelpLink", IDS_INFO_HELPLINK
, CFE_BOLD
, CFM_LINK
);
231 GET_INFO(L
"HelpTelephone", IDS_INFO_HELPPHONE
, CFE_BOLD
, 0);
232 GET_INFO(L
"Readme", IDS_INFO_README
, CFE_BOLD
, 0);
233 GET_INFO(L
"Contact", IDS_INFO_CONTACT
, CFE_BOLD
, 0);
234 GET_INFO(L
"URLUpdateInfo", IDS_INFO_UPDATEINFO
, CFE_BOLD
, CFM_LINK
);
235 GET_INFO(L
"URLInfoAbout", IDS_INFO_INFOABOUT
, CFE_BOLD
, CFM_LINK
);
236 GET_INFO(L
"Comments", IDS_INFO_COMMENTS
, CFE_BOLD
, 0);
237 GET_INFO(L
"InstallDate", IDS_INFO_INSTALLDATE
, CFE_BOLD
, 0);
238 GET_INFO(L
"InstallLocation", IDS_INFO_INSTLOCATION
, CFE_BOLD
, 0);
239 GET_INFO(L
"InstallSource", IDS_INFO_INSTALLSRC
, CFE_BOLD
, 0);
240 GET_INFO(L
"UninstallString", IDS_INFO_UNINSTALLSTR
, CFE_BOLD
, 0);
241 GET_INFO(L
"InstallSource", IDS_INFO_INSTALLSRC
, CFE_BOLD
, 0);
242 GET_INFO(L
"ModifyPath", IDS_INFO_MODIFYPATH
, CFE_BOLD
, 0);
247 VOID
SetWelcomeText()
249 ATL::CStringW szText
;
251 szText
.LoadStringW(IDS_WELCOME_TITLE
);
252 SetText(szText
, CFE_BOLD
);
254 szText
.LoadStringW(IDS_WELCOME_TEXT
);
255 InsertText(szText
, 0);
257 szText
.LoadStringW(IDS_WELCOME_URL
);
258 InsertText(szText
, CFM_LINK
);
263 public CUiWindow
< CToolbar
<> >
265 const INT m_iToolbarHeight
;
266 DWORD m_dButtonsWidthMax
;
268 WCHAR szInstallBtn
[MAX_STR_LEN
];
269 WCHAR szUninstallBtn
[MAX_STR_LEN
];
270 WCHAR szModifyBtn
[MAX_STR_LEN
];
271 WCHAR szSelectAll
[MAX_STR_LEN
];
273 VOID
AddImageToImageList(HIMAGELIST hImageList
, UINT ImageIndex
)
277 if (!(hImage
= (HICON
) LoadImageW(hInst
,
278 MAKEINTRESOURCE(ImageIndex
),
284 /* TODO: Error message */
287 ImageList_AddIcon(hImageList
, hImage
);
288 DeleteObject(hImage
);
291 HIMAGELIST
InitImageList()
293 HIMAGELIST hImageList
;
295 /* Create the toolbar icon image list */
296 hImageList
= ImageList_Create(m_iToolbarHeight
,//GetSystemMetrics(SM_CXSMICON),
297 m_iToolbarHeight
,//GetSystemMetrics(SM_CYSMICON),
298 ILC_MASK
| GetSystemColorDepth(),
302 /* TODO: Error message */
306 AddImageToImageList(hImageList
, IDI_INSTALL
);
307 AddImageToImageList(hImageList
, IDI_UNINSTALL
);
308 AddImageToImageList(hImageList
, IDI_MODIFY
);
309 AddImageToImageList(hImageList
, IDI_CHECK_ALL
);
310 AddImageToImageList(hImageList
, IDI_REFRESH
);
311 AddImageToImageList(hImageList
, IDI_UPDATE_DB
);
312 AddImageToImageList(hImageList
, IDI_SETTINGS
);
313 AddImageToImageList(hImageList
, IDI_EXIT
);
319 CMainToolbar() : m_iToolbarHeight(24)
323 VOID
OnGetDispInfo(LPTOOLTIPTEXT lpttt
)
325 UINT idButton
= (UINT
) lpttt
->hdr
.idFrom
;
330 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT
);
334 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL
);
338 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL
);
342 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY
);
346 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS
);
350 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH
);
354 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB
);
359 HWND
Create(HWND hwndParent
)
363 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
364 { 0, ID_INSTALL
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, (INT_PTR
) szInstallBtn
},
365 { 1, ID_UNINSTALL
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, (INT_PTR
) szUninstallBtn
},
366 { 2, ID_MODIFY
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, (INT_PTR
) szModifyBtn
},
367 { 3, ID_CHECK_ALL
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, (INT_PTR
) szSelectAll
},
368 { -1, 0, TBSTATE_ENABLED
, BTNS_SEP
, { 0 }, 0, 0 },
369 { 4, ID_REFRESH
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, 0 },
370 { 5, ID_RESETDB
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, 0 },
371 { -1, 0, TBSTATE_ENABLED
, BTNS_SEP
, { 0 }, 0, 0 },
372 { 6, ID_SETTINGS
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, 0 },
373 { 7, ID_EXIT
, TBSTATE_ENABLED
, BTNS_BUTTON
| BTNS_AUTOSIZE
, { 0 }, 0, 0 },
376 LoadStringW(hInst
, IDS_INSTALL
, szInstallBtn
, _countof(szInstallBtn
));
377 LoadStringW(hInst
, IDS_UNINSTALL
, szUninstallBtn
, _countof(szUninstallBtn
));
378 LoadStringW(hInst
, IDS_MODIFY
, szModifyBtn
, _countof(szModifyBtn
));
379 LoadStringW(hInst
, IDS_SELECT_ALL
, szSelectAll
, _countof(szSelectAll
));
381 m_hWnd
= CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
,
382 WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
| TBSTYLE_LIST
,
389 /* TODO: Show error message */
393 SendMessageW(TB_SETEXTENDEDSTYLE
, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
394 SetButtonStructSize();
397 HIMAGELIST hImageList
= InitImageList();
401 /* TODO: Show error message */
405 ImageList_Destroy(SetImageList(hImageList
));
407 AddButtons(_countof(Buttons
), Buttons
);
409 /* Remember ideal width to use as a max width of buttons */
411 GetIdealSize(FALSE
, &size
);
412 m_dButtonsWidthMax
= size
.cx
;
417 VOID
HideButtonCaption()
419 DWORD dCurrentExStyle
= (DWORD
) SendMessageW(TB_GETEXTENDEDSTYLE
, 0, 0);
420 SendMessageW(TB_SETEXTENDEDSTYLE
, 0, dCurrentExStyle
| TBSTYLE_EX_MIXEDBUTTONS
);
423 VOID
ShowButtonCaption()
425 DWORD dCurrentExStyle
= (DWORD
) SendMessageW(TB_GETEXTENDEDSTYLE
, 0, 0);
426 SendMessageW(TB_SETEXTENDEDSTYLE
, 0, dCurrentExStyle
& ~TBSTYLE_EX_MIXEDBUTTONS
);
429 DWORD
GetMaxButtonsWidth() const
431 return m_dButtonsWidthMax
;
435 class CAppsListView
:
436 public CUiWindow
<CListView
>
452 bHasAllChecked(FALSE
),
454 bHasCheckboxes(FALSE
),
459 VOID
SetCheckboxesVisible(BOOL bIsVisible
)
463 SetExtendedListViewStyle(LVS_EX_CHECKBOXES
| LVS_EX_FULLROWSELECT
);
467 SetExtendedListViewStyle(LVS_EX_FULLROWSELECT
);
470 bHasCheckboxes
= bIsVisible
;
473 VOID
ColumnClick(LPNMLISTVIEW pnmv
)
477 INT nHeaderID
= pnmv
->iSubItem
;
479 if ((GetWindowLongPtr(GWL_STYLE
) & ~LVS_NOSORTHEADER
) == 0)
482 hHeader
= (HWND
) SendMessage(LVM_GETHEADER
, 0, 0);
483 ZeroMemory(&hColumn
, sizeof(hColumn
));
485 /* If the sorting column changed, remove the sorting style from the old column */
486 if ((nLastHeaderID
!= -1) && (nLastHeaderID
!= nHeaderID
))
488 hColumn
.mask
= HDI_FORMAT
;
489 Header_GetItem(hHeader
, nLastHeaderID
, &hColumn
);
490 hColumn
.fmt
&= ~(HDF_SORTUP
| HDF_SORTDOWN
);
491 Header_SetItem(hHeader
, nLastHeaderID
, &hColumn
);
494 /* Set the sorting style to the new column */
495 hColumn
.mask
= HDI_FORMAT
;
496 Header_GetItem(hHeader
, nHeaderID
, &hColumn
);
498 hColumn
.fmt
&= (bIsAscending
? ~HDF_SORTDOWN
: ~HDF_SORTUP
);
499 hColumn
.fmt
|= (bIsAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
500 Header_SetItem(hHeader
, nHeaderID
, &hColumn
);
502 /* Sort the list, using the current values of nHeaderID and bIsAscending */
503 SortContext ctx
= {this, nHeaderID
};
504 SortItems(s_CompareFunc
, &ctx
);
506 /* Save new values */
507 nLastHeaderID
= nHeaderID
;
508 bIsAscending
= !bIsAscending
;
511 PVOID
GetLParam(INT Index
)
518 ItemIndex
= (INT
) SendMessage(LVM_GETNEXTITEM
, -1, LVNI_FOCUSED
);
527 ZeroMemory(&Item
, sizeof(Item
));
529 Item
.mask
= LVIF_PARAM
;
530 Item
.iItem
= ItemIndex
;
534 return (PVOID
) Item
.lParam
;
537 BOOL
AddColumn(INT Index
, ATL::CStringW
& Text
, INT Width
, INT Format
)
539 return AddColumn(Index
, const_cast<LPWSTR
>(Text
.GetString()), Width
, Format
);
542 BOOL
AddColumn(INT Index
, LPWSTR lpText
, INT Width
, INT Format
)
546 ZeroMemory(&Column
, sizeof(Column
));
548 Column
.mask
= LVCF_FMT
| LVCF_TEXT
| LVCF_WIDTH
| LVCF_SUBITEM
;
549 Column
.iSubItem
= Index
;
550 Column
.pszText
= lpText
;
554 return (InsertColumn(Index
, &Column
) == -1) ? FALSE
: TRUE
;
557 INT
AddItem(INT ItemIndex
, INT IconIndex
, LPCWSTR lpText
, LPARAM lParam
)
561 ZeroMemory(&Item
, sizeof(Item
));
563 Item
.mask
= LVIF_TEXT
| LVIF_PARAM
| LVIF_STATE
| LVIF_IMAGE
;
564 Item
.pszText
= const_cast<LPWSTR
>(lpText
);
565 Item
.lParam
= lParam
;
566 Item
.iItem
= ItemIndex
;
567 Item
.iImage
= IconIndex
;
569 return InsertItem(&Item
);
572 static INT CALLBACK
s_CompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
574 SortContext
* ctx
= ((SortContext
*) lParamSort
);
575 return ctx
->lvw
->CompareFunc(lParam1
, lParam2
, ctx
->iSubItem
);
578 INT
CompareFunc(LPARAM lParam1
, LPARAM lParam2
, INT iSubItem
)
580 ATL::CStringW Item1
, Item2
;
581 LVFINDINFOW IndexInfo
;
584 IndexInfo
.flags
= LVFI_PARAM
;
586 IndexInfo
.lParam
= lParam1
;
587 Index
= FindItem(-1, &IndexInfo
);
588 GetItemText(Index
, iSubItem
, Item1
.GetBuffer(MAX_STR_LEN
), MAX_STR_LEN
);
589 Item1
.ReleaseBuffer();
591 IndexInfo
.lParam
= lParam2
;
592 Index
= FindItem(-1, &IndexInfo
);
593 GetItemText(Index
, iSubItem
, Item2
.GetBuffer(MAX_STR_LEN
), MAX_STR_LEN
);
594 Item2
.ReleaseBuffer();
596 return bIsAscending
? Item1
.Compare(Item2
) : Item2
.Compare(Item1
);
599 HWND
Create(HWND hwndParent
)
601 RECT r
= {205, 28, 465, 250};
602 DWORD style
= WS_CHILD
| WS_VISIBLE
| LVS_SORTASCENDING
| LVS_REPORT
| LVS_SINGLESEL
| LVS_SHOWSELALWAYS
;
603 HMENU menu
= GetSubMenu(LoadMenuW(hInst
, MAKEINTRESOURCEW(IDR_APPLICATIONMENU
)), 0);
605 HWND hwnd
= CListView::Create(hwndParent
, r
, NULL
, style
, WS_EX_CLIENTEDGE
, menu
);
609 SetCheckboxesVisible(FALSE
);
615 BOOL
GetCheckState(INT item
)
617 return (BOOL
) (GetItemState(item
, LVIS_STATEIMAGEMASK
) >> 12) - 1;
620 VOID
SetCheckState(INT item
, BOOL fCheck
)
624 SetItemState(item
, INDEXTOSTATEIMAGEMASK((fCheck
) ? 2 : 1), LVIS_STATEIMAGEMASK
);
625 SetSelected(item
, fCheck
);
629 VOID
SetSelected(INT item
, BOOL value
)
633 for (INT i
= 0; i
>= 0; i
= GetNextItem(i
, LVNI_ALL
))
635 CAvailableApplicationInfo
* pAppInfo
= (CAvailableApplicationInfo
*) GetItemData(i
);
638 pAppInfo
->m_IsSelected
= value
;
644 CAvailableApplicationInfo
* pAppInfo
= (CAvailableApplicationInfo
*) GetItemData(item
);
647 pAppInfo
->m_IsSelected
= value
;
656 bHasAllChecked
= !bHasAllChecked
;
657 SetCheckState(-1, bHasAllChecked
);
661 ATL::CSimpleArray
<CAvailableApplicationInfo
> GetCheckedItems()
665 return ATL::CSimpleArray
<CAvailableApplicationInfo
>();
668 ATL::CSimpleArray
<CAvailableApplicationInfo
> list
;
669 for (INT i
= 0; i
>= 0; i
= GetNextItem(i
, LVNI_ALL
))
671 if (GetCheckState(i
) != FALSE
)
673 CAvailableApplicationInfo
* pAppInfo
= (CAvailableApplicationInfo
*) GetItemData(i
);
680 CAvailableApplicationInfo
* GetSelectedData()
682 INT item
= GetSelectionMark();
683 return (CAvailableApplicationInfo
*) GetItemData(item
);
687 class CSideTreeView
:
688 public CUiWindow
<CTreeView
>
690 HIMAGELIST hImageTreeView
;
695 hImageTreeView(ImageList_Create(TREEVIEW_ICON_SIZE
, TREEVIEW_ICON_SIZE
,
696 GetSystemColorDepth() | ILC_MASK
,
701 HTREEITEM
AddItem(HTREEITEM hParent
, ATL::CStringW
&Text
, INT Image
, INT SelectedImage
, LPARAM lParam
)
703 return CUiWindow
<CTreeView
>::AddItem(hParent
, const_cast<LPWSTR
>(Text
.GetString()), Image
, SelectedImage
, lParam
);
706 HTREEITEM
AddCategory(HTREEITEM hRootItem
, UINT TextIndex
, UINT IconIndex
)
708 ATL::CStringW szText
;
712 hIcon
= (HICON
) LoadImageW(hInst
,
713 MAKEINTRESOURCE(IconIndex
),
717 LR_CREATEDIBSECTION
);
720 Index
= ImageList_AddIcon(hImageTreeView
, hIcon
);
724 szText
.LoadStringW(TextIndex
);
725 return AddItem(hRootItem
, szText
, Index
, Index
, TextIndex
);
728 HIMAGELIST
SetImageList()
730 return CUiWindow
<CTreeView
>::SetImageList(hImageTreeView
, TVSIL_NORMAL
);
733 VOID
DestroyImageList()
736 ImageList_Destroy(hImageTreeView
);
752 CSearchBar() : m_Width(200), m_Height(22)
756 VOID
SetText(LPCWSTR lpszText
)
758 SendMessageW(SB_SETTEXT
, SBT_NOBORDERS
, (LPARAM
) lpszText
);
761 HWND
Create(HWND hwndParent
)
764 m_hWnd
= CreateWindowExW(WS_EX_CLIENTEDGE
, L
"Edit", NULL
,
765 WS_CHILD
| WS_VISIBLE
| ES_LEFT
| ES_AUTOHSCROLL
,
766 0, 0, m_Width
, m_Height
,
767 hwndParent
, (HMENU
) NULL
,
770 SendMessageW(WM_SETFONT
, (WPARAM
) GetStockObject(DEFAULT_GUI_FONT
), 0);
771 szBuf
.LoadStringW(IDS_SEARCH_TEXT
);
772 SetWindowTextW(szBuf
);
779 public CWindowImpl
<CMainWindow
, CWindow
, CFrameWinTraits
>
781 CUiPanel
* m_ClientPanel
;
782 CUiSplitPanel
* m_VSplitter
;
783 CUiSplitPanel
* m_HSplitter
;
785 CMainToolbar
* m_Toolbar
;
786 CAppsListView
* m_ListView
;
788 CSideTreeView
* m_TreeView
;
789 CUiWindow
<CStatusBar
>* m_StatusBar
;
790 CAppRichEdit
* m_RichEdit
;
792 CUiWindow
<CSearchBar
>* m_SearchBar
;
793 CAvailableApps m_AvailableApps
;
806 bSearchEnabled(FALSE
)
811 VOID
InitApplicationsList()
813 ATL::CStringW szText
;
815 /* Add columns to ListView */
816 szText
.LoadStringW(IDS_APP_NAME
);
817 m_ListView
->AddColumn(0, szText
, 250, LVCFMT_LEFT
);
819 szText
.LoadStringW(IDS_APP_INST_VERSION
);
820 m_ListView
->AddColumn(1, szText
, 90, LVCFMT_RIGHT
);
822 szText
.LoadStringW(IDS_APP_DESCRIPTION
);
823 m_ListView
->AddColumn(3, szText
, 300, LVCFMT_LEFT
);
825 // Unnesesary since the list updates on every TreeView selection
826 // UpdateApplicationsList(ENUM_ALL_COMPONENTS);
829 HTREEITEM
AddCategory(HTREEITEM hRootItem
, UINT TextIndex
, UINT IconIndex
)
831 return m_TreeView
->AddCategory(hRootItem
, TextIndex
, IconIndex
);
834 VOID
InitCategoriesList()
836 HTREEITEM hRootItemInstalled
, hRootItemAvailable
;
838 hRootItemInstalled
= AddCategory(TVI_ROOT
, IDS_INSTALLED
, IDI_CATEGORY
);
839 AddCategory(hRootItemInstalled
, IDS_APPLICATIONS
, IDI_APPS
);
840 AddCategory(hRootItemInstalled
, IDS_UPDATES
, IDI_APPUPD
);
842 AddCategory(TVI_ROOT
, IDS_SELECTEDFORINST
, IDI_SELECTEDFORINST
);
844 hRootItemAvailable
= AddCategory(TVI_ROOT
, IDS_AVAILABLEFORINST
, IDI_CATEGORY
);
845 AddCategory(hRootItemAvailable
, IDS_CAT_AUDIO
, IDI_CAT_AUDIO
);
846 AddCategory(hRootItemAvailable
, IDS_CAT_VIDEO
, IDI_CAT_VIDEO
);
847 AddCategory(hRootItemAvailable
, IDS_CAT_GRAPHICS
, IDI_CAT_GRAPHICS
);
848 AddCategory(hRootItemAvailable
, IDS_CAT_GAMES
, IDI_CAT_GAMES
);
849 AddCategory(hRootItemAvailable
, IDS_CAT_INTERNET
, IDI_CAT_INTERNET
);
850 AddCategory(hRootItemAvailable
, IDS_CAT_OFFICE
, IDI_CAT_OFFICE
);
851 AddCategory(hRootItemAvailable
, IDS_CAT_DEVEL
, IDI_CAT_DEVEL
);
852 AddCategory(hRootItemAvailable
, IDS_CAT_EDU
, IDI_CAT_EDU
);
853 AddCategory(hRootItemAvailable
, IDS_CAT_ENGINEER
, IDI_CAT_ENGINEER
);
854 AddCategory(hRootItemAvailable
, IDS_CAT_FINANCE
, IDI_CAT_FINANCE
);
855 AddCategory(hRootItemAvailable
, IDS_CAT_SCIENCE
, IDI_CAT_SCIENCE
);
856 AddCategory(hRootItemAvailable
, IDS_CAT_TOOLS
, IDI_CAT_TOOLS
);
857 AddCategory(hRootItemAvailable
, IDS_CAT_DRIVERS
, IDI_CAT_DRIVERS
);
858 AddCategory(hRootItemAvailable
, IDS_CAT_LIBS
, IDI_CAT_LIBS
);
859 AddCategory(hRootItemAvailable
, IDS_CAT_THEMES
, IDI_CAT_THEMES
);
860 AddCategory(hRootItemAvailable
, IDS_CAT_OTHER
, IDI_CAT_OTHER
);
862 m_TreeView
->SetImageList();
863 m_TreeView
->Expand(hRootItemInstalled
, TVE_EXPAND
);
864 m_TreeView
->Expand(hRootItemAvailable
, TVE_EXPAND
);
865 m_TreeView
->SelectItem(hRootItemAvailable
);
868 BOOL
CreateStatusBar()
870 m_StatusBar
= new CUiWindow
<CStatusBar
>();
871 m_StatusBar
->m_VerticalAlignment
= UiAlign_RightBtm
;
872 m_StatusBar
->m_HorizontalAlignment
= UiAlign_Stretch
;
873 m_ClientPanel
->Children().Append(m_StatusBar
);
875 return m_StatusBar
->Create(m_hWnd
, (HMENU
) IDC_STATUSBAR
) != NULL
;
880 m_Toolbar
= new CMainToolbar();
881 m_Toolbar
->m_VerticalAlignment
= UiAlign_LeftTop
;
882 m_Toolbar
->m_HorizontalAlignment
= UiAlign_Stretch
;
883 m_ClientPanel
->Children().Append(m_Toolbar
);
885 return m_Toolbar
->Create(m_hWnd
) != NULL
;
888 BOOL
CreateTreeView()
890 m_TreeView
= new CSideTreeView();
891 m_TreeView
->m_VerticalAlignment
= UiAlign_Stretch
;
892 m_TreeView
->m_HorizontalAlignment
= UiAlign_Stretch
;
893 m_VSplitter
->First().Append(m_TreeView
);
895 return m_TreeView
->Create(m_hWnd
) != NULL
;
898 BOOL
CreateListView()
900 m_ListView
= new CAppsListView();
901 m_ListView
->m_VerticalAlignment
= UiAlign_Stretch
;
902 m_ListView
->m_HorizontalAlignment
= UiAlign_Stretch
;
903 m_HSplitter
->First().Append(m_ListView
);
905 hListView
= m_ListView
->Create(m_hWnd
);
906 return hListView
!= NULL
;
909 BOOL
CreateRichEdit()
911 m_RichEdit
= new CAppRichEdit();
912 m_RichEdit
->m_VerticalAlignment
= UiAlign_Stretch
;
913 m_RichEdit
->m_HorizontalAlignment
= UiAlign_Stretch
;
914 m_HSplitter
->Second().Append(m_RichEdit
);
916 return m_RichEdit
->Create(m_hWnd
) != NULL
;
919 BOOL
CreateVSplitter()
921 m_VSplitter
= new CUiSplitPanel();
922 m_VSplitter
->m_VerticalAlignment
= UiAlign_Stretch
;
923 m_VSplitter
->m_HorizontalAlignment
= UiAlign_Stretch
;
924 m_VSplitter
->m_DynamicFirst
= FALSE
;
925 m_VSplitter
->m_Horizontal
= FALSE
;
926 m_VSplitter
->m_MinFirst
= 0;
927 m_VSplitter
->m_MinSecond
= 320;
928 m_VSplitter
->m_Pos
= 240;
929 m_ClientPanel
->Children().Append(m_VSplitter
);
931 return m_VSplitter
->Create(m_hWnd
) != NULL
;
934 BOOL
CreateHSplitter()
936 m_HSplitter
= new CUiSplitPanel();
937 m_HSplitter
->m_VerticalAlignment
= UiAlign_Stretch
;
938 m_HSplitter
->m_HorizontalAlignment
= UiAlign_Stretch
;
939 m_HSplitter
->m_DynamicFirst
= TRUE
;
940 m_HSplitter
->m_Horizontal
= TRUE
;
941 m_HSplitter
->m_Pos
= INT_MAX
; //set INT_MAX to use lowest possible position (m_MinSecond)
942 m_HSplitter
->m_MinFirst
= 10;
943 m_HSplitter
->m_MinSecond
= 140;
944 m_VSplitter
->Second().Append(m_HSplitter
);
946 return m_HSplitter
->Create(m_hWnd
) != NULL
;
949 BOOL
CreateSearchBar()
951 m_SearchBar
= new CUiWindow
<CSearchBar
>();
952 m_SearchBar
->m_VerticalAlignment
= UiAlign_LeftTop
;
953 m_SearchBar
->m_HorizontalAlignment
= UiAlign_RightBtm
;
954 m_SearchBar
->m_Margin
.top
= 4;
955 m_SearchBar
->m_Margin
.right
= 6;
957 return m_SearchBar
->Create(m_Toolbar
->m_hWnd
) != NULL
;
965 m_ClientPanel
= new CUiPanel();
966 m_ClientPanel
->m_VerticalAlignment
= UiAlign_Stretch
;
967 m_ClientPanel
->m_HorizontalAlignment
= UiAlign_Stretch
;
970 b
= b
&& CreateStatusBar();
971 b
= b
&& CreateToolbar();
972 b
= b
&& CreateSearchBar();
973 b
= b
&& CreateVSplitter();
976 b
= b
&& CreateHSplitter();
977 b
= b
&& CreateTreeView();
980 b
= b
&& CreateListView();
981 b
= b
&& CreateRichEdit();
988 /* Size status bar */
989 m_StatusBar
->SendMessageW(WM_SIZE
, 0, 0);
992 m_Toolbar
->AutoSize();
994 ::GetWindowRect(m_Toolbar
->m_hWnd
, &rTop
);
995 ::GetWindowRect(m_StatusBar
->m_hWnd
, &rBottom
);
997 m_VSplitter
->m_Margin
.top
= rTop
.bottom
- rTop
.top
;
998 m_VSplitter
->m_Margin
.bottom
= rBottom
.bottom
- rBottom
.top
;
1010 InitApplicationsList();
1011 InitCategoriesList();
1014 UpdateStatusBarText();
1022 VOID
ShowAppInfo(INT Index
)
1024 if (IsInstalledEnum(SelectedEnumType
))
1027 Index
= m_ListView
->GetSelectionMark();
1029 PINSTALLED_INFO Info
= (PINSTALLED_INFO
) m_ListView
->GetItemData(Index
);
1031 m_RichEdit
->ShowInstalledAppInfo(Info
);
1033 else if (IsAvailableEnum(SelectedEnumType
))
1038 CAvailableApplicationInfo
* Info
= (CAvailableApplicationInfo
*) m_ListView
->GetItemData(Index
);
1040 m_RichEdit
->ShowAvailableAppInfo(Info
);
1044 VOID
OnSize(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1046 if (wParam
== SIZE_MINIMIZED
)
1049 /* Size status bar */
1050 m_StatusBar
->SendMessage(WM_SIZE
, 0, 0);
1053 m_Toolbar
->AutoSize();
1055 /* Automatically hide captions */
1056 DWORD dToolbarTreshold
= m_Toolbar
->GetMaxButtonsWidth();
1057 DWORD dSearchbarMargin
= (LOWORD(lParam
) - m_SearchBar
->m_Width
);
1059 if (dSearchbarMargin
> dToolbarTreshold
)
1061 m_Toolbar
->ShowButtonCaption();
1063 else if (dSearchbarMargin
< dToolbarTreshold
)
1065 m_Toolbar
->HideButtonCaption();
1068 RECT r
= {0, 0, LOWORD(lParam
), HIWORD(lParam
)};
1070 INT count
= m_ClientPanel
->CountSizableChildren();
1072 hdwp
= BeginDeferWindowPos(count
);
1075 hdwp
= m_ClientPanel
->OnParentSize(r
, hdwp
);
1078 EndDeferWindowPos(hdwp
);
1083 // TODO: Sub-layouts for children of children
1084 count
= m_SearchBar
->CountSizableChildren();
1085 hdwp
= BeginDeferWindowPos(count
);
1088 hdwp
= m_SearchBar
->OnParentSize(r
, hdwp
);
1091 EndDeferWindowPos(hdwp
);
1097 VOID
RemoveSelectedAppFromRegistry()
1099 PINSTALLED_INFO Info
;
1100 WCHAR szFullName
[MAX_PATH
] = L
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
1101 ATL::CStringW szMsgText
, szMsgTitle
;
1102 INT ItemIndex
= m_ListView
->GetNextItem(-1, LVNI_FOCUSED
);
1104 if (!IsInstalledEnum(SelectedEnumType
))
1107 Info
= reinterpret_cast<PINSTALLED_INFO
>(m_ListView
->GetItemData(ItemIndex
));
1108 if (!Info
|| !Info
->hSubKey
|| (ItemIndex
== -1))
1111 if (!szMsgText
.LoadStringW(IDS_APP_REG_REMOVE
) ||
1112 !szMsgTitle
.LoadStringW(IDS_INFORMATION
))
1115 if (MessageBoxW(szMsgText
, szMsgTitle
, MB_YESNO
| MB_ICONQUESTION
) == IDYES
)
1117 ATL::CStringW::CopyChars(szFullName
,
1119 Info
->szKeyName
.GetString(),
1120 MAX_PATH
- wcslen(szFullName
));
1122 if (RegDeleteKeyW(Info
->hRootKey
, szFullName
) == ERROR_SUCCESS
)
1124 m_ListView
->DeleteItem(ItemIndex
);
1128 if (!szMsgText
.LoadStringW(IDS_UNABLE_TO_REMOVE
))
1131 MessageBoxW(szMsgText
.GetString(), NULL
, MB_OK
| MB_ICONERROR
);
1135 BOOL
ProcessWindowMessage(HWND hwnd
, UINT Msg
, WPARAM wParam
, LPARAM lParam
, LRESULT
& theResult
, DWORD dwMapId
)
1141 if (!InitControls())
1142 ::PostMessageW(hwnd
, WM_CLOSE
, 0, 0);
1147 ShowWindow(SW_HIDE
);
1151 m_AvailableApps
.FreeCachedEntries();
1153 if (IsInstalledEnum(SelectedEnumType
))
1154 FreeInstalledAppList();
1156 delete m_ClientPanel
;
1163 OnCommand(wParam
, lParam
);
1168 LPNMHDR data
= (LPNMHDR
) lParam
;
1172 case TVN_SELCHANGED
:
1174 if (data
->hwndFrom
== m_TreeView
->m_hWnd
)
1176 switch (((LPNMTREEVIEW
) lParam
)->itemNew
.lParam
)
1179 UpdateApplicationsList(ENUM_ALL_INSTALLED
);
1182 case IDS_APPLICATIONS
:
1183 UpdateApplicationsList(ENUM_INSTALLED_APPLICATIONS
);
1187 UpdateApplicationsList(ENUM_UPDATES
);
1190 case IDS_AVAILABLEFORINST
:
1191 UpdateApplicationsList(ENUM_ALL_AVAILABLE
);
1195 UpdateApplicationsList(ENUM_CAT_AUDIO
);
1199 UpdateApplicationsList(ENUM_CAT_DEVEL
);
1202 case IDS_CAT_DRIVERS
:
1203 UpdateApplicationsList(ENUM_CAT_DRIVERS
);
1207 UpdateApplicationsList(ENUM_CAT_EDU
);
1210 case IDS_CAT_ENGINEER
:
1211 UpdateApplicationsList(ENUM_CAT_ENGINEER
);
1214 case IDS_CAT_FINANCE
:
1215 UpdateApplicationsList(ENUM_CAT_FINANCE
);
1219 UpdateApplicationsList(ENUM_CAT_GAMES
);
1222 case IDS_CAT_GRAPHICS
:
1223 UpdateApplicationsList(ENUM_CAT_GRAPHICS
);
1226 case IDS_CAT_INTERNET
:
1227 UpdateApplicationsList(ENUM_CAT_INTERNET
);
1231 UpdateApplicationsList(ENUM_CAT_LIBS
);
1234 case IDS_CAT_OFFICE
:
1235 UpdateApplicationsList(ENUM_CAT_OFFICE
);
1239 UpdateApplicationsList(ENUM_CAT_OTHER
);
1242 case IDS_CAT_SCIENCE
:
1243 UpdateApplicationsList(ENUM_CAT_SCIENCE
);
1247 UpdateApplicationsList(ENUM_CAT_TOOLS
);
1251 UpdateApplicationsList(ENUM_CAT_VIDEO
);
1254 case IDS_CAT_THEMES
:
1255 UpdateApplicationsList(ENUM_CAT_THEMES
);
1258 case IDS_SELECTEDFORINST
:
1259 UpdateApplicationsList(ENUM_CAT_SELECTED
);
1264 HMENU mainMenu
= ::GetMenu(hwnd
);
1265 HMENU lvwMenu
= ::GetMenu(m_ListView
->m_hWnd
);
1267 /* Disable/enable items based on treeview selection */
1268 if (IsSelectedNodeInstalled())
1270 EnableMenuItem(mainMenu
, ID_REGREMOVE
, MF_ENABLED
);
1271 EnableMenuItem(mainMenu
, ID_INSTALL
, MF_GRAYED
);
1272 EnableMenuItem(mainMenu
, ID_UNINSTALL
, MF_ENABLED
);
1273 EnableMenuItem(mainMenu
, ID_MODIFY
, MF_ENABLED
);
1275 EnableMenuItem(lvwMenu
, ID_REGREMOVE
, MF_ENABLED
);
1276 EnableMenuItem(lvwMenu
, ID_INSTALL
, MF_GRAYED
);
1277 EnableMenuItem(lvwMenu
, ID_UNINSTALL
, MF_ENABLED
);
1278 EnableMenuItem(lvwMenu
, ID_MODIFY
, MF_ENABLED
);
1280 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_REGREMOVE
, TRUE
);
1281 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_INSTALL
, FALSE
);
1282 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_UNINSTALL
, TRUE
);
1283 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_MODIFY
, TRUE
);
1287 EnableMenuItem(mainMenu
, ID_REGREMOVE
, MF_GRAYED
);
1288 EnableMenuItem(mainMenu
, ID_INSTALL
, MF_ENABLED
);
1289 EnableMenuItem(mainMenu
, ID_UNINSTALL
, MF_GRAYED
);
1290 EnableMenuItem(mainMenu
, ID_MODIFY
, MF_GRAYED
);
1292 EnableMenuItem(lvwMenu
, ID_REGREMOVE
, MF_GRAYED
);
1293 EnableMenuItem(lvwMenu
, ID_INSTALL
, MF_ENABLED
);
1294 EnableMenuItem(lvwMenu
, ID_UNINSTALL
, MF_GRAYED
);
1295 EnableMenuItem(lvwMenu
, ID_MODIFY
, MF_GRAYED
);
1297 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_REGREMOVE
, FALSE
);
1298 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_INSTALL
, TRUE
);
1299 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_UNINSTALL
, FALSE
);
1300 m_Toolbar
->SendMessageW(TB_ENABLEBUTTON
, ID_MODIFY
, FALSE
);
1305 case LVN_ITEMCHANGED
:
1307 LPNMLISTVIEW pnic
= (LPNMLISTVIEW
) lParam
;
1309 if (pnic
->hdr
.hwndFrom
== m_ListView
->m_hWnd
)
1311 /* Check if this is a valid item
1312 * (technically, it can be also an unselect) */
1313 INT ItemIndex
= pnic
->iItem
;
1314 if (ItemIndex
== -1 ||
1315 ItemIndex
>= ListView_GetItemCount(pnic
->hdr
.hwndFrom
))
1320 /* Check if the focus has been moved to another item */
1321 if ((pnic
->uChanged
& LVIF_STATE
) &&
1322 (pnic
->uNewState
& LVIS_FOCUSED
) &&
1323 !(pnic
->uOldState
& LVIS_FOCUSED
))
1325 ShowAppInfo(ItemIndex
);
1327 /* Check if the item is checked */
1328 if ((pnic
->uNewState
& LVIS_STATEIMAGEMASK
) && !bUpdating
)
1330 BOOL checked
= m_ListView
->GetCheckState(pnic
->iItem
);
1332 - preventing decremention below zero as a safeguard for ReactOS
1333 In ReactOS this action is triggered whenever user changes *selection*, but should be only when *checkbox* state toggled
1334 Maybe LVIS_STATEIMAGEMASK is set incorrectly
1339 : ((nSelectedApps
> 0)
1343 /* Update item's selection status */
1344 m_ListView
->SetSelected(pnic
->iItem
, checked
);
1346 UpdateStatusBarText();
1352 case LVN_COLUMNCLICK
:
1354 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
1356 m_ListView
->ColumnClick(pnmv
);
1362 if (data
->hwndFrom
== m_ListView
->m_hWnd
&& ((LPNMLISTVIEW
) lParam
)->iItem
!= -1)
1371 if (data
->hwndFrom
== m_ListView
->m_hWnd
&& ((LPNMLISTVIEW
) lParam
)->iItem
!= -1)
1373 /* this won't do anything if the program is already installed */
1374 SendMessageW(hwnd
, WM_COMMAND
, ID_INSTALL
, 0);
1381 if (data
->hwndFrom
== m_ListView
->m_hWnd
&& ((LPNMLISTVIEW
) lParam
)->iItem
!= -1)
1383 ShowPopupMenu(m_ListView
->m_hWnd
, 0, ID_INSTALL
);
1389 OnLink((ENLINK
*) lParam
);
1392 case TTN_GETDISPINFO
:
1393 m_Toolbar
->OnGetDispInfo((LPTOOLTIPTEXT
) lParam
);
1400 OnSize(hwnd
, wParam
, lParam
);
1405 LPRECT pRect
= (LPRECT
) lParam
;
1407 if (pRect
->right
- pRect
->left
< 565)
1408 pRect
->right
= pRect
->left
+ 565;
1410 if (pRect
->bottom
- pRect
->top
< 300)
1411 pRect
->bottom
= pRect
->top
+ 300;
1416 case WM_SYSCOLORCHANGE
:
1418 /* Forward WM_SYSCOLORCHANGE to common controls */
1419 m_ListView
->SendMessageW(WM_SYSCOLORCHANGE
, 0, 0);
1420 m_TreeView
->SendMessageW(WM_SYSCOLORCHANGE
, 0, 0);
1421 m_Toolbar
->SendMessageW(WM_SYSCOLORCHANGE
, 0, 0);
1422 m_ListView
->SendMessageW(EM_SETBKGNDCOLOR
, 0, GetSysColor(COLOR_BTNFACE
));
1427 if (wParam
== SEARCH_TIMER_ID
)
1429 ::KillTimer(hwnd
, SEARCH_TIMER_ID
);
1431 UpdateApplicationsList(-1);
1439 virtual VOID
OnLink(ENLINK
*Link
)
1446 if (pLink
) HeapFree(GetProcessHeap(), 0, pLink
);
1448 pLink
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0,
1449 (max(Link
->chrg
.cpMin
, Link
->chrg
.cpMax
) -
1450 min(Link
->chrg
.cpMin
, Link
->chrg
.cpMax
) + 1) * sizeof(WCHAR
));
1453 /* TODO: Error message */
1457 m_RichEdit
->SendMessageW(EM_SETSEL
, Link
->chrg
.cpMin
, Link
->chrg
.cpMax
);
1458 m_RichEdit
->SendMessageW(EM_GETSELTEXT
, 0, (LPARAM
) pLink
);
1460 ShowPopupMenu(m_RichEdit
->m_hWnd
, IDR_LINKMENU
, -1);
1466 BOOL
IsSelectedNodeInstalled()
1468 HTREEITEM hSelectedItem
= m_TreeView
->GetSelection();
1471 tItem
.mask
= TVIF_PARAM
| TVIF_HANDLE
;
1472 tItem
.hItem
= hSelectedItem
;
1473 m_TreeView
->GetItem(&tItem
);
1474 switch (tItem
.lParam
)
1477 case IDS_APPLICATIONS
:
1485 VOID
OnCommand(WPARAM wParam
, LPARAM lParam
)
1487 WORD wCommand
= LOWORD(wParam
);
1489 if (lParam
== (LPARAM
) m_SearchBar
->m_hWnd
)
1491 ATL::CStringW szBuf
;
1493 switch (HIWORD(wParam
))
1497 ATL::CStringW szWndText
;
1499 szBuf
.LoadStringW(IDS_SEARCH_TEXT
);
1500 m_SearchBar
->GetWindowTextW(szWndText
);
1501 if (szBuf
== szWndText
)
1503 bSearchEnabled
= FALSE
;
1504 m_SearchBar
->SetWindowTextW(L
"");
1511 m_SearchBar
->GetWindowTextW(szBuf
);
1512 if (szBuf
.IsEmpty())
1514 szBuf
.LoadStringW(IDS_SEARCH_TEXT
);
1515 bSearchEnabled
= FALSE
;
1516 m_SearchBar
->SetWindowTextW(szBuf
.GetString());
1523 ATL::CStringW szWndText
;
1525 if (!bSearchEnabled
)
1527 bSearchEnabled
= TRUE
;
1531 szBuf
.LoadStringW(IDS_SEARCH_TEXT
);
1532 m_SearchBar
->GetWindowTextW(szWndText
);
1533 if (szBuf
== szWndText
)
1535 szSearchPattern
.Empty();
1539 szSearchPattern
= szWndText
;
1543 SystemParametersInfoW(SPI_GETMENUSHOWDELAY
, 0, &dwDelay
, 0);
1544 SetTimer(SEARCH_TIMER_ID
, dwDelay
);
1555 ShellExecuteW(m_hWnd
, L
"open", pLink
, NULL
, NULL
, SW_SHOWNOACTIVATE
);
1556 HeapFree(GetProcessHeap(), 0, pLink
);
1560 CopyTextToClipboard(pLink
);
1561 HeapFree(GetProcessHeap(), 0, pLink
);
1565 CreateSettingsDlg(m_hWnd
);
1569 PostMessageW(WM_CLOSE
, 0, 0);
1573 ::SetFocus(m_SearchBar
->m_hWnd
);
1577 if (IsAvailableEnum(SelectedEnumType
))
1579 if (nSelectedApps
> 0)
1581 DownloadListOfApplications(m_AvailableApps
.GetSelected(), FALSE
);
1582 UpdateApplicationsList(-1);
1583 m_ListView
->SetSelected(-1, FALSE
);
1585 else if (DownloadApplication(m_ListView
->GetSelectedData(), FALSE
))
1587 UpdateApplicationsList(-1);
1594 if (UninstallApplication(-1, FALSE
))
1595 UpdateApplicationsList(-1);
1599 if (UninstallApplication(-1, TRUE
))
1600 UpdateApplicationsList(-1);
1604 RemoveSelectedAppFromRegistry();
1608 UpdateApplicationsList(-1);
1612 CAvailableApps::ForceUpdateAppsDB();
1613 UpdateApplicationsList(-1);
1617 MessageBoxW(L
"Help not implemented yet", NULL
, MB_OK
);
1625 m_ListView
->CheckAll();
1630 VOID
FreeInstalledAppList()
1632 INT Count
= m_ListView
->GetItemCount() - 1;
1633 PINSTALLED_INFO Info
;
1637 Info
= (PINSTALLED_INFO
) ListViewGetlParam(Count
);
1640 RegCloseKey(Info
->hSubKey
);
1647 static BOOL
SearchPatternMatch(LPCWSTR szHaystack
, LPCWSTR szNeedle
)
1651 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
1652 return StrStrIW(szHaystack
, szNeedle
) != NULL
;
1655 BOOL CALLBACK
EnumInstalledAppProc(INT ItemIndex
, ATL::CStringW
&m_szName
, PINSTALLED_INFO Info
)
1657 PINSTALLED_INFO ItemInfo
;
1658 ATL::CStringW szText
;
1661 if (!SearchPatternMatch(m_szName
.GetString(), szSearchPattern
))
1663 RegCloseKey(Info
->hSubKey
);
1667 ItemInfo
= new INSTALLED_INFO(*Info
);
1670 RegCloseKey(Info
->hSubKey
);
1674 Index
= m_ListView
->AddItem(ItemIndex
, 0, m_szName
.GetString(), (LPARAM
) ItemInfo
);
1676 /* Get version info */
1677 ItemInfo
->GetApplicationString(L
"DisplayVersion", szText
);
1678 m_ListView
->SetItemText(Index
, 1, szText
.GetString());
1681 ItemInfo
->GetApplicationString(L
"Comments", szText
);
1682 m_ListView
->SetItemText(Index
, 2, szText
.GetString());
1687 BOOL
EnumAvailableAppProc(CAvailableApplicationInfo
* Info
, LPCWSTR szFolderPath
)
1692 HIMAGELIST hImageListView
= ListView_GetImageList(hListView
, LVSIL_SMALL
);
1694 if (!SearchPatternMatch(Info
->m_szName
.GetString(), szSearchPattern
) &&
1695 !SearchPatternMatch(Info
->m_szDesc
.GetString(), szSearchPattern
))
1700 /* Load icon from file */
1701 ATL::CStringW szIconPath
;
1702 szIconPath
.Format(L
"%lsicons\\%ls.ico", szFolderPath
, Info
->m_szName
.GetString());
1703 hIcon
= (HICON
) LoadImageW(NULL
,
1704 szIconPath
.GetString(),
1710 if (!hIcon
|| GetLastError() != ERROR_SUCCESS
)
1712 /* Load default icon */
1713 hIcon
= (HICON
) LoadIconW(hInst
, MAKEINTRESOURCEW(IDI_MAIN
));
1716 Index
= ImageList_AddIcon(hImageListView
, hIcon
);
1719 Index
= m_ListView
->AddItem(Info
->m_Category
, Index
, Info
->m_szName
.GetString(), (LPARAM
) Info
);
1720 m_ListView
->SetImageList(hImageListView
, LVSIL_SMALL
);
1721 m_ListView
->SetItemText(Index
, 1, Info
->m_szVersion
.GetString());
1722 m_ListView
->SetItemText(Index
, 2, Info
->m_szDesc
.GetString());
1723 m_ListView
->SetCheckState(Index
, Info
->m_IsSelected
);
1728 static BOOL CALLBACK
s_EnumInstalledAppProc(INT ItemIndex
, ATL::CStringW
&m_szName
, PINSTALLED_INFO Info
, PVOID param
)
1730 CMainWindow
* pThis
= (CMainWindow
*)param
;
1731 return pThis
->EnumInstalledAppProc(ItemIndex
, m_szName
, Info
);
1734 static BOOL CALLBACK
s_EnumAvailableAppProc(CAvailableApplicationInfo
* Info
, LPCWSTR szFolderPath
, PVOID param
)
1736 CMainWindow
* pThis
= (CMainWindow
*)param
;
1737 return pThis
->EnumAvailableAppProc(Info
, szFolderPath
);
1740 VOID
UpdateStatusBarText()
1744 ATL::CStringW szBuffer
;
1746 szBuffer
.Format(IDS_APPS_COUNT
, m_ListView
->GetItemCount(), nSelectedApps
);
1747 m_StatusBar
->SetText(szBuffer
);
1751 VOID
UpdateApplicationsList(INT EnumType
)
1753 ATL::CStringW szBuffer1
, szBuffer2
;
1754 HIMAGELIST hImageListView
;
1755 BOOL bWasInInstalled
= IsInstalledEnum(SelectedEnumType
);
1758 m_ListView
->SetRedraw(FALSE
);
1762 EnumType
= SelectedEnumType
;
1765 //if previous one was INSTALLED purge the list
1766 //TODO: make the Installed category a separate class to avoid doing this
1767 if (bWasInInstalled
)
1769 FreeInstalledAppList();
1772 m_ListView
->DeleteAllItems();
1774 // Create new ImageList
1775 hImageListView
= ImageList_Create(LISTVIEW_ICON_SIZE
,
1777 GetSystemColorDepth() | ILC_MASK
,
1779 HIMAGELIST hImageListBuf
= m_ListView
->SetImageList(hImageListView
, LVSIL_SMALL
);
1782 ImageList_Destroy(hImageListBuf
);
1785 if (IsInstalledEnum(EnumType
))
1787 if (!bWasInInstalled
)
1789 m_ListView
->SetCheckboxesVisible(FALSE
);
1792 HICON hIcon
= (HICON
) LoadIconW(hInst
, MAKEINTRESOURCEW(IDI_MAIN
));
1793 ImageList_AddIcon(hImageListView
, hIcon
);
1796 // Enum installed applications and updates
1797 EnumInstalledApplications(EnumType
, TRUE
, s_EnumInstalledAppProc
, this);
1798 EnumInstalledApplications(EnumType
, FALSE
, s_EnumInstalledAppProc
, this);
1800 else if (IsAvailableEnum(EnumType
))
1802 if (bWasInInstalled
)
1804 m_ListView
->SetCheckboxesVisible(TRUE
);
1807 // Enum available applications
1808 m_AvailableApps
.Enum(EnumType
, s_EnumAvailableAppProc
, this);
1811 SelectedEnumType
= EnumType
;
1812 UpdateStatusBarText();
1813 m_RichEdit
->SetWelcomeText();
1815 // Set automatic column width for program names if the list is not empty
1816 if (m_ListView
->GetItemCount() > 0)
1818 ListView_SetColumnWidth(m_ListView
->GetWindow(), 0, LVSCW_AUTOSIZE
);
1822 m_ListView
->SetRedraw(TRUE
);
1826 static ATL::CWndClassInfo
& GetWndClassInfo()
1828 DWORD csStyle
= CS_VREDRAW
| CS_HREDRAW
;
1829 static ATL::CWndClassInfo wc
=
1838 LoadIconW(_AtlBaseModule
.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN
)),
1839 LoadCursorW(NULL
, IDC_ARROW
),
1840 (HBRUSH
) (COLOR_BTNFACE
+ 1),
1841 MAKEINTRESOURCEW(IDR_MAINMENU
),
1845 NULL
, NULL
, IDC_ARROW
, TRUE
, 0, _T("")
1852 ATL::CStringW szWindowName
;
1853 szWindowName
.LoadStringW(IDS_APPTITLE
);
1856 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Left
: CW_USEDEFAULT
),
1857 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Top
: CW_USEDEFAULT
),
1858 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Width
: 680),
1859 (SettingsInfo
.bSaveWndPos
? SettingsInfo
.Height
: 450)
1864 return CWindowImpl::Create(NULL
, r
, szWindowName
.GetString(), WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, WS_EX_WINDOWEDGE
);
1867 CStatusBar
* GetStatusBar()
1872 CAppsListView
* GetListView()
1877 CRichEdit
* GetRichEdit()
1882 CAvailableApps
* GetAvailableApps()
1884 return &m_AvailableApps
;
1889 CMainWindow
* g_MainWindow
;
1891 HWND
CreateMainWindow()
1893 g_MainWindow
= new CMainWindow();
1894 return g_MainWindow
->Create();
1897 DWORD_PTR
ListViewGetlParam(INT item
)
1901 item
= g_MainWindow
->GetListView()->GetSelectionMark();
1903 return g_MainWindow
->GetListView()->GetItemData(item
);
1906 VOID
SetStatusBarText(LPCWSTR szText
)
1908 g_MainWindow
->GetStatusBar()->SetText(szText
);
1911 INT
ListViewAddItem(INT ItemIndex
, INT IconIndex
, LPWSTR lpName
, LPARAM lParam
)
1913 return g_MainWindow
->GetListView()->AddItem(ItemIndex
, IconIndex
, lpName
, lParam
);
1916 VOID
NewRichEditText(LPCWSTR szText
, DWORD flags
)
1918 g_MainWindow
->GetRichEdit()->SetText(szText
, flags
);
1921 VOID
InsertRichEditText(LPCWSTR szText
, DWORD flags
)
1923 g_MainWindow
->GetRichEdit()->InsertText(szText
, flags
);
1926 CAvailableApps
* GetAvailableApps()
1928 return g_MainWindow
->GetAvailableApps();
1931 // ATL version of functions above
1932 VOID
SetStatusBarText(const ATL::CStringW
& szText
)
1934 SetStatusBarText(szText
.GetString());
1937 INT
ListViewAddItem(INT ItemIndex
, INT IconIndex
, const ATL::CStringW
& Name
, LPARAM lParam
)
1939 return ListViewAddItem(ItemIndex
, IconIndex
, const_cast<LPWSTR
>(Name
.GetString()), lParam
);
1942 VOID
NewRichEditText(const ATL::CStringW
& szText
, DWORD flags
)
1944 NewRichEditText(szText
.GetString(), flags
);
1947 VOID
InsertRichEditText(const ATL::CStringW
& szText
, DWORD flags
)
1949 InsertRichEditText(szText
.GetString(), flags
);
1952 VOID
ShowMainWindow(INT nShowCmd
)
1957 hMainWnd
= CreateMainWindow();
1961 /* Maximize it if we must */
1962 ShowWindow(hMainWnd
, ((SettingsInfo
.bSaveWndPos
&& SettingsInfo
.Maximized
) ? SW_MAXIMIZE
: nShowCmd
));
1963 UpdateWindow(hMainWnd
);
1965 /* Load the menu hotkeys */
1966 KeyBrd
= LoadAcceleratorsW(NULL
, MAKEINTRESOURCEW(HOTKEYS
));
1969 while (GetMessageW(&Msg
, NULL
, 0, 0))
1971 if (!TranslateAcceleratorW(hMainWnd
, KeyBrd
, &Msg
))
1973 TranslateMessage(&Msg
);
1974 DispatchMessageW(&Msg
);