mirror of
https://github.com/reactos/reactos.git
synced 2025-04-30 19:19:00 +00:00

- Replaced some functions with their Wide versions - Generalized `GetInstalledVersion` function so it could accept NULL - Minor cleanup svn path=/branches/GSoC_2017/rapps/; revision=75324
1377 lines
40 KiB
C++
1377 lines
40 KiB
C++
/* PROJECT: ReactOS CE Applications Manager
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* AUTHORS: David Quintana <gigaherz@gmail.com>
|
|
* Alexander Shaposhnikov <chaez.san@gmail.com>
|
|
*/
|
|
|
|
#include "rapps.h"
|
|
|
|
#include <shlobj_undoc.h>
|
|
#include <shlguid_undoc.h>
|
|
|
|
#include <atlbase.h>
|
|
#include <atlcom.h>
|
|
#include <atlwin.h>
|
|
#include <wininet.h>
|
|
#include <shellutils.h>
|
|
|
|
#include <rosctrls.h>
|
|
|
|
#include "rosui.h"
|
|
#include "crichedit.h"
|
|
|
|
#define SEARCH_TIMER_ID 'SR'
|
|
|
|
HWND hListView = NULL;
|
|
|
|
class CMainToolbar :
|
|
public CUiWindow< CToolbar<> >
|
|
{
|
|
#define TOOLBAR_HEIGHT 24
|
|
|
|
WCHAR szInstallBtn[MAX_STR_LEN];
|
|
WCHAR szUninstallBtn[MAX_STR_LEN];
|
|
WCHAR szModifyBtn[MAX_STR_LEN];
|
|
|
|
VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
|
|
{
|
|
HICON hImage;
|
|
|
|
if (!(hImage = (HICON) LoadImageW(hInst,
|
|
MAKEINTRESOURCE(ImageIndex),
|
|
IMAGE_ICON,
|
|
TOOLBAR_HEIGHT,
|
|
TOOLBAR_HEIGHT,
|
|
0)))
|
|
{
|
|
/* TODO: Error message */
|
|
}
|
|
|
|
ImageList_AddIcon(hImageList, hImage);
|
|
DeleteObject(hImage);
|
|
}
|
|
|
|
HIMAGELIST InitImageList(VOID)
|
|
{
|
|
HIMAGELIST hImageList;
|
|
|
|
/* Create the toolbar icon image list */
|
|
hImageList = ImageList_Create(TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CXSMICON),
|
|
TOOLBAR_HEIGHT,//GetSystemMetrics(SM_CYSMICON),
|
|
ILC_MASK | GetSystemColorDepth(),
|
|
1,
|
|
1);
|
|
if (!hImageList)
|
|
{
|
|
/* TODO: Error message */
|
|
return NULL;
|
|
}
|
|
|
|
AddImageToImageList(hImageList, IDI_INSTALL);
|
|
AddImageToImageList(hImageList, IDI_UNINSTALL);
|
|
AddImageToImageList(hImageList, IDI_MODIFY);
|
|
AddImageToImageList(hImageList, IDI_REFRESH);
|
|
AddImageToImageList(hImageList, IDI_UPDATE_DB);
|
|
AddImageToImageList(hImageList, IDI_SETTINGS);
|
|
AddImageToImageList(hImageList, IDI_EXIT);
|
|
|
|
return hImageList;
|
|
}
|
|
|
|
public:
|
|
VOID OnGetDispInfo(LPTOOLTIPTEXT lpttt)
|
|
{
|
|
UINT idButton = (UINT) lpttt->hdr.idFrom;
|
|
|
|
switch (idButton)
|
|
{
|
|
case ID_EXIT:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT);
|
|
break;
|
|
|
|
case ID_INSTALL:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_INSTALL);
|
|
break;
|
|
|
|
case ID_UNINSTALL:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL);
|
|
break;
|
|
|
|
case ID_MODIFY:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_MODIFY);
|
|
break;
|
|
|
|
case ID_SETTINGS:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SETTINGS);
|
|
break;
|
|
|
|
case ID_REFRESH:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
|
|
break;
|
|
|
|
case ID_RESETDB:
|
|
lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE_DB);
|
|
break;
|
|
}
|
|
}
|
|
|
|
HWND Create(HWND hwndParent)
|
|
{
|
|
HIMAGELIST hImageList;
|
|
|
|
// buttons
|
|
static TBBUTTON Buttons[] =
|
|
{ /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
|
|
{ 0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szInstallBtn },
|
|
{ 1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szUninstallBtn },
|
|
{ 2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, (INT_PTR) szModifyBtn },
|
|
{ 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
|
|
{ 3, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
|
|
{ 4, ID_RESETDB, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, 0},
|
|
{ 5, 0, TBSTATE_ENABLED, BTNS_SEP, { 0 }, 0, 0 },
|
|
{ 5, ID_SETTINGS, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 },
|
|
{ 6, ID_EXIT, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, { 0 }, 0, 0 }
|
|
};
|
|
|
|
LoadStringW(hInst, IDS_INSTALL, szInstallBtn, _countof(szInstallBtn));
|
|
LoadStringW(hInst, IDS_UNINSTALL, szUninstallBtn, _countof(szUninstallBtn));
|
|
LoadStringW(hInst, IDS_MODIFY, szModifyBtn, _countof(szModifyBtn));
|
|
|
|
m_hWnd = CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL,
|
|
WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST,
|
|
0, 0, 0, 0,
|
|
hwndParent,
|
|
0, hInst, NULL);
|
|
|
|
if (!m_hWnd)
|
|
{
|
|
/* TODO: Show error message */
|
|
return FALSE;
|
|
}
|
|
|
|
SendMessageW(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
|
|
SetButtonStructSize();
|
|
|
|
hImageList = InitImageList();
|
|
|
|
if (!hImageList)
|
|
{
|
|
/* TODO: Show error message */
|
|
return FALSE;
|
|
}
|
|
|
|
ImageList_Destroy((HIMAGELIST) SetImageList(hImageList));
|
|
|
|
AddButtons(_countof(Buttons), Buttons);
|
|
|
|
return m_hWnd;
|
|
}
|
|
};
|
|
|
|
class CAppsListView :
|
|
public CUiWindow<CListView>
|
|
{
|
|
struct SortContext
|
|
{
|
|
CAppsListView * lvw;
|
|
int iSubItem;
|
|
};
|
|
|
|
public:
|
|
BOOL bAscending;
|
|
|
|
CAppsListView()
|
|
{
|
|
bAscending = TRUE;
|
|
}
|
|
|
|
VOID ColumnClick(LPNMLISTVIEW pnmv)
|
|
{
|
|
SortContext ctx = {this, pnmv->iSubItem};
|
|
|
|
SortItems(s_CompareFunc, &ctx);
|
|
|
|
bAscending = !bAscending;
|
|
}
|
|
|
|
PVOID GetLParam(INT Index)
|
|
{
|
|
INT ItemIndex;
|
|
LVITEM Item;
|
|
|
|
if (Index == -1)
|
|
{
|
|
ItemIndex = (INT) SendMessage(LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
|
|
if (ItemIndex == -1)
|
|
return NULL;
|
|
}
|
|
else
|
|
{
|
|
ItemIndex = Index;
|
|
}
|
|
|
|
ZeroMemory(&Item, sizeof(Item));
|
|
|
|
Item.mask = LVIF_PARAM;
|
|
Item.iItem = ItemIndex;
|
|
if (!GetItem(&Item))
|
|
return NULL;
|
|
|
|
return (PVOID) Item.lParam;
|
|
}
|
|
|
|
BOOL AddColumn(INT Index, ATL::CStringW& Text, INT Width, INT Format)
|
|
{
|
|
BOOL result = AddColumn(Index, Text.GetBuffer(), Width, Format);
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOL AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format)
|
|
{
|
|
LV_COLUMN Column;
|
|
|
|
ZeroMemory(&Column, sizeof(Column));
|
|
|
|
Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
|
Column.iSubItem = Index;
|
|
Column.pszText = (LPTSTR) lpText;
|
|
Column.cx = Width;
|
|
Column.fmt = Format;
|
|
|
|
return (InsertColumn(Index, &Column) == -1) ? FALSE : TRUE;
|
|
}
|
|
|
|
INT AddItem(INT ItemIndex, INT IconIndex, LPWSTR lpText, LPARAM lParam)
|
|
{
|
|
LV_ITEMW Item;
|
|
|
|
ZeroMemory(&Item, sizeof(Item));
|
|
|
|
Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE | LVIF_IMAGE;
|
|
Item.pszText = lpText;
|
|
Item.lParam = lParam;
|
|
Item.iItem = ItemIndex;
|
|
Item.iImage = IconIndex;
|
|
|
|
return InsertItem(&Item);
|
|
}
|
|
|
|
static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
|
{
|
|
SortContext * ctx = ((SortContext*) lParamSort);
|
|
return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem);
|
|
}
|
|
|
|
INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
|
|
{
|
|
ATL::CStringW Item1, Item2;
|
|
LVFINDINFOW IndexInfo;
|
|
INT Index;
|
|
|
|
IndexInfo.flags = LVFI_PARAM;
|
|
|
|
IndexInfo.lParam = lParam1;
|
|
Index = FindItem(-1, &IndexInfo);
|
|
GetItemText(Index, iSubItem, Item1.GetBuffer(MAX_STR_LEN), MAX_STR_LEN);
|
|
Item1.ReleaseBuffer();
|
|
|
|
IndexInfo.lParam = lParam2;
|
|
Index = FindItem(-1, &IndexInfo);
|
|
GetItemText(Index, iSubItem, Item2.GetBuffer(MAX_STR_LEN), MAX_STR_LEN);
|
|
Item2.ReleaseBuffer();
|
|
|
|
if (bAscending)
|
|
return Item2 == Item1;
|
|
else
|
|
return Item1 == Item2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
HWND Create(HWND hwndParent)
|
|
{
|
|
RECT r = {205, 28, 465, 250};
|
|
DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS;
|
|
HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0);
|
|
|
|
HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE, menu);
|
|
|
|
if (hwnd)
|
|
SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
|
|
|
|
return hwnd;
|
|
}
|
|
|
|
};
|
|
|
|
class CSideTreeView :
|
|
public CUiWindow<CTreeView>
|
|
{
|
|
HIMAGELIST hImageTreeView = ImageList_Create(TREEVIEW_ICON_SIZE, TREEVIEW_ICON_SIZE,
|
|
GetSystemColorDepth() | ILC_MASK,
|
|
0, 1);
|
|
|
|
public:
|
|
HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam)
|
|
{
|
|
HTREEITEM result = CUiWindow<CTreeView>::AddItem(hParent, Text.GetBuffer(), Image, SelectedImage, lParam);
|
|
Text.ReleaseBuffer();
|
|
return result;
|
|
}
|
|
|
|
HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
|
|
{
|
|
ATL::CStringW szText;
|
|
INT Index;
|
|
HICON hIcon;
|
|
|
|
hIcon = (HICON) LoadImage(hInst,
|
|
MAKEINTRESOURCE(IconIndex),
|
|
IMAGE_ICON,
|
|
TREEVIEW_ICON_SIZE,
|
|
TREEVIEW_ICON_SIZE,
|
|
LR_CREATEDIBSECTION);
|
|
if (hIcon)
|
|
{
|
|
Index = ImageList_AddIcon(hImageTreeView, hIcon);
|
|
DestroyIcon(hIcon);
|
|
}
|
|
|
|
szText.LoadStringW(hInst, TextIndex);
|
|
return AddItem(hRootItem, szText, Index, Index, TextIndex);
|
|
}
|
|
|
|
HIMAGELIST SetImageList()
|
|
{
|
|
return CUiWindow<CTreeView>::SetImageList(hImageTreeView, TVSIL_NORMAL);
|
|
}
|
|
|
|
VOID DestroyImageList()
|
|
{
|
|
if (hImageTreeView)
|
|
ImageList_Destroy(hImageTreeView);
|
|
}
|
|
|
|
~CSideTreeView()
|
|
{
|
|
DestroyImageList();
|
|
CUiWindow<CTreeView>::~CUiWindow();
|
|
}
|
|
};
|
|
|
|
class CSearchBar :
|
|
public CWindow
|
|
{
|
|
public:
|
|
VOID SetText(LPCWSTR lpszText)
|
|
{
|
|
SendMessageW(SB_SETTEXT, SBT_NOBORDERS, (LPARAM) lpszText);
|
|
}
|
|
|
|
HWND Create(HWND hwndParent)
|
|
{
|
|
ATL::CStringW szBuf;
|
|
m_hWnd = CreateWindowExW(WS_EX_CLIENTEDGE, L"Edit", NULL,
|
|
WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL,
|
|
0, 0, 200, 22,
|
|
hwndParent, (HMENU) NULL,
|
|
hInst, 0);
|
|
|
|
SendMessageW(WM_SETFONT, (WPARAM) GetStockObject(DEFAULT_GUI_FONT), 0);
|
|
szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
|
|
SetWindowTextW(szBuf);
|
|
return m_hWnd;
|
|
}
|
|
|
|
};
|
|
|
|
class CMainWindow :
|
|
public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
|
|
{
|
|
CUiPanel * m_ClientPanel;
|
|
CUiSplitPanel * m_VSplitter;
|
|
CUiSplitPanel * m_HSplitter;
|
|
|
|
CMainToolbar * m_Toolbar;
|
|
CAppsListView * m_ListView;
|
|
|
|
CSideTreeView * m_TreeView;
|
|
CUiWindow<CStatusBar> * m_StatusBar;
|
|
CUiWindow<CRichEdit> * m_RichEdit;
|
|
|
|
CUiWindow<CSearchBar> * m_SearchBar;
|
|
|
|
LPWSTR pLink;
|
|
|
|
BOOL SearchEnabled;
|
|
|
|
public:
|
|
CMainWindow() :
|
|
m_ClientPanel(NULL),
|
|
pLink(NULL),
|
|
SearchEnabled(TRUE)
|
|
{
|
|
}
|
|
|
|
private:
|
|
|
|
VOID InitApplicationsList(VOID)
|
|
{
|
|
ATL::CStringW szText;
|
|
|
|
/* Add columns to ListView */
|
|
szText.LoadStringW(hInst, IDS_APP_NAME);
|
|
m_ListView->AddColumn(0, szText, 200, LVCFMT_LEFT);
|
|
|
|
szText.LoadStringW(hInst, IDS_APP_INST_VERSION);
|
|
m_ListView->AddColumn(1, szText, 90, LVCFMT_RIGHT);
|
|
|
|
szText.LoadStringW(hInst, IDS_APP_DESCRIPTION);
|
|
m_ListView->AddColumn(3, szText, 250, LVCFMT_LEFT);
|
|
|
|
UpdateApplicationsList(ENUM_ALL_COMPONENTS);
|
|
}
|
|
|
|
HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex)
|
|
{
|
|
return m_TreeView->AddCategory(hRootItem, TextIndex, IconIndex);
|
|
}
|
|
|
|
VOID InitCategoriesList(VOID)
|
|
{
|
|
HTREEITEM hRootItem;
|
|
|
|
hRootItem = AddCategory(TVI_ROOT, IDS_AVAILABLEFORINST, IDI_CATEGORY);
|
|
AddCategory(hRootItem, IDS_CAT_AUDIO, IDI_CAT_AUDIO);
|
|
AddCategory(hRootItem, IDS_CAT_VIDEO, IDI_CAT_VIDEO);
|
|
AddCategory(hRootItem, IDS_CAT_GRAPHICS, IDI_CAT_GRAPHICS);
|
|
AddCategory(hRootItem, IDS_CAT_GAMES, IDI_CAT_GAMES);
|
|
AddCategory(hRootItem, IDS_CAT_INTERNET, IDI_CAT_INTERNET);
|
|
AddCategory(hRootItem, IDS_CAT_OFFICE, IDI_CAT_OFFICE);
|
|
AddCategory(hRootItem, IDS_CAT_DEVEL, IDI_CAT_DEVEL);
|
|
AddCategory(hRootItem, IDS_CAT_EDU, IDI_CAT_EDU);
|
|
AddCategory(hRootItem, IDS_CAT_ENGINEER, IDI_CAT_ENGINEER);
|
|
AddCategory(hRootItem, IDS_CAT_FINANCE, IDI_CAT_FINANCE);
|
|
AddCategory(hRootItem, IDS_CAT_SCIENCE, IDI_CAT_SCIENCE);
|
|
AddCategory(hRootItem, IDS_CAT_TOOLS, IDI_CAT_TOOLS);
|
|
AddCategory(hRootItem, IDS_CAT_DRIVERS, IDI_CAT_DRIVERS);
|
|
AddCategory(hRootItem, IDS_CAT_LIBS, IDI_CAT_LIBS);
|
|
AddCategory(hRootItem, IDS_CAT_OTHER, IDI_CAT_OTHER);
|
|
|
|
m_TreeView->SetImageList();
|
|
m_TreeView->Expand(hRootItem, TVE_EXPAND);
|
|
m_TreeView->SelectItem(hRootItem);
|
|
}
|
|
|
|
BOOL CreateStatusBar()
|
|
{
|
|
m_StatusBar = new CUiWindow<CStatusBar>();
|
|
m_StatusBar->m_VerticalAlignment = UiAlign_RightBtm;
|
|
m_StatusBar->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_ClientPanel->Children().Append(m_StatusBar);
|
|
|
|
return m_StatusBar->Create(m_hWnd, (HMENU) IDC_STATUSBAR) != NULL;
|
|
}
|
|
|
|
BOOL CreateToolbar()
|
|
{
|
|
m_Toolbar = new CMainToolbar();
|
|
m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop;
|
|
m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_ClientPanel->Children().Append(m_Toolbar);
|
|
|
|
return m_Toolbar->Create(m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateTreeView()
|
|
{
|
|
m_TreeView = new CSideTreeView();
|
|
m_TreeView->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_TreeView->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_VSplitter->First().Append(m_TreeView);
|
|
|
|
return m_TreeView->Create(m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateListView()
|
|
{
|
|
m_ListView = new CAppsListView();
|
|
m_ListView->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_ListView->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_HSplitter->First().Append(m_ListView);
|
|
|
|
hListView = m_ListView->Create(m_hWnd);
|
|
return hListView != NULL;
|
|
}
|
|
|
|
BOOL CreateRichEdit()
|
|
{
|
|
m_RichEdit = new CUiWindow<CRichEdit>();
|
|
m_RichEdit->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_RichEdit->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_HSplitter->Second().Append(m_RichEdit);
|
|
|
|
return m_RichEdit->Create(m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateVSplitter()
|
|
{
|
|
m_VSplitter = new CUiSplitPanel();
|
|
m_VSplitter->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_VSplitter->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_VSplitter->m_DynamicFirst = FALSE;
|
|
m_VSplitter->m_Horizontal = FALSE;
|
|
m_VSplitter->m_MinFirst = 240;
|
|
m_VSplitter->m_MinSecond = 300;
|
|
m_ClientPanel->Children().Append(m_VSplitter);
|
|
|
|
return m_VSplitter->Create(m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateHSplitter()
|
|
{
|
|
m_HSplitter = new CUiSplitPanel();
|
|
m_HSplitter->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_HSplitter->m_HorizontalAlignment = UiAlign_Stretch;
|
|
m_HSplitter->m_DynamicFirst = TRUE;
|
|
m_HSplitter->m_Horizontal = TRUE;
|
|
m_HSplitter->m_Pos = 32768;
|
|
m_HSplitter->m_MinFirst = 300;
|
|
m_HSplitter->m_MinSecond = 80;
|
|
m_VSplitter->Second().Append(m_HSplitter);
|
|
|
|
return m_HSplitter->Create(m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateSearchBar(VOID)
|
|
{
|
|
m_SearchBar = new CUiWindow<CSearchBar>();
|
|
m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
|
|
m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm;
|
|
m_SearchBar->m_Margin.top = 6;
|
|
m_SearchBar->m_Margin.right = 6;
|
|
|
|
return m_SearchBar->Create(m_Toolbar->m_hWnd) != NULL;
|
|
}
|
|
|
|
BOOL CreateLayout()
|
|
{
|
|
bool b = TRUE;
|
|
|
|
m_ClientPanel = new CUiPanel();
|
|
m_ClientPanel->m_VerticalAlignment = UiAlign_Stretch;
|
|
m_ClientPanel->m_HorizontalAlignment = UiAlign_Stretch;
|
|
|
|
// Top level
|
|
b = b && CreateStatusBar();
|
|
b = b && CreateToolbar();
|
|
b = b && CreateSearchBar();
|
|
b = b && CreateVSplitter();
|
|
|
|
// Inside V Splitter
|
|
b = b && CreateHSplitter();
|
|
b = b && CreateTreeView();
|
|
|
|
// Inside H Splitter
|
|
b = b && CreateListView();
|
|
b = b && CreateRichEdit();
|
|
|
|
if (b)
|
|
{
|
|
RECT rTop;
|
|
RECT rBottom;
|
|
|
|
/* Size status bar */
|
|
m_StatusBar->SendMessage(WM_SIZE, 0, 0);
|
|
|
|
/* Size tool bar */
|
|
m_Toolbar->AutoSize();
|
|
|
|
::GetWindowRect(m_Toolbar->m_hWnd, &rTop);
|
|
::GetWindowRect(m_StatusBar->m_hWnd, &rBottom);
|
|
|
|
m_VSplitter->m_Margin.top = rTop.bottom - rTop.top;
|
|
m_VSplitter->m_Margin.bottom = rBottom.bottom - rBottom.top;
|
|
}
|
|
|
|
return b;
|
|
}
|
|
|
|
BOOL InitControls()
|
|
{
|
|
if (CreateLayout())
|
|
{
|
|
ATL::CStringW szBuffer1, szBuffer2;
|
|
|
|
InitApplicationsList();
|
|
|
|
InitCategoriesList();
|
|
|
|
szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
|
|
szBuffer1.Format(szBuffer2, m_ListView->GetItemCount());
|
|
|
|
m_StatusBar->SetText(szBuffer1);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
/* Size status bar */
|
|
m_StatusBar->SendMessage(WM_SIZE, 0, 0);
|
|
|
|
/* Size tool bar */
|
|
m_Toolbar->AutoSize();
|
|
|
|
RECT r = {0, 0, LOWORD(lParam), HIWORD(lParam)};
|
|
HDWP hdwp = NULL;
|
|
int count = m_ClientPanel->CountSizableChildren();
|
|
|
|
hdwp = BeginDeferWindowPos(count);
|
|
if (hdwp)
|
|
{
|
|
hdwp = m_ClientPanel->OnParentSize(r, hdwp);
|
|
}
|
|
if (hdwp)
|
|
{
|
|
EndDeferWindowPos(hdwp);
|
|
}
|
|
|
|
// TODO: Sub-layouts for children of children
|
|
count = m_SearchBar->CountSizableChildren();
|
|
hdwp = BeginDeferWindowPos(count);
|
|
if (hdwp)
|
|
{
|
|
hdwp = m_SearchBar->OnParentSize(r, hdwp);
|
|
}
|
|
if (hdwp)
|
|
{
|
|
EndDeferWindowPos(hdwp);
|
|
}
|
|
}
|
|
|
|
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
|
|
{
|
|
theResult = 0;
|
|
switch (Msg)
|
|
{
|
|
case WM_CREATE:
|
|
if (!InitControls())
|
|
::PostMessage(hwnd, WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
ShowWindow(SW_HIDE);
|
|
SaveSettings(hwnd);
|
|
|
|
FreeLogs();
|
|
|
|
FreeCachedAvailableEntries();
|
|
|
|
if (IS_INSTALLED_ENUM(SelectedEnumType))
|
|
FreeInstalledAppList();
|
|
|
|
delete m_ClientPanel;
|
|
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
}
|
|
|
|
case WM_COMMAND:
|
|
OnCommand(wParam, lParam);
|
|
break;
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR data = (LPNMHDR) lParam;
|
|
|
|
switch (data->code)
|
|
{
|
|
case TVN_SELCHANGED:
|
|
{
|
|
if (data->hwndFrom == m_TreeView->m_hWnd)
|
|
{
|
|
switch (((LPNMTREEVIEW) lParam)->itemNew.lParam)
|
|
{
|
|
case IDS_INSTALLED:
|
|
UpdateApplicationsList(ENUM_ALL_COMPONENTS);
|
|
break;
|
|
|
|
case IDS_APPLICATIONS:
|
|
UpdateApplicationsList(ENUM_APPLICATIONS);
|
|
break;
|
|
|
|
case IDS_UPDATES:
|
|
UpdateApplicationsList(ENUM_UPDATES);
|
|
break;
|
|
|
|
case IDS_AVAILABLEFORINST:
|
|
UpdateApplicationsList(ENUM_ALL_AVAILABLE);
|
|
break;
|
|
|
|
case IDS_CAT_AUDIO:
|
|
UpdateApplicationsList(ENUM_CAT_AUDIO);
|
|
break;
|
|
|
|
case IDS_CAT_DEVEL:
|
|
UpdateApplicationsList(ENUM_CAT_DEVEL);
|
|
break;
|
|
|
|
case IDS_CAT_DRIVERS:
|
|
UpdateApplicationsList(ENUM_CAT_DRIVERS);
|
|
break;
|
|
|
|
case IDS_CAT_EDU:
|
|
UpdateApplicationsList(ENUM_CAT_EDU);
|
|
break;
|
|
|
|
case IDS_CAT_ENGINEER:
|
|
UpdateApplicationsList(ENUM_CAT_ENGINEER);
|
|
break;
|
|
|
|
case IDS_CAT_FINANCE:
|
|
UpdateApplicationsList(ENUM_CAT_FINANCE);
|
|
break;
|
|
|
|
case IDS_CAT_GAMES:
|
|
UpdateApplicationsList(ENUM_CAT_GAMES);
|
|
break;
|
|
|
|
case IDS_CAT_GRAPHICS:
|
|
UpdateApplicationsList(ENUM_CAT_GRAPHICS);
|
|
break;
|
|
|
|
case IDS_CAT_INTERNET:
|
|
UpdateApplicationsList(ENUM_CAT_INTERNET);
|
|
break;
|
|
|
|
case IDS_CAT_LIBS:
|
|
UpdateApplicationsList(ENUM_CAT_LIBS);
|
|
break;
|
|
|
|
case IDS_CAT_OFFICE:
|
|
UpdateApplicationsList(ENUM_CAT_OFFICE);
|
|
break;
|
|
|
|
case IDS_CAT_OTHER:
|
|
UpdateApplicationsList(ENUM_CAT_OTHER);
|
|
break;
|
|
|
|
case IDS_CAT_SCIENCE:
|
|
UpdateApplicationsList(ENUM_CAT_SCIENCE);
|
|
break;
|
|
|
|
case IDS_CAT_TOOLS:
|
|
UpdateApplicationsList(ENUM_CAT_TOOLS);
|
|
break;
|
|
|
|
case IDS_CAT_VIDEO:
|
|
UpdateApplicationsList(ENUM_CAT_VIDEO);
|
|
break;
|
|
}
|
|
}
|
|
|
|
HMENU mainMenu = ::GetMenu(hwnd);
|
|
HMENU lvwMenu = ::GetMenu(m_ListView->m_hWnd);
|
|
|
|
/* Disable/enable items based on treeview selection */
|
|
if (IsSelectedNodeInstalled())
|
|
{
|
|
EnableMenuItem(mainMenu, ID_REGREMOVE, MF_ENABLED);
|
|
EnableMenuItem(mainMenu, ID_INSTALL, MF_GRAYED);
|
|
EnableMenuItem(mainMenu, ID_UNINSTALL, MF_ENABLED);
|
|
EnableMenuItem(mainMenu, ID_MODIFY, MF_ENABLED);
|
|
|
|
EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_ENABLED);
|
|
EnableMenuItem(lvwMenu, ID_INSTALL, MF_GRAYED);
|
|
EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_ENABLED);
|
|
EnableMenuItem(lvwMenu, ID_MODIFY, MF_ENABLED);
|
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, TRUE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
|
|
}
|
|
else
|
|
{
|
|
EnableMenuItem(mainMenu, ID_REGREMOVE, MF_GRAYED);
|
|
EnableMenuItem(mainMenu, ID_INSTALL, MF_ENABLED);
|
|
EnableMenuItem(mainMenu, ID_UNINSTALL, MF_GRAYED);
|
|
EnableMenuItem(mainMenu, ID_MODIFY, MF_GRAYED);
|
|
|
|
EnableMenuItem(lvwMenu, ID_REGREMOVE, MF_GRAYED);
|
|
EnableMenuItem(lvwMenu, ID_INSTALL, MF_ENABLED);
|
|
EnableMenuItem(lvwMenu, ID_UNINSTALL, MF_GRAYED);
|
|
EnableMenuItem(lvwMenu, ID_MODIFY, MF_GRAYED);
|
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_REGREMOVE, FALSE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, TRUE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, FALSE);
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, FALSE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LVN_ITEMCHANGED:
|
|
{
|
|
LPNMLISTVIEW pnic = (LPNMLISTVIEW) lParam;
|
|
|
|
if (pnic->hdr.hwndFrom == m_ListView->m_hWnd)
|
|
{
|
|
/* Check if this is a valid item
|
|
* (technically, it can be also an unselect) */
|
|
INT ItemIndex = pnic->iItem;
|
|
if (ItemIndex == -1 ||
|
|
ItemIndex >= ListView_GetItemCount(pnic->hdr.hwndFrom))
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* Check if the focus has been moved to another item */
|
|
if ((pnic->uChanged & LVIF_STATE) &&
|
|
(pnic->uNewState & LVIS_FOCUSED) &&
|
|
!(pnic->uOldState & LVIS_FOCUSED))
|
|
{
|
|
if (IS_INSTALLED_ENUM(SelectedEnumType))
|
|
ShowInstalledAppInfo(ItemIndex);
|
|
if (IS_AVAILABLE_ENUM(SelectedEnumType))
|
|
ShowAvailableAppInfo(ItemIndex);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LVN_COLUMNCLICK:
|
|
{
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
|
|
|
|
m_ListView->ColumnClick(pnmv);
|
|
}
|
|
break;
|
|
|
|
case NM_CLICK:
|
|
{
|
|
if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
|
|
{
|
|
if (IS_INSTALLED_ENUM(SelectedEnumType))
|
|
ShowInstalledAppInfo(-1);
|
|
if (IS_AVAILABLE_ENUM(SelectedEnumType))
|
|
ShowAvailableAppInfo(-1);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_DBLCLK:
|
|
{
|
|
if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
|
|
{
|
|
/* this won't do anything if the program is already installed */
|
|
SendMessage(hwnd, WM_COMMAND, ID_INSTALL, 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case NM_RCLICK:
|
|
{
|
|
if (data->hwndFrom == m_ListView->m_hWnd && ((LPNMLISTVIEW) lParam)->iItem != -1)
|
|
{
|
|
ShowPopupMenu(m_ListView->m_hWnd, 0, ID_INSTALL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_LINK:
|
|
OnLink((ENLINK*) lParam);
|
|
break;
|
|
|
|
case TTN_GETDISPINFO:
|
|
m_Toolbar->OnGetDispInfo((LPTOOLTIPTEXT) lParam);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
OnSize(hwnd, wParam, lParam);
|
|
break;
|
|
|
|
case WM_SIZING:
|
|
{
|
|
LPRECT pRect = (LPRECT) lParam;
|
|
|
|
if (pRect->right - pRect->left < 565)
|
|
pRect->right = pRect->left + 565;
|
|
|
|
if (pRect->bottom - pRect->top < 300)
|
|
pRect->bottom = pRect->top + 300;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
{
|
|
/* Forward WM_SYSCOLORCHANGE to common controls */
|
|
m_ListView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
|
|
m_TreeView->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
|
|
m_Toolbar->SendMessageW(WM_SYSCOLORCHANGE, 0, 0);
|
|
m_ListView->SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
|
|
}
|
|
break;
|
|
|
|
case WM_TIMER:
|
|
if (wParam == SEARCH_TIMER_ID)
|
|
{
|
|
::KillTimer(hwnd, SEARCH_TIMER_ID);
|
|
UpdateApplicationsList(-1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
virtual VOID OnLink(ENLINK *Link)
|
|
{
|
|
switch (Link->msg)
|
|
{
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONUP:
|
|
{
|
|
if (pLink) HeapFree(GetProcessHeap(), 0, pLink);
|
|
|
|
pLink = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
|
|
(max(Link->chrg.cpMin, Link->chrg.cpMax) -
|
|
min(Link->chrg.cpMin, Link->chrg.cpMax) + 1) * sizeof(WCHAR));
|
|
if (!pLink)
|
|
{
|
|
/* TODO: Error message */
|
|
return;
|
|
}
|
|
|
|
m_RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
|
|
m_RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM) pLink);
|
|
|
|
ShowPopupMenu(m_RichEdit->m_hWnd, IDR_LINKMENU, -1);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
BOOL IsSelectedNodeInstalled(void)
|
|
{
|
|
HTREEITEM hSelectedItem = m_TreeView->GetSelection();
|
|
TV_ITEM tItem;
|
|
|
|
tItem.mask = TVIF_PARAM | TVIF_HANDLE;
|
|
tItem.hItem = hSelectedItem;
|
|
m_TreeView->GetItem(&tItem);
|
|
switch (tItem.lParam)
|
|
{
|
|
case IDS_INSTALLED:
|
|
case IDS_APPLICATIONS:
|
|
case IDS_UPDATES:
|
|
return TRUE;
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
VOID OnCommand(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WORD wCommand = LOWORD(wParam);
|
|
|
|
if (lParam == (LPARAM) m_SearchBar->m_hWnd)
|
|
{
|
|
ATL::CStringW szBuf;
|
|
|
|
switch (HIWORD(wParam))
|
|
{
|
|
case EN_SETFOCUS:
|
|
{
|
|
ATL::CStringW szWndText;
|
|
|
|
szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
|
|
m_SearchBar->GetWindowTextW(szWndText);
|
|
if (szBuf == szWndText)
|
|
{
|
|
SearchEnabled = FALSE;
|
|
m_SearchBar->SetWindowTextW(L"");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_KILLFOCUS:
|
|
{
|
|
m_SearchBar->GetWindowTextW(szBuf);
|
|
if (szBuf.IsEmpty())
|
|
{
|
|
szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
|
|
SearchEnabled = FALSE;
|
|
m_SearchBar->SetWindowTextW(szBuf.GetString());
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_CHANGE:
|
|
{
|
|
ATL::CStringW szWndText;
|
|
|
|
if (!SearchEnabled)
|
|
{
|
|
SearchEnabled = TRUE;
|
|
break;
|
|
}
|
|
|
|
szBuf.LoadStringW(hInst, IDS_SEARCH_TEXT);
|
|
m_SearchBar->GetWindowTextW(szWndText);
|
|
if (szBuf == szWndText)
|
|
{
|
|
szSearchPattern.Empty();
|
|
}
|
|
else
|
|
{
|
|
szSearchPattern = szWndText;
|
|
}
|
|
|
|
DWORD dwDelay;
|
|
SystemParametersInfoW(SPI_GETMENUSHOWDELAY, 0, &dwDelay, 0);
|
|
SetTimer(SEARCH_TIMER_ID, dwDelay);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
switch (wCommand)
|
|
{
|
|
case ID_OPEN_LINK:
|
|
ShellExecuteW(m_hWnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
|
|
HeapFree(GetProcessHeap(), 0, pLink);
|
|
break;
|
|
|
|
case ID_COPY_LINK:
|
|
CopyTextToClipboard(pLink);
|
|
HeapFree(GetProcessHeap(), 0, pLink);
|
|
break;
|
|
|
|
case ID_SETTINGS:
|
|
CreateSettingsDlg(m_hWnd);
|
|
break;
|
|
|
|
case ID_EXIT:
|
|
PostMessageW(WM_CLOSE, 0, 0);
|
|
break;
|
|
|
|
case ID_INSTALL:
|
|
if (DownloadApplication(-1))
|
|
/* TODO: Implement install dialog
|
|
* if (InstallApplication(-1))
|
|
*/
|
|
UpdateApplicationsList(-1);
|
|
break;
|
|
|
|
case ID_UNINSTALL:
|
|
if (UninstallApplication(-1, FALSE))
|
|
UpdateApplicationsList(-1);
|
|
break;
|
|
|
|
case ID_MODIFY:
|
|
if (UninstallApplication(-1, TRUE))
|
|
UpdateApplicationsList(-1);
|
|
break;
|
|
|
|
case ID_REGREMOVE:
|
|
RemoveAppFromRegistry(-1);
|
|
break;
|
|
|
|
case ID_REFRESH:
|
|
UpdateApplicationsList(-1);
|
|
break;
|
|
|
|
case ID_RESETDB:
|
|
UpdateAppsDB();
|
|
UpdateApplicationsList(-1);
|
|
break;
|
|
|
|
case ID_HELP:
|
|
MessageBoxW(L"Help not implemented yet", NULL, MB_OK);
|
|
break;
|
|
|
|
case ID_ABOUT:
|
|
ShowAboutDialog();
|
|
break;
|
|
}
|
|
}
|
|
|
|
VOID FreeInstalledAppList(VOID)
|
|
{
|
|
INT Count = ListView_GetItemCount(hListView) - 1;
|
|
PINSTALLED_INFO Info;
|
|
|
|
while (Count >= 0)
|
|
{
|
|
Info = (PINSTALLED_INFO) ListViewGetlParam(Count);
|
|
if (Info)
|
|
{
|
|
RegCloseKey(Info->hSubKey);
|
|
delete Info;
|
|
}
|
|
Count--;
|
|
}
|
|
}
|
|
|
|
static BOOL SearchPatternMatch(PCWSTR szHaystack, PCWSTR szNeedle)
|
|
{
|
|
if (!*szNeedle)
|
|
return TRUE;
|
|
/* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
|
|
return StrStrIW(szHaystack, szNeedle) != NULL;
|
|
}
|
|
|
|
static BOOL CALLBACK s_EnumInstalledAppProc(INT ItemIndex, LPWSTR lpName, PINSTALLED_INFO Info)
|
|
{
|
|
PINSTALLED_INFO ItemInfo;
|
|
ATL::CStringW szText;
|
|
INT Index;
|
|
|
|
if (!SearchPatternMatch(lpName, szSearchPattern))
|
|
{
|
|
RegCloseKey(Info->hSubKey);
|
|
return TRUE;
|
|
}
|
|
|
|
ItemInfo = (PINSTALLED_INFO) HeapAlloc(GetProcessHeap(), 0, sizeof(INSTALLED_INFO));
|
|
if (!ItemInfo)
|
|
{
|
|
RegCloseKey(Info->hSubKey);
|
|
return FALSE;
|
|
}
|
|
|
|
RtlCopyMemory(ItemInfo, Info, sizeof(INSTALLED_INFO));
|
|
|
|
Index = ListViewAddItem(ItemIndex, 0, lpName, (LPARAM) ItemInfo);
|
|
|
|
/* Get version info */
|
|
GetApplicationString(ItemInfo->hSubKey, L"DisplayVersion", szText);
|
|
ListView_SetItemText(hListView, Index, 1, szText.GetBuffer());
|
|
szText.ReleaseBuffer();
|
|
|
|
/* Get comments */
|
|
GetApplicationString(ItemInfo->hSubKey, L"Comments", szText);
|
|
ListView_SetItemText(hListView, Index, 2, szText.GetBuffer());
|
|
szText.ReleaseBuffer();
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL CALLBACK s_EnumAvailableAppProc(PAPPLICATION_INFO Info)
|
|
{
|
|
INT Index;
|
|
HICON hIcon = NULL;
|
|
ATL::CStringW szIconPath;
|
|
HIMAGELIST hImageListView = ListView_GetImageList(hListView, LVSIL_SMALL);
|
|
|
|
if (!SearchPatternMatch(Info->szName, szSearchPattern) &&
|
|
!SearchPatternMatch(Info->szDesc, szSearchPattern))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
if (GetStorageDirectory(szIconPath))
|
|
{
|
|
/* Load icon from file */
|
|
szIconPath += L"\\rapps\\icons\\" + Info->szName + L".ico";
|
|
hIcon = (HICON) LoadImageW(NULL,
|
|
szIconPath.GetString(),
|
|
IMAGE_ICON,
|
|
LISTVIEW_ICON_SIZE,
|
|
LISTVIEW_ICON_SIZE,
|
|
LR_LOADFROMFILE);
|
|
}
|
|
|
|
if (!hIcon)
|
|
{
|
|
/* Load default icon */
|
|
hIcon = (HICON) LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
|
|
}
|
|
Index = ImageList_AddIcon(hImageListView, hIcon);
|
|
DestroyIcon(hIcon);
|
|
|
|
Index = ListViewAddItem(Info->Category, Index, Info->szName, (LPARAM) Info);
|
|
hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
|
|
|
|
ListView_SetItemText(hListView, Index, 1, Info->szVersion.GetBuffer());
|
|
Info->szVersion.ReleaseBuffer();
|
|
|
|
ListView_SetItemText(hListView, Index, 2, Info->szDesc.GetBuffer());
|
|
Info->szDesc.ReleaseBuffer();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID UpdateApplicationsList(INT EnumType)
|
|
{
|
|
ATL::CStringW szBuffer1, szBuffer2;
|
|
HIMAGELIST hImageListView = NULL;
|
|
|
|
m_ListView->SendMessageW(WM_SETREDRAW, FALSE, 0);
|
|
|
|
if (EnumType < 0) EnumType = SelectedEnumType;
|
|
|
|
if (IS_INSTALLED_ENUM(SelectedEnumType))
|
|
FreeInstalledAppList();
|
|
|
|
(VOID) ListView_DeleteAllItems(hListView);
|
|
/* Create new ImageList */
|
|
hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE,
|
|
LISTVIEW_ICON_SIZE,
|
|
GetSystemColorDepth() | ILC_MASK,
|
|
0, 1);
|
|
hImageListView = ListView_SetImageList(hListView, hImageListView, LVSIL_SMALL);
|
|
|
|
if (hImageListView)
|
|
ImageList_Destroy(hImageListView);
|
|
|
|
if (IS_AVAILABLE_ENUM(EnumType))
|
|
{
|
|
/* Enum available applications */
|
|
EnumAvailableApplications(EnumType, s_EnumAvailableAppProc);
|
|
}
|
|
|
|
SelectedEnumType = EnumType;
|
|
|
|
szBuffer2.LoadStringW(hInst, IDS_APPS_COUNT);
|
|
szBuffer1.Format(szBuffer2, ListView_GetItemCount(hListView));
|
|
SetStatusBarText(szBuffer1);
|
|
|
|
SetWelcomeText();
|
|
|
|
/* set automatic column width for program names if the list is not empty */
|
|
if (ListView_GetItemCount(hListView) > 0)
|
|
ListView_SetColumnWidth(hListView, 0, LVSCW_AUTOSIZE);
|
|
|
|
SendMessageW(hListView, WM_SETREDRAW, TRUE, 0);
|
|
}
|
|
|
|
public:
|
|
static ATL::CWndClassInfo& GetWndClassInfo()
|
|
{
|
|
DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
|
|
static ATL::CWndClassInfo wc =
|
|
{
|
|
{
|
|
sizeof(WNDCLASSEX),
|
|
csStyle,
|
|
StartWindowProc,
|
|
0,
|
|
0,
|
|
NULL,
|
|
LoadIconW(_AtlBaseModule.GetModuleInstance(), MAKEINTRESOURCEW(IDI_MAIN)),
|
|
LoadCursorW(NULL, IDC_ARROW),
|
|
(HBRUSH) (COLOR_BTNFACE + 1),
|
|
MAKEINTRESOURCEW(IDR_MAINMENU),
|
|
L"RAppsWnd",
|
|
NULL
|
|
},
|
|
NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
|
|
};
|
|
return wc;
|
|
}
|
|
|
|
HWND Create()
|
|
{
|
|
ATL::CStringW szWindowName;
|
|
szWindowName.LoadStringW(hInst, IDS_APPTITLE);
|
|
|
|
RECT r = {
|
|
(SettingsInfo.bSaveWndPos ? SettingsInfo.Left : CW_USEDEFAULT),
|
|
(SettingsInfo.bSaveWndPos ? SettingsInfo.Top : CW_USEDEFAULT),
|
|
(SettingsInfo.bSaveWndPos ? SettingsInfo.Width : 680),
|
|
(SettingsInfo.bSaveWndPos ? SettingsInfo.Height : 450)
|
|
};
|
|
r.right += r.left;
|
|
r.bottom += r.top;
|
|
|
|
return CWindowImpl::Create(NULL, r, szWindowName.GetString(), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, WS_EX_WINDOWEDGE);
|
|
}
|
|
|
|
CStatusBar * GetStatusBar()
|
|
{
|
|
return m_StatusBar;
|
|
}
|
|
|
|
CAppsListView * GetListView()
|
|
{
|
|
return m_ListView;
|
|
}
|
|
|
|
CRichEdit * GetRichEdit()
|
|
{
|
|
return m_RichEdit;
|
|
}
|
|
};
|
|
|
|
CMainWindow * g_MainWindow;
|
|
|
|
HWND CreateMainWindow()
|
|
{
|
|
g_MainWindow = new CMainWindow();
|
|
return g_MainWindow->Create();
|
|
}
|
|
|
|
DWORD_PTR ListViewGetlParam(INT item)
|
|
{
|
|
if (item < 0)
|
|
{
|
|
item = g_MainWindow->GetListView()->GetSelectionMark();
|
|
}
|
|
return g_MainWindow->GetListView()->GetItemData(item);
|
|
}
|
|
|
|
VOID SetStatusBarText(LPCWSTR szText)
|
|
{
|
|
g_MainWindow->GetStatusBar()->SetText(szText);
|
|
}
|
|
|
|
INT ListViewAddItem(INT ItemIndex, INT IconIndex, LPWSTR lpName, LPARAM lParam)
|
|
{
|
|
return g_MainWindow->GetListView()->AddItem(ItemIndex, IconIndex, lpName, lParam);
|
|
}
|
|
|
|
VOID NewRichEditText(LPCWSTR szText, DWORD flags)
|
|
{
|
|
g_MainWindow->GetRichEdit()->SetText(szText, flags);
|
|
}
|
|
|
|
VOID InsertRichEditText(LPCWSTR szText, DWORD flags)
|
|
{
|
|
g_MainWindow->GetRichEdit()->InsertText(szText, flags);
|
|
}
|
|
|
|
/* ATL version of functions */
|
|
VOID SetStatusBarText(const ATL::CStringW& szText)
|
|
{
|
|
SetStatusBarText(szText.GetString());
|
|
}
|
|
|
|
INT ListViewAddItem(INT ItemIndex, INT IconIndex, ATL::CStringW & Name, LPARAM lParam)
|
|
{
|
|
INT result = ListViewAddItem(ItemIndex, IconIndex, Name.GetBuffer(), lParam);
|
|
Name.ReleaseBuffer();
|
|
return result;
|
|
}
|
|
|
|
VOID NewRichEditText(const ATL::CStringW& szText, DWORD flags)
|
|
{
|
|
NewRichEditText(szText.GetString(), flags);
|
|
}
|
|
|
|
VOID InsertRichEditText(const ATL::CStringW& szText, DWORD flags)
|
|
{
|
|
InsertRichEditText(szText.GetString(), flags);
|
|
}
|
|
|