2020-07-24 08:07:43 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Applications Manager
|
|
|
|
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
|
|
|
* PURPOSE: Application view class and other classes used by it
|
2023-02-20 18:30:02 +00:00
|
|
|
* COPYRIGHT: Copyright 2020 He Yang (1160386205@qq.com)
|
|
|
|
* Copyright 2022,2023 Mark Jansen <mark.jansen@reactos.org>
|
2020-07-24 08:07:43 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "rapps.h"
|
|
|
|
#include "appview.h"
|
|
|
|
#include "gui.h"
|
2020-07-29 10:50:57 +00:00
|
|
|
#include <windowsx.h>
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
using namespace Gdiplus;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
// **** CMainToolbar ****
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CMainToolbar::AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
HICON hImage;
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (!(hImage =
|
|
|
|
(HICON)LoadImageW(hInst, MAKEINTRESOURCE(ImageIndex), IMAGE_ICON, m_iToolbarHeight, m_iToolbarHeight, 0)))
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
return;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ImageList_AddIcon(hImageList, hImage);
|
|
|
|
DeleteObject(hImage);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HIMAGELIST
|
|
|
|
CMainToolbar::InitImageList()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
HIMAGELIST hImageList;
|
|
|
|
|
|
|
|
/* Create the toolbar icon image list */
|
2023-02-20 18:30:02 +00:00
|
|
|
hImageList = ImageList_Create(m_iToolbarHeight, m_iToolbarHeight, ILC_MASK | GetSystemColorDepth(), 1, 1);
|
2020-07-29 10:50:57 +00:00
|
|
|
if (!hImageList)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
AddImageToImageList(hImageList, IDI_INSTALL);
|
|
|
|
AddImageToImageList(hImageList, IDI_UNINSTALL);
|
|
|
|
AddImageToImageList(hImageList, IDI_MODIFY);
|
|
|
|
AddImageToImageList(hImageList, IDI_CHECK_ALL);
|
|
|
|
AddImageToImageList(hImageList, IDI_REFRESH);
|
|
|
|
AddImageToImageList(hImageList, IDI_UPDATE_DB);
|
|
|
|
AddImageToImageList(hImageList, IDI_SETTINGS);
|
|
|
|
AddImageToImageList(hImageList, IDI_EXIT);
|
|
|
|
|
|
|
|
return hImageList;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
CMainToolbar::CMainToolbar() : m_iToolbarHeight(24), m_dButtonsWidthMax(0)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CMainToolbar::OnGetDispInfo(LPTOOLTIPTEXT lpttt)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
UINT idButton = (UINT)lpttt->hdr.idFrom;
|
|
|
|
|
|
|
|
switch (idButton)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_EXIT:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_EXIT);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_INSTALL:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_INSTALL);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_UNINSTALL:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_MODIFY:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_MODIFY);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_SETTINGS:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SETTINGS);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_REFRESH:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_REFRESH);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_RESETDB:
|
|
|
|
lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE_DB);
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CMainToolbar::Create(HWND hwndParent)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-07-07 23:02:10 +00:00
|
|
|
CStringW szInstallBtn;
|
|
|
|
CStringW szUninstallBtn;
|
|
|
|
CStringW szModifyBtn;
|
|
|
|
CStringW szSelectAllBtn;
|
|
|
|
CStringW szRefreshBtn;
|
|
|
|
CStringW szUpdateDbBtn;
|
|
|
|
|
|
|
|
/* Load tooltip strings */
|
|
|
|
szInstallBtn.LoadStringW(IDS_TOOLTIP_INSTALL);
|
|
|
|
szUninstallBtn.LoadStringW(IDS_TOOLTIP_UNINSTALL);
|
|
|
|
szModifyBtn.LoadStringW(IDS_TOOLTIP_MODIFY);
|
|
|
|
szSelectAllBtn.LoadStringW(IDS_TOOLTIP_SELECT_ALL);
|
|
|
|
szRefreshBtn.LoadStringW(IDS_TOOLTIP_REFRESH);
|
|
|
|
szUpdateDbBtn.LoadStringW(IDS_TOOLTIP_UPDATE_DB);
|
|
|
|
|
2020-07-29 10:50:57 +00:00
|
|
|
/* Create buttons */
|
2023-02-20 18:30:02 +00:00
|
|
|
TBBUTTON Buttons[] = {
|
|
|
|
/* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
|
2023-07-07 23:02:10 +00:00
|
|
|
{0, ID_INSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szInstallBtn.GetString()},
|
|
|
|
{1, ID_UNINSTALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szUninstallBtn.GetString()},
|
|
|
|
{2, ID_MODIFY, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szModifyBtn.GetString()},
|
|
|
|
{3, ID_CHECK_ALL, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szSelectAllBtn.GetString()},
|
2023-02-20 18:30:02 +00:00
|
|
|
{-1, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
|
2023-07-07 23:02:10 +00:00
|
|
|
{4, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szRefreshBtn.GetString()},
|
|
|
|
{5, ID_RESETDB, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_AUTOSIZE, {0}, 0, (INT_PTR)szUpdateDbBtn.GetString()}};
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
m_hWnd = CreateWindowExW(
|
|
|
|
0, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | TBSTYLE_LIST, 0, 0, 0, 0,
|
|
|
|
hwndParent, 0, hInst, NULL);
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
if (!m_hWnd)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
SendMessageW(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS);
|
|
|
|
SetButtonStructSize();
|
|
|
|
|
|
|
|
/* Set image list */
|
|
|
|
HIMAGELIST hImageList = InitImageList();
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (hImageList)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
ImageList_Destroy(SetImageList(hImageList));
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
AddButtons(_countof(Buttons), Buttons);
|
|
|
|
|
|
|
|
/* Remember ideal width to use as a max width of buttons */
|
|
|
|
SIZE size;
|
|
|
|
GetIdealSize(FALSE, &size);
|
|
|
|
m_dButtonsWidthMax = size.cx;
|
|
|
|
|
|
|
|
return m_hWnd;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CMainToolbar::HideButtonCaption()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
DWORD dCurrentExStyle = (DWORD)SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0);
|
|
|
|
SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle | TBSTYLE_EX_MIXEDBUTTONS);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CMainToolbar::ShowButtonCaption()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
DWORD dCurrentExStyle = (DWORD)SendMessageW(TB_GETEXTENDEDSTYLE, 0, 0);
|
|
|
|
SendMessageW(TB_SETEXTENDEDSTYLE, 0, dCurrentExStyle & ~TBSTYLE_EX_MIXEDBUTTONS);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
DWORD
|
|
|
|
CMainToolbar::GetMaxButtonsWidth() const
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
return m_dButtonsWidthMax;
|
|
|
|
}
|
|
|
|
// **** CMainToolbar ****
|
|
|
|
|
|
|
|
// **** CSearchBar ****
|
|
|
|
|
|
|
|
CSearchBar::CSearchBar() : m_Width(180), m_Height(22)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CSearchBar::SetText(LPCWSTR lpszText)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
SendMessageW(SB_SETTEXT, SBT_NOBORDERS, (LPARAM)lpszText);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CSearchBar::Create(HWND hwndParent)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szBuf;
|
|
|
|
m_hWnd = CreateWindowExW(
|
|
|
|
WS_EX_CLIENTEDGE, L"Edit", NULL, WS_CHILD | WS_VISIBLE | ES_LEFT | ES_AUTOHSCROLL, 0, 0, m_Width, m_Height,
|
|
|
|
hwndParent, (HMENU)NULL, hInst, 0);
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
|
|
|
|
szBuf.LoadStringW(IDS_SEARCH_TEXT);
|
|
|
|
SetWindowTextW(szBuf);
|
|
|
|
return m_hWnd;
|
|
|
|
}
|
|
|
|
// **** CSearchBar ****
|
|
|
|
|
|
|
|
// **** CComboBox ****
|
|
|
|
|
|
|
|
CComboBox::CComboBox() : m_Width(80), m_Height(22)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CComboBox::Create(HWND hwndParent)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
m_hWnd = CreateWindowW(
|
|
|
|
WC_COMBOBOX, L"", CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 0, 0, m_Width,
|
|
|
|
m_Height, hwndParent, NULL, 0, NULL);
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
|
2021-09-13 01:33:14 +00:00
|
|
|
|
2020-07-29 10:50:57 +00:00
|
|
|
for (int i = 0; i < (int)_countof(m_TypeStringID); i++)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szBuf;
|
2020-07-29 10:50:57 +00:00
|
|
|
szBuf.LoadStringW(m_TypeStringID[i]);
|
|
|
|
SendMessageW(CB_ADDSTRING, 0, (LPARAM)(LPCWSTR)szBuf);
|
|
|
|
}
|
2021-09-13 01:33:14 +00:00
|
|
|
|
2020-07-29 10:50:57 +00:00
|
|
|
SendMessageW(CB_SETCURSEL, m_DefaultSelectType, 0); // select the first item
|
|
|
|
|
|
|
|
return m_hWnd;
|
|
|
|
}
|
|
|
|
// **** CComboBox ****
|
|
|
|
|
2020-07-24 08:07:43 +00:00
|
|
|
// **** CAppRichEdit ****
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppRichEdit::LoadAndInsertText(UINT uStringID, const CStringW &szText, DWORD TextFlags)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szLoadedText;
|
2020-07-24 08:07:43 +00:00
|
|
|
if (!szText.IsEmpty() && szLoadedText.LoadStringW(uStringID))
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
const DWORD StringFlags = CFE_BOLD;
|
2020-07-24 08:07:43 +00:00
|
|
|
InsertText(szLoadedText, StringFlags);
|
|
|
|
InsertText(szText, TextFlags);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppRichEdit::LoadAndInsertText(UINT uStringID, DWORD StringFlags)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szLoadedText;
|
2020-07-24 08:07:43 +00:00
|
|
|
if (szLoadedText.LoadStringW(uStringID))
|
|
|
|
{
|
|
|
|
InsertText(L"\n", 0);
|
|
|
|
InsertText(szLoadedText, StringFlags);
|
|
|
|
InsertText(L"\n", 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppRichEdit::InsertTextWithString(UINT StringID, const CStringW &Text, DWORD TextFlags)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (!Text.IsEmpty())
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
LoadAndInsertText(StringID, Text, TextFlags);
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppRichEdit::SetWelcomeText()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szText;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
szText.LoadStringW(IDS_WELCOME_TITLE);
|
|
|
|
SetText(szText, CFE_BOLD);
|
|
|
|
|
|
|
|
szText.LoadStringW(IDS_WELCOME_TEXT);
|
|
|
|
InsertText(szText, 0);
|
|
|
|
|
|
|
|
szText.LoadStringW(IDS_WELCOME_URL);
|
|
|
|
InsertText(szText, CFM_LINK);
|
|
|
|
}
|
|
|
|
// **** CAppRichEdit ****
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int
|
|
|
|
ScrnshotDownloadCallback(pASYNCINET AsyncInet, ASYNC_EVENT Event, WPARAM wParam, LPARAM lParam, VOID *Extension)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
ScrnshotDownloadParam *DownloadParam = (ScrnshotDownloadParam *)Extension;
|
|
|
|
switch (Event)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case ASYNCINET_DATA:
|
|
|
|
DWORD BytesWritten;
|
|
|
|
WriteFile(DownloadParam->hFile, (LPCVOID)wParam, (DWORD)lParam, &BytesWritten, NULL);
|
|
|
|
break;
|
|
|
|
case ASYNCINET_COMPLETE:
|
|
|
|
CloseHandle(DownloadParam->hFile);
|
|
|
|
SendMessage(
|
|
|
|
DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, (WPARAM)ERROR_SUCCESS, (LPARAM)DownloadParam);
|
|
|
|
break;
|
|
|
|
case ASYNCINET_CANCELLED:
|
|
|
|
CloseHandle(DownloadParam->hFile);
|
|
|
|
SendMessage(
|
|
|
|
DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, (WPARAM)ERROR_CANCELLED, (LPARAM)DownloadParam);
|
|
|
|
break;
|
|
|
|
case ASYNCINET_ERROR:
|
|
|
|
CloseHandle(DownloadParam->hFile);
|
|
|
|
SendMessage(DownloadParam->hwndNotify, WM_RAPPS_DOWNLOAD_COMPLETE, wParam, (LPARAM)DownloadParam);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ATLASSERT(FALSE);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// **** CAppScrnshotPreview ****
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
CAppScrnshotPreview::CAppScrnshotPreview(const CStringW &BasePath) : m_BasePath(BasePath)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
|
|
CAppScrnshotPreview::ProcessWindowMessage(
|
|
|
|
HWND hwnd,
|
|
|
|
UINT Msg,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
LRESULT &theResult,
|
|
|
|
DWORD dwMapId)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
theResult = 0;
|
|
|
|
switch (Msg)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_CREATE:
|
|
|
|
hBrokenImgIcon =
|
|
|
|
(HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_BROKEN_IMAGE), IMAGE_ICON, BrokenImgSize, BrokenImgSize, 0);
|
|
|
|
break;
|
|
|
|
case WM_SIZE:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (BrokenImgSize != min(min(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), BROKENIMG_ICON_SIZE))
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
BrokenImgSize = min(min(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), BROKENIMG_ICON_SIZE);
|
|
|
|
|
|
|
|
if (hBrokenImgIcon)
|
|
|
|
{
|
|
|
|
DeleteObject(hBrokenImgIcon);
|
|
|
|
hBrokenImgIcon = (HICON)LoadImage(
|
|
|
|
hInst, MAKEINTRESOURCE(IDI_BROKEN_IMAGE), IMAGE_ICON, BrokenImgSize, BrokenImgSize, 0);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_RAPPS_DOWNLOAD_COMPLETE:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
ScrnshotDownloadParam *DownloadParam = (ScrnshotDownloadParam *)lParam;
|
|
|
|
AsyncInetRelease(AsyncInet);
|
|
|
|
AsyncInet = NULL;
|
|
|
|
switch (wParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case ERROR_SUCCESS:
|
|
|
|
if (ContentID == DownloadParam->ID)
|
|
|
|
{
|
|
|
|
DisplayFile(DownloadParam->DownloadFileName);
|
|
|
|
// send a message to trigger resizing
|
|
|
|
::SendMessageW(::GetParent(m_hWnd), WM_RAPPS_RESIZE_CHILDREN, 0, 0);
|
|
|
|
InvalidateRect(0, 0);
|
|
|
|
TempImagePath =
|
|
|
|
DownloadParam->DownloadFileName; // record tmp file path in order to delete it when cleanup
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// the picture downloaded is already outdated. delete it.
|
|
|
|
DeleteFileW(DownloadParam->DownloadFileName);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ERROR_CANCELLED:
|
|
|
|
DeleteFileW(DownloadParam->DownloadFileName);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DisplayFailed();
|
|
|
|
// send a message to trigger resizing
|
|
|
|
::SendMessageW(::GetParent(m_hWnd), WM_RAPPS_RESIZE_CHILDREN, 0, 0);
|
|
|
|
InvalidateRect(0, 0);
|
|
|
|
DeleteFileW(DownloadParam->DownloadFileName);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
delete DownloadParam;
|
2020-07-24 08:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_PAINT:
|
|
|
|
{
|
|
|
|
PAINTSTRUCT ps;
|
|
|
|
HDC hdc = BeginPaint(&ps);
|
|
|
|
CRect rect;
|
|
|
|
GetClientRect(&rect);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
PaintOnDC(hdc, rect.Width(), rect.Height(), ps.fErase);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
EndPaint(&ps);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_PRINTCLIENT:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (lParam & PRF_CHECKVISIBLE)
|
|
|
|
{
|
|
|
|
if (!IsWindowVisible())
|
|
|
|
break;
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
CRect rect;
|
|
|
|
GetClientRect(&rect);
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
PaintOnDC((HDC)wParam, rect.Width(), rect.Height(), lParam & PRF_ERASEBKGND);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_ERASEBKGND:
|
|
|
|
{
|
|
|
|
return TRUE; // do not erase to avoid blinking
|
|
|
|
}
|
|
|
|
case WM_TIMER:
|
|
|
|
{
|
|
|
|
switch (wParam)
|
|
|
|
{
|
|
|
|
case TIMER_LOADING_ANIMATION:
|
|
|
|
LoadingAnimationFrame++;
|
|
|
|
LoadingAnimationFrame %= (LOADING_ANIMATION_PERIOD * LOADING_ANIMATION_FPS);
|
|
|
|
HDC hdc = GetDC();
|
|
|
|
CRect rect;
|
|
|
|
GetClientRect(&rect);
|
|
|
|
|
|
|
|
PaintOnDC(hdc, rect.Width(), rect.Height(), TRUE);
|
|
|
|
ReleaseDC(hdc);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
|
|
{
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
DeleteObject(hBrokenImgIcon);
|
|
|
|
hBrokenImgIcon = NULL;
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::DisplayLoading()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
SetStatus(SCRNSHOT_PREV_LOADING);
|
|
|
|
if (bLoadingTimerOn)
|
|
|
|
{
|
|
|
|
KillTimer(TIMER_LOADING_ANIMATION);
|
|
|
|
}
|
|
|
|
LoadingAnimationFrame = 0;
|
|
|
|
bLoadingTimerOn = TRUE;
|
|
|
|
SetTimer(TIMER_LOADING_ANIMATION, 1000 / LOADING_ANIMATION_FPS, 0);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::DisplayFailed()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
InterlockedIncrement64(&ContentID);
|
|
|
|
SetStatus(SCRNSHOT_PREV_FAILED);
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppScrnshotPreview::DisplayFile(LPCWSTR lpszFileName)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
SetStatus(SCRNSHOT_PREV_IMAGE);
|
|
|
|
pImage = Bitmap::FromFile(lpszFileName, 0);
|
|
|
|
if (pImage->GetLastStatus() != Ok)
|
|
|
|
{
|
|
|
|
DisplayFailed();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::SetStatus(SCRNSHOT_STATUS Status)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
ScrnshotPrevStauts = Status;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
// use an off screen dc to avoid blinking
|
|
|
|
HDC hdcMem = CreateCompatibleDC(hdc);
|
|
|
|
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);
|
|
|
|
SelectObject(hdcMem, hBitmap);
|
|
|
|
|
|
|
|
if (bDrawBkgnd)
|
|
|
|
{
|
|
|
|
HBRUSH hOldBrush = (HBRUSH)SelectObject(hdcMem, (HGDIOBJ)GetSysColorBrush(COLOR_BTNFACE));
|
|
|
|
PatBlt(hdcMem, 0, 0, width, height, PATCOPY);
|
|
|
|
SelectObject(hdcMem, hOldBrush);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ScrnshotPrevStauts)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case SCRNSHOT_PREV_EMPTY:
|
|
|
|
{
|
|
|
|
}
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case SCRNSHOT_PREV_LOADING:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
Graphics graphics(hdcMem);
|
2023-02-20 18:30:02 +00:00
|
|
|
Color color(255, 0, 0);
|
|
|
|
SolidBrush dotBrush(Color(255, 100, 100, 100));
|
|
|
|
|
|
|
|
graphics.SetSmoothingMode(SmoothingMode::SmoothingModeAntiAlias);
|
|
|
|
|
|
|
|
// Paint three dot
|
|
|
|
float DotWidth = GetLoadingDotWidth(width, height);
|
|
|
|
graphics.FillEllipse(
|
|
|
|
(Brush *)(&dotBrush), (REAL)width / 2.0 - min(width, height) * 2.0 / 16.0 - DotWidth / 2.0,
|
|
|
|
(REAL)height / 2.0 -
|
|
|
|
GetFrameDotShift(LoadingAnimationFrame + LOADING_ANIMATION_FPS / 4, width, height) - DotWidth / 2.0,
|
|
|
|
DotWidth, DotWidth);
|
|
|
|
|
|
|
|
graphics.FillEllipse(
|
|
|
|
(Brush *)(&dotBrush), (REAL)width / 2.0 - DotWidth / 2.0,
|
|
|
|
(REAL)height / 2.0 - GetFrameDotShift(LoadingAnimationFrame, width, height) - DotWidth / 2.0, DotWidth,
|
|
|
|
DotWidth);
|
|
|
|
|
|
|
|
graphics.FillEllipse(
|
|
|
|
(Brush *)(&dotBrush), (REAL)width / 2.0 + min(width, height) * 2.0 / 16.0 - DotWidth / 2.0,
|
|
|
|
(REAL)height / 2.0 -
|
|
|
|
GetFrameDotShift(LoadingAnimationFrame - LOADING_ANIMATION_FPS / 4, width, height) - DotWidth / 2.0,
|
|
|
|
DotWidth, DotWidth);
|
|
|
|
}
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case SCRNSHOT_PREV_IMAGE:
|
|
|
|
{
|
|
|
|
if (pImage)
|
|
|
|
{
|
|
|
|
// always draw entire image inside the window.
|
|
|
|
Graphics graphics(hdcMem);
|
|
|
|
float ZoomRatio =
|
|
|
|
min(((float)width / (float)pImage->GetWidth()), ((float)height / (float)pImage->GetHeight()));
|
|
|
|
float ZoomedImgWidth = ZoomRatio * (float)pImage->GetWidth();
|
|
|
|
float ZoomedImgHeight = ZoomRatio * (float)pImage->GetHeight();
|
|
|
|
|
|
|
|
graphics.DrawImage(
|
|
|
|
pImage, ((float)width - ZoomedImgWidth) / 2.0, ((float)height - ZoomedImgHeight) / 2.0,
|
|
|
|
ZoomedImgWidth, ZoomedImgHeight);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case SCRNSHOT_PREV_FAILED:
|
|
|
|
{
|
|
|
|
DrawIconEx(
|
|
|
|
hdcMem, (width - BrokenImgSize) / 2, (height - BrokenImgSize) / 2, hBrokenImgIcon, BrokenImgSize,
|
|
|
|
BrokenImgSize, NULL, NULL, DI_NORMAL | DI_COMPAT);
|
|
|
|
}
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// copy the content form off-screen dc to hdc
|
|
|
|
BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
|
|
|
|
DeleteDC(hdcMem);
|
|
|
|
DeleteObject(hBitmap);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
float
|
|
|
|
CAppScrnshotPreview::GetLoadingDotWidth(int width, int height)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return min(width, height) / 20.0;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
float
|
|
|
|
CAppScrnshotPreview::GetFrameDotShift(int Frame, int width, int height)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
return min(width, height) * (1.0 / 16.0) * (2.0 / (2.0 - sqrt(3.0))) *
|
|
|
|
(max(sin((float)Frame * 2 * PI / (LOADING_ANIMATION_PERIOD * LOADING_ANIMATION_FPS)), sqrt(3.0) / 2.0) -
|
|
|
|
sqrt(3.0) / 2.0);
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ATL::CWndClassInfo &
|
|
|
|
CAppScrnshotPreview::GetWndClassInfo()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
|
2023-02-20 18:30:02 +00:00
|
|
|
static ATL::CWndClassInfo wc = {
|
|
|
|
{sizeof(WNDCLASSEX), csStyle, StartWindowProc, 0, 0, NULL, 0, LoadCursorW(NULL, IDC_ARROW),
|
|
|
|
(HBRUSH)(COLOR_BTNFACE + 1), 0, L"RAppsScrnshotPreview", NULL},
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
IDC_ARROW,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
_T("")};
|
2020-07-24 08:07:43 +00:00
|
|
|
return wc;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CAppScrnshotPreview::Create(HWND hParent)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT r = {0, 0, 0, 0};
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
return CWindowImpl::Create(hParent, r, L"", WS_CHILD | WS_VISIBLE);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::PreviousDisplayCleanup()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (bLoadingTimerOn)
|
|
|
|
{
|
|
|
|
KillTimer(TIMER_LOADING_ANIMATION);
|
|
|
|
bLoadingTimerOn = FALSE;
|
|
|
|
}
|
|
|
|
LoadingAnimationFrame = 0;
|
|
|
|
if (pImage)
|
|
|
|
{
|
|
|
|
delete pImage;
|
|
|
|
pImage = NULL;
|
|
|
|
}
|
|
|
|
if (AsyncInet)
|
|
|
|
{
|
|
|
|
AsyncInetCancel(AsyncInet);
|
|
|
|
}
|
|
|
|
if (!TempImagePath.IsEmpty())
|
|
|
|
{
|
|
|
|
DeleteFileW(TempImagePath.GetString());
|
|
|
|
TempImagePath.Empty();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppScrnshotPreview::DisplayEmpty()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
InterlockedIncrement64(&ContentID);
|
|
|
|
SetStatus(SCRNSHOT_PREV_EMPTY);
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppScrnshotPreview::DisplayImage(LPCWSTR lpszLocation)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
LONGLONG ID = InterlockedIncrement64(&ContentID);
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
|
|
|
|
if (PathIsURLW(lpszLocation))
|
|
|
|
{
|
|
|
|
DisplayLoading();
|
|
|
|
|
|
|
|
ScrnshotDownloadParam *DownloadParam = new ScrnshotDownloadParam;
|
2023-02-20 18:30:02 +00:00
|
|
|
if (!DownloadParam)
|
|
|
|
return FALSE;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
DownloadParam->hwndNotify = m_hWnd;
|
|
|
|
DownloadParam->ID = ID;
|
|
|
|
// generate a filename
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW ScrnshotFolder = m_BasePath;
|
2020-07-24 08:07:43 +00:00
|
|
|
PathAppendW(ScrnshotFolder.GetBuffer(MAX_PATH), L"screenshots");
|
|
|
|
ScrnshotFolder.ReleaseBuffer();
|
|
|
|
|
|
|
|
if (!PathIsDirectoryW(ScrnshotFolder.GetString()))
|
|
|
|
{
|
|
|
|
CreateDirectoryW(ScrnshotFolder.GetString(), NULL);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (!GetTempFileNameW(
|
|
|
|
ScrnshotFolder.GetString(), L"img", 0, DownloadParam->DownloadFileName.GetBuffer(MAX_PATH)))
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
DownloadParam->DownloadFileName.ReleaseBuffer();
|
|
|
|
delete DownloadParam;
|
|
|
|
DisplayFailed();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
DownloadParam->DownloadFileName.ReleaseBuffer();
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
DownloadParam->hFile = CreateFileW(
|
|
|
|
DownloadParam->DownloadFileName.GetString(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
|
|
|
|
NULL);
|
2020-07-24 08:07:43 +00:00
|
|
|
if (DownloadParam->hFile == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
delete DownloadParam;
|
|
|
|
DisplayFailed();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
AsyncInet = AsyncInetDownload(
|
|
|
|
0, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, lpszLocation, TRUE, ScrnshotDownloadCallback, DownloadParam);
|
2020-07-24 08:07:43 +00:00
|
|
|
if (!AsyncInet)
|
|
|
|
{
|
|
|
|
CloseHandle(DownloadParam->hFile);
|
|
|
|
DeleteFileW(DownloadParam->DownloadFileName.GetBuffer());
|
|
|
|
delete DownloadParam;
|
|
|
|
DisplayFailed();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return DisplayFile(lpszLocation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int
|
|
|
|
CAppScrnshotPreview::GetRequestedWidth(int Height) // calculate requested window width by given height
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
switch (ScrnshotPrevStauts)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case SCRNSHOT_PREV_EMPTY:
|
|
|
|
return 0;
|
|
|
|
case SCRNSHOT_PREV_LOADING:
|
|
|
|
return 200;
|
|
|
|
case SCRNSHOT_PREV_IMAGE:
|
|
|
|
if (pImage)
|
|
|
|
{
|
|
|
|
// return the width needed to display image inside the window.
|
|
|
|
// and always keep window w/h ratio inside [ 1/SCRNSHOT_MAX_ASPECT_RAT, SCRNSHOT_MAX_ASPECT_RAT ]
|
|
|
|
return (int)floor(
|
|
|
|
(float)Height *
|
|
|
|
max(min((float)pImage->GetWidth() / (float)pImage->GetHeight(), (float)SCRNSHOT_MAX_ASPECT_RAT),
|
|
|
|
1.0 / (float)SCRNSHOT_MAX_ASPECT_RAT));
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case SCRNSHOT_PREV_FAILED:
|
|
|
|
return 200;
|
|
|
|
default:
|
|
|
|
return 0;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CAppScrnshotPreview::~CAppScrnshotPreview()
|
|
|
|
{
|
|
|
|
PreviousDisplayCleanup();
|
|
|
|
}
|
|
|
|
// **** CAppScrnshotPreview ****
|
|
|
|
|
|
|
|
// **** CAppInfoDisplay ****
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppInfoDisplay::ProcessWindowMessage(
|
|
|
|
HWND hwnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
LRESULT &theResult,
|
|
|
|
DWORD dwMapId)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
theResult = 0;
|
|
|
|
switch (message)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_CREATE:
|
|
|
|
{
|
|
|
|
RichEdit = new CAppRichEdit();
|
|
|
|
RichEdit->Create(hwnd);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW Directory;
|
|
|
|
::GetStorageDirectory(Directory);
|
|
|
|
ScrnshotPrev = new CAppScrnshotPreview(Directory);
|
|
|
|
ScrnshotPrev->Create(hwnd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_SIZE:
|
|
|
|
{
|
|
|
|
ResizeChildren(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_RAPPS_RESIZE_CHILDREN:
|
|
|
|
{
|
|
|
|
ResizeChildren();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_COMMAND:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
OnCommand(wParam, lParam);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case WM_NOTIFY:
|
|
|
|
{
|
|
|
|
NMHDR *NotifyHeader = (NMHDR *)lParam;
|
|
|
|
if (NotifyHeader->hwndFrom == RichEdit->m_hWnd)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
switch (NotifyHeader->code)
|
|
|
|
{
|
|
|
|
case EN_LINK:
|
|
|
|
OnLink((ENLINK *)lParam);
|
|
|
|
break;
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppInfoDisplay::ResizeChildren()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
CRect rect;
|
|
|
|
GetWindowRect(&rect);
|
|
|
|
ResizeChildren(rect.Width(), rect.Height());
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppInfoDisplay::ResizeChildren(int Width, int Height)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
int ScrnshotWidth = ScrnshotPrev->GetRequestedWidth(Height);
|
|
|
|
|
|
|
|
// make sure richedit always have room to display
|
|
|
|
ScrnshotWidth = min(ScrnshotWidth, Width - INFO_DISPLAY_PADDING - RICHEDIT_MIN_WIDTH);
|
|
|
|
|
|
|
|
DWORD dwError = ERROR_SUCCESS;
|
|
|
|
HDWP hDwp = BeginDeferWindowPos(2);
|
|
|
|
|
|
|
|
if (hDwp)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
hDwp = ::DeferWindowPos(hDwp, ScrnshotPrev->m_hWnd, NULL, 0, 0, ScrnshotWidth, Height, 0);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
if (hDwp)
|
|
|
|
{
|
|
|
|
// hide the padding if scrnshot window width == 0
|
|
|
|
int RicheditPosX = ScrnshotWidth ? (ScrnshotWidth + INFO_DISPLAY_PADDING) : 0;
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
hDwp = ::DeferWindowPos(hDwp, RichEdit->m_hWnd, NULL, RicheditPosX, 0, Width - RicheditPosX, Height, 0);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
if (hDwp)
|
|
|
|
{
|
|
|
|
EndDeferWindowPos(hDwp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwError = GetLastError();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DBG
|
|
|
|
ATLASSERT(dwError == ERROR_SUCCESS);
|
|
|
|
#endif
|
2021-03-11 11:26:45 +00:00
|
|
|
UNREFERENCED_PARAMETER(dwError);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
UpdateWindow();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppInfoDisplay::OnLink(ENLINK *Link)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
switch (Link->msg)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_RBUTTONUP:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
|
|
|
|
RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM)pLink);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ShowPopupMenuEx(m_hWnd, m_hWnd, IDR_LINKMENU, -1);
|
|
|
|
}
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ATL::CWndClassInfo &
|
|
|
|
CAppInfoDisplay::GetWndClassInfo()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
|
2023-02-20 18:30:02 +00:00
|
|
|
static ATL::CWndClassInfo wc = {/*.m_wc=*/
|
|
|
|
{/*cbSize=*/sizeof(WNDCLASSEX),
|
|
|
|
/*style=*/csStyle,
|
|
|
|
/*lpfnWndProc=*/StartWindowProc,
|
|
|
|
/*cbClsExtra=*/0,
|
|
|
|
/*cbWndExtra=*/0,
|
|
|
|
/*hInstance=*/NULL,
|
|
|
|
/*hIcon=*/NULL,
|
|
|
|
/*hCursor*/ NULL,
|
|
|
|
/*hbrBackground=*/(HBRUSH)(COLOR_BTNFACE + 1),
|
|
|
|
/*lpszMenuName=*/NULL,
|
|
|
|
/*lpszClassName=*/L"RAppsAppInfo",
|
|
|
|
/*hIconSm=*/NULL},
|
|
|
|
/*m_lpszOrigName=*/NULL,
|
|
|
|
/*pWndProc=*/NULL,
|
|
|
|
/*m_lpszCursorID=*/IDC_ARROW,
|
|
|
|
/*m_bSystemCursor*/ TRUE,
|
|
|
|
/*m_atom=*/0,
|
|
|
|
/*m_szAutoName=*/_T("")};
|
2020-07-24 08:07:43 +00:00
|
|
|
return wc;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CAppInfoDisplay::Create(HWND hwndParent)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT r = {0, 0, 0, 0};
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
2023-02-28 00:00:29 +00:00
|
|
|
CAppInfoDisplay::ShowAppInfo(CAppInfo *Info)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW ScrnshotLocation;
|
|
|
|
if (Info->RetrieveScreenshot(ScrnshotLocation))
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
ScrnshotPrev->DisplayImage(ScrnshotLocation);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ScrnshotPrev->DisplayEmpty();
|
|
|
|
}
|
|
|
|
ResizeChildren();
|
2023-02-20 18:30:02 +00:00
|
|
|
Info->ShowAppInfo(RichEdit);
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppInfoDisplay::SetWelcomeText()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
ScrnshotPrev->DisplayEmpty();
|
|
|
|
ResizeChildren();
|
|
|
|
RichEdit->SetWelcomeText();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppInfoDisplay::OnCommand(WPARAM wParam, LPARAM lParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
WORD wCommand = LOWORD(wParam);
|
|
|
|
|
|
|
|
switch (wCommand)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_OPEN_LINK:
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ShellExecuteW(m_hWnd, L"open", pLink, NULL, NULL, SW_SHOWNOACTIVATE);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pLink);
|
|
|
|
pLink = NULL;
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_COPY_LINK:
|
|
|
|
CopyTextToClipboard(pLink);
|
|
|
|
HeapFree(GetProcessHeap(), 0, pLink);
|
|
|
|
pLink = NULL;
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CAppInfoDisplay::~CAppInfoDisplay()
|
|
|
|
{
|
|
|
|
delete RichEdit;
|
|
|
|
delete ScrnshotPrev;
|
|
|
|
}
|
|
|
|
// **** CAppInfoDisplay ****
|
|
|
|
|
|
|
|
// **** CAppsListView ****
|
|
|
|
|
2021-06-09 20:56:53 +00:00
|
|
|
CAppsListView::CAppsListView()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2021-06-09 20:56:53 +00:00
|
|
|
CAppsListView::~CAppsListView()
|
|
|
|
{
|
|
|
|
if (m_hImageListView)
|
|
|
|
{
|
|
|
|
ImageList_Destroy(m_hImageListView);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-30 19:17:32 +00:00
|
|
|
LRESULT
|
|
|
|
CAppsListView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
|
|
|
|
{
|
|
|
|
LRESULT lRes = this->DefWindowProc(uMsg, wParam, lParam);
|
|
|
|
if (!m_Watermark.IsEmpty())
|
|
|
|
{
|
|
|
|
RECT rc;
|
|
|
|
GetClientRect(&rc);
|
|
|
|
HGDIOBJ oldFont = SelectFont(HDC(wParam), GetStockFont(DEFAULT_GUI_FONT));
|
|
|
|
DrawShadowText(
|
|
|
|
HDC(wParam), m_Watermark.GetString(), m_Watermark.GetLength(), &rc,
|
|
|
|
DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE, GetSysColor(COLOR_GRAYTEXT),
|
|
|
|
GetSysColor(COLOR_GRAYTEXT), 1, 1);
|
|
|
|
SelectFont(HDC(wParam), oldFont);
|
|
|
|
}
|
|
|
|
return lRes;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::SetWatermark(const CStringW &Text)
|
2021-12-30 19:17:32 +00:00
|
|
|
{
|
|
|
|
m_Watermark = Text;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::SetCheckboxesVisible(BOOL bIsVisible)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (bIsVisible)
|
|
|
|
{
|
|
|
|
SetExtendedListViewStyle(LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetExtendedListViewStyle(LVS_EX_FULLROWSELECT);
|
|
|
|
}
|
|
|
|
|
|
|
|
bHasCheckboxes = bIsVisible;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::ColumnClick(LPNMLISTVIEW pnmv)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
HWND hHeader;
|
|
|
|
HDITEMW hColumn;
|
|
|
|
INT nHeaderID = pnmv->iSubItem;
|
|
|
|
|
|
|
|
if ((GetWindowLongPtr(GWL_STYLE) & ~LVS_NOSORTHEADER) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
hHeader = (HWND)SendMessage(LVM_GETHEADER, 0, 0);
|
|
|
|
ZeroMemory(&hColumn, sizeof(hColumn));
|
|
|
|
|
|
|
|
/* If the sorting column changed, remove the sorting style from the old column */
|
|
|
|
if ((nLastHeaderID != -1) && (nLastHeaderID != nHeaderID))
|
|
|
|
{
|
|
|
|
bIsAscending = TRUE; // also reset sorting method to ascending
|
|
|
|
hColumn.mask = HDI_FORMAT;
|
|
|
|
Header_GetItem(hHeader, nLastHeaderID, &hColumn);
|
|
|
|
hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
|
|
|
|
Header_SetItem(hHeader, nLastHeaderID, &hColumn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the sorting style to the new column */
|
|
|
|
hColumn.mask = HDI_FORMAT;
|
|
|
|
Header_GetItem(hHeader, nHeaderID, &hColumn);
|
|
|
|
|
|
|
|
hColumn.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
|
|
|
|
hColumn.fmt |= (bIsAscending ? HDF_SORTUP : HDF_SORTDOWN);
|
|
|
|
Header_SetItem(hHeader, nHeaderID, &hColumn);
|
|
|
|
|
|
|
|
/* Sort the list, using the current values of nHeaderID and bIsAscending */
|
2023-02-20 18:30:02 +00:00
|
|
|
SortContext ctx = {this, nHeaderID};
|
2020-07-24 08:07:43 +00:00
|
|
|
SortItems(s_CompareFunc, &ctx);
|
|
|
|
|
|
|
|
/* Save new values */
|
|
|
|
nLastHeaderID = nHeaderID;
|
|
|
|
bIsAscending = !bIsAscending;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppsListView::AddColumn(INT Index, CStringW &Text, INT Width, INT Format)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
LVCOLUMNW Column;
|
|
|
|
|
|
|
|
ZeroMemory(&Column, sizeof(Column));
|
|
|
|
|
|
|
|
Column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
|
|
|
|
Column.iSubItem = Index;
|
2023-02-20 18:30:02 +00:00
|
|
|
Column.pszText = const_cast<LPWSTR>(Text.GetString());
|
2020-07-24 08:07:43 +00:00
|
|
|
Column.cx = Width;
|
|
|
|
Column.fmt = Format;
|
|
|
|
|
|
|
|
return SendMessage(LVM_INSERTCOLUMN, Index, (LPARAM)(&Column));
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
void
|
|
|
|
CAppsListView::DeleteColumn(INT Index)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
SendMessage(LVM_DELETECOLUMN, Index, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
INT
|
|
|
|
CAppsListView::AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
LVITEMW Item;
|
|
|
|
|
|
|
|
ZeroMemory(&Item, sizeof(Item));
|
|
|
|
|
|
|
|
Item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
|
|
|
|
Item.pszText = const_cast<LPWSTR>(lpText);
|
|
|
|
Item.lParam = lParam;
|
|
|
|
Item.iItem = ItemIndex;
|
|
|
|
Item.iImage = IconIndex;
|
|
|
|
|
|
|
|
if (IconIndex >= 0)
|
|
|
|
{
|
|
|
|
Item.iImage = IconIndex;
|
|
|
|
Item.mask |= LVIF_IMAGE;
|
|
|
|
}
|
|
|
|
return InsertItem(&Item);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HIMAGELIST
|
|
|
|
CAppsListView::GetImageList(int iImageList)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return (HIMAGELIST)SendMessage(LVM_GETIMAGELIST, iImageList, 0);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
INT CALLBACK
|
|
|
|
CAppsListView::s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
SortContext *ctx = ((SortContext *)lParamSort);
|
|
|
|
return ctx->lvw->CompareFunc(lParam1, lParam2, ctx->iSubItem);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
INT
|
|
|
|
CAppsListView::CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW Item1, Item2;
|
2020-07-24 08:07:43 +00:00
|
|
|
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();
|
|
|
|
|
|
|
|
return bIsAscending ? Item1.Compare(Item2) : Item2.Compare(Item1);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CAppsListView::Create(HWND hwndParent)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT r = {205, 28, 465, 250};
|
|
|
|
DWORD style = WS_CHILD | WS_VISIBLE | LVS_SORTASCENDING | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS |
|
|
|
|
LVS_AUTOARRANGE | LVS_SHAREIMAGELISTS;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
HWND hwnd = CListView::Create(hwndParent, r, NULL, style, WS_EX_CLIENTEDGE);
|
|
|
|
|
|
|
|
if (hwnd)
|
|
|
|
{
|
|
|
|
SetCheckboxesVisible(FALSE);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
m_hImageListView = ImageList_Create(LISTVIEW_ICON_SIZE, LISTVIEW_ICON_SIZE, GetSystemColorDepth() | ILC_MASK, 0, 1);
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
SetImageList(m_hImageListView, LVSIL_SMALL);
|
|
|
|
SetImageList(m_hImageListView, LVSIL_NORMAL);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2021-12-30 19:17:32 +00:00
|
|
|
#pragma push_macro("SubclassWindow")
|
|
|
|
#undef SubclassWindow
|
|
|
|
m_hWnd = NULL;
|
|
|
|
SubclassWindow(hwnd);
|
|
|
|
#pragma pop_macro("SubclassWindow")
|
|
|
|
|
2020-07-24 08:07:43 +00:00
|
|
|
return hwnd;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppsListView::GetCheckState(INT item)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return (BOOL)(GetItemState(item, LVIS_STATEIMAGEMASK) >> 12) - 1;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::SetCheckState(INT item, BOOL fCheck)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (bHasCheckboxes)
|
|
|
|
{
|
|
|
|
SetItemState(item, INDEXTOSTATEIMAGEMASK((fCheck) ? 2 : 1), LVIS_STATEIMAGEMASK);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::CheckAll()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (bHasCheckboxes)
|
|
|
|
{
|
|
|
|
if (CheckedItemCount == ItemCount)
|
|
|
|
{
|
|
|
|
// clear all
|
|
|
|
SetCheckState(-1, FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// check all
|
|
|
|
SetCheckState(-1, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
PVOID
|
|
|
|
CAppsListView::GetFocusedItemData()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
INT item = GetSelectionMark();
|
|
|
|
if (item == -1)
|
|
|
|
{
|
|
|
|
return (PVOID)0;
|
|
|
|
}
|
|
|
|
return (PVOID)GetItemData(item);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppsListView::SetDisplayAppType(APPLICATION_VIEW_TYPE AppType)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (!DeleteAllItems())
|
|
|
|
return FALSE;
|
2020-07-29 10:50:57 +00:00
|
|
|
ApplicationViewType = AppType;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
bIsAscending = TRUE;
|
|
|
|
|
|
|
|
ItemCount = 0;
|
|
|
|
CheckedItemCount = 0;
|
|
|
|
|
|
|
|
// delete old columns
|
|
|
|
while (ColumnCount)
|
|
|
|
{
|
|
|
|
DeleteColumn(--ColumnCount);
|
|
|
|
}
|
|
|
|
|
2020-07-29 10:50:57 +00:00
|
|
|
ImageList_RemoveAll(m_hImageListView);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
// add new columns
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szText;
|
2020-07-29 10:50:57 +00:00
|
|
|
switch (AppType)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case AppViewTypeInstalledApps:
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
/* Add columns to ListView */
|
|
|
|
szText.LoadStringW(IDS_APP_NAME);
|
|
|
|
AddColumn(ColumnCount++, szText, 250, LVCFMT_LEFT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
szText.LoadStringW(IDS_APP_INST_VERSION);
|
|
|
|
AddColumn(ColumnCount++, szText, 90, LVCFMT_RIGHT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
szText.LoadStringW(IDS_APP_DESCRIPTION);
|
|
|
|
AddColumn(ColumnCount++, szText, 300, LVCFMT_LEFT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
// disable checkboxes
|
|
|
|
SetCheckboxesVisible(FALSE);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case AppViewTypeAvailableApps:
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
/* Add columns to ListView */
|
|
|
|
szText.LoadStringW(IDS_APP_NAME);
|
|
|
|
AddColumn(ColumnCount++, szText, 250, LVCFMT_LEFT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
szText.LoadStringW(IDS_APP_INST_VERSION);
|
|
|
|
AddColumn(ColumnCount++, szText, 90, LVCFMT_RIGHT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
szText.LoadStringW(IDS_APP_DESCRIPTION);
|
|
|
|
AddColumn(ColumnCount++, szText, 300, LVCFMT_LEFT);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
// enable checkboxes
|
|
|
|
SetCheckboxesVisible(TRUE);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
default:
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CAppsListView::SetViewMode(DWORD ViewMode)
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
return SendMessage(LVM_SETVIEW, (WPARAM)ViewMode, 0) == 1;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
2023-02-28 00:00:29 +00:00
|
|
|
CAppsListView::AddApplication(CAppInfo *AppInfo, BOOL InitialCheckState)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (ApplicationViewType == AppViewTypeInstalledApps)
|
[RAPPS] Display custom applications icons for installed applications CORE-17257 (#3144)
* [RAPPS] Display custom applications icons for installed applications
- Implement `RetrieveIcon` helper function in `CInstalledApplicationInfo` class, which retrueves the current app's icon from registry, same as it done for `CAvailableApplicationInfo`.
- Use it for loading the icon in `CAppsListView::AddInstalledApplication` function, via `ExtractIconW`. Load default Rapps icon only when the app has no its custom icon.
- Retrieve `DisplayIcon` value from registry in `CInstalledApps::Enum` function, same as other registry values (like app name, description, etc).Store it in `szDisplayIcon` string, which is used in `CInstalledApplicationInfo::RetrieveIcon` for retrieving the data of that value.
- Increase `LISTVIEW_ICON_SIZE` macro from 24 to 32, so 32x32 icon size is now used instead of 24x24. This makes displayed icons more accurate, since most of apps contain 32x32 icon, so they look a bit distorted with 24x24 size.
2020-09-20 17:19:59 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
/* Load icon from registry */
|
|
|
|
HICON hIcon = NULL;
|
|
|
|
CStringW szIconPath;
|
2023-11-20 16:41:31 +00:00
|
|
|
int IconIndex;
|
2023-02-20 18:30:02 +00:00
|
|
|
if (AppInfo->RetrieveIcon(szIconPath))
|
|
|
|
{
|
2023-11-20 16:41:31 +00:00
|
|
|
IconIndex = PathParseIconLocationW(szIconPath.GetBuffer());
|
|
|
|
szIconPath.ReleaseBuffer();
|
[RAPPS] Display custom applications icons for installed applications CORE-17257 (#3144)
* [RAPPS] Display custom applications icons for installed applications
- Implement `RetrieveIcon` helper function in `CInstalledApplicationInfo` class, which retrueves the current app's icon from registry, same as it done for `CAvailableApplicationInfo`.
- Use it for loading the icon in `CAppsListView::AddInstalledApplication` function, via `ExtractIconW`. Load default Rapps icon only when the app has no its custom icon.
- Retrieve `DisplayIcon` value from registry in `CInstalledApps::Enum` function, same as other registry values (like app name, description, etc).Store it in `szDisplayIcon` string, which is used in `CInstalledApplicationInfo::RetrieveIcon` for retrieving the data of that value.
- Increase `LISTVIEW_ICON_SIZE` macro from 24 to 32, so 32x32 icon size is now used instead of 24x24. This makes displayed icons more accurate, since most of apps contain 32x32 icon, so they look a bit distorted with 24x24 size.
2020-09-20 17:19:59 +00:00
|
|
|
|
2023-11-20 16:41:31 +00:00
|
|
|
ExtractIconExW(szIconPath.GetString(), IconIndex, &hIcon, NULL, 1);
|
2023-02-20 18:30:02 +00:00
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-11-08 10:53:02 +00:00
|
|
|
/* Use the default icon if none were found in the file, or if it is not supported (returned 1) */
|
|
|
|
if (!hIcon || (hIcon == (HICON)1))
|
2023-02-20 18:30:02 +00:00
|
|
|
{
|
|
|
|
/* Load default icon */
|
|
|
|
hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-11-20 16:41:31 +00:00
|
|
|
IconIndex = ImageList_AddIcon(m_hImageListView, hIcon);
|
2023-02-20 18:30:02 +00:00
|
|
|
DestroyIcon(hIcon);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int Index = AddItem(ItemCount, IconIndex, AppInfo->szDisplayName, (LPARAM)AppInfo);
|
|
|
|
SetItemText(Index, 1, AppInfo->szDisplayVersion.IsEmpty() ? L"---" : AppInfo->szDisplayVersion);
|
|
|
|
SetItemText(Index, 2, AppInfo->szComments.IsEmpty() ? L"---" : AppInfo->szComments);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ItemCount++;
|
|
|
|
return TRUE;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
else if (ApplicationViewType == AppViewTypeAvailableApps)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
/* Load icon from file */
|
|
|
|
HICON hIcon = NULL;
|
|
|
|
CStringW szIconPath;
|
|
|
|
if (AppInfo->RetrieveIcon(szIconPath))
|
|
|
|
{
|
|
|
|
hIcon = (HICON)LoadImageW(
|
|
|
|
NULL, szIconPath, IMAGE_ICON, LISTVIEW_ICON_SIZE, LISTVIEW_ICON_SIZE, LR_LOADFROMFILE);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (!hIcon)
|
|
|
|
{
|
|
|
|
/* Load default icon */
|
|
|
|
hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_MAIN));
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int IconIndex = ImageList_AddIcon(m_hImageListView, hIcon);
|
|
|
|
DestroyIcon(hIcon);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int Index = AddItem(ItemCount, IconIndex, AppInfo->szDisplayName, (LPARAM)AppInfo);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (InitialCheckState)
|
|
|
|
{
|
|
|
|
SetCheckState(Index, TRUE);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
SetItemText(Index, 1, AppInfo->szDisplayVersion);
|
|
|
|
SetItemText(Index, 2, AppInfo->szComments);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ItemCount++;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// this function is called when parent window receiving an notification about checkstate changing
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CAppsListView::ItemCheckStateNotify(int iItem, BOOL bCheck)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (bCheck)
|
|
|
|
{
|
|
|
|
CheckedItemCount++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CheckedItemCount--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// **** CAppsListView ****
|
|
|
|
|
|
|
|
// **** CApplicationView ****
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::ProcessWindowMessage(
|
|
|
|
HWND hwnd,
|
|
|
|
UINT message,
|
|
|
|
WPARAM wParam,
|
|
|
|
LPARAM lParam,
|
|
|
|
LRESULT &theResult,
|
|
|
|
DWORD dwMapId)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
theResult = 0;
|
|
|
|
switch (message)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_CREATE:
|
|
|
|
{
|
|
|
|
BOOL bSuccess = TRUE;
|
|
|
|
m_Panel = new CUiPanel();
|
|
|
|
m_Panel->m_VerticalAlignment = UiAlign_Stretch;
|
|
|
|
m_Panel->m_HorizontalAlignment = UiAlign_Stretch;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
bSuccess &= CreateToolbar();
|
|
|
|
bSuccess &= CreateSearchBar();
|
|
|
|
bSuccess &= CreateComboBox();
|
|
|
|
bSuccess &= CreateHSplitter();
|
|
|
|
bSuccess &= CreateListView();
|
|
|
|
bSuccess &= CreateAppInfoDisplay();
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
m_Toolbar->AutoSize();
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT rTop;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
::GetWindowRect(m_Toolbar->m_hWnd, &rTop);
|
|
|
|
m_HSplitter->m_Margin.top = rTop.bottom - rTop.top;
|
|
|
|
if (!bSuccess)
|
|
|
|
{
|
|
|
|
return -1; // creation failure
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_NOTIFY:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
LPNMHDR pNotifyHeader = (LPNMHDR)lParam;
|
|
|
|
if (pNotifyHeader->hwndFrom == m_ListView->GetWindow())
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
switch (pNotifyHeader->code)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case LVN_ITEMCHANGED:
|
|
|
|
{
|
|
|
|
LPNMLISTVIEW pnic = (LPNMLISTVIEW)lParam;
|
|
|
|
|
|
|
|
/* 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))
|
|
|
|
{
|
|
|
|
ItemGetFocus((LPVOID)pnic->lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if the item is checked/unchecked */
|
|
|
|
if (pnic->uChanged & LVIF_STATE)
|
|
|
|
{
|
|
|
|
int iOldState = STATEIMAGETOINDEX(pnic->uOldState);
|
|
|
|
int iNewState = STATEIMAGETOINDEX(pnic->uNewState);
|
|
|
|
|
|
|
|
if (iOldState == STATEIMAGE_UNCHECKED && iNewState == STATEIMAGE_CHECKED)
|
|
|
|
{
|
|
|
|
// this item is just checked
|
|
|
|
m_ListView->ItemCheckStateNotify(pnic->iItem, TRUE);
|
|
|
|
ItemCheckStateChanged(TRUE, (LPVOID)pnic->lParam);
|
|
|
|
}
|
|
|
|
else if (iOldState == STATEIMAGE_CHECKED && iNewState == STATEIMAGE_UNCHECKED)
|
|
|
|
{
|
|
|
|
// this item is just unchecked
|
|
|
|
m_ListView->ItemCheckStateNotify(pnic->iItem, FALSE);
|
|
|
|
ItemCheckStateChanged(FALSE, (LPVOID)pnic->lParam);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
break;
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case LVN_COLUMNCLICK:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
LPNMLISTVIEW pnmv = (LPNMLISTVIEW)lParam;
|
|
|
|
|
|
|
|
m_ListView->ColumnClick(pnmv);
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NM_DBLCLK:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
LPNMITEMACTIVATE Item = (LPNMITEMACTIVATE)lParam;
|
|
|
|
if (Item->iItem != -1)
|
|
|
|
{
|
|
|
|
/* this won't do anything if the program is already installed */
|
|
|
|
|
|
|
|
if (ApplicationViewType == AppViewTypeAvailableApps)
|
|
|
|
{
|
|
|
|
m_MainWindow->InstallApplication(
|
2023-02-28 00:00:29 +00:00
|
|
|
(CAppInfo *)m_ListView->GetItemData(Item->iItem));
|
2023-02-20 18:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case NM_RCLICK:
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (((LPNMLISTVIEW)lParam)->iItem != -1)
|
|
|
|
{
|
|
|
|
ShowPopupMenuEx(m_hWnd, m_hWnd, 0, ID_INSTALL);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
else if (pNotifyHeader->hwndFrom == m_Toolbar->GetWindow())
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
switch (pNotifyHeader->code)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case TTN_GETDISPINFO:
|
|
|
|
m_Toolbar->OnGetDispInfo((LPTOOLTIPTEXT)lParam);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_SYSCOLORCHANGE:
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
/* Forward WM_SYSCOLORCHANGE to common controls */
|
|
|
|
m_ListView->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam);
|
|
|
|
m_ListView->SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
|
|
|
|
m_Toolbar->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam);
|
|
|
|
m_ComboBox->SendMessageW(WM_SYSCOLORCHANGE, wParam, lParam);
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_SIZE:
|
|
|
|
{
|
|
|
|
OnSize(hwnd, wParam, lParam);
|
|
|
|
break;
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case WM_COMMAND:
|
|
|
|
{
|
|
|
|
OnCommand(wParam, lParam);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateToolbar()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
m_Toolbar = new CMainToolbar();
|
|
|
|
m_Toolbar->m_VerticalAlignment = UiAlign_LeftTop;
|
|
|
|
m_Toolbar->m_HorizontalAlignment = UiAlign_Stretch;
|
|
|
|
m_Panel->Children().Append(m_Toolbar);
|
|
|
|
|
|
|
|
return m_Toolbar->Create(m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateSearchBar()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
m_SearchBar = new CUiWindow<CSearchBar>();
|
|
|
|
m_SearchBar->m_VerticalAlignment = UiAlign_LeftTop;
|
|
|
|
m_SearchBar->m_HorizontalAlignment = UiAlign_RightBtm;
|
|
|
|
m_SearchBar->m_Margin.top = 4;
|
|
|
|
m_SearchBar->m_Margin.right = TOOLBAR_PADDING;
|
|
|
|
|
|
|
|
return m_SearchBar->Create(m_Toolbar->m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateComboBox()
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
|
|
|
m_ComboBox = new CUiWindow<CComboBox>();
|
|
|
|
m_ComboBox->m_VerticalAlignment = UiAlign_LeftTop;
|
|
|
|
m_ComboBox->m_HorizontalAlignment = UiAlign_RightBtm;
|
|
|
|
m_ComboBox->m_Margin.top = 4;
|
|
|
|
|
|
|
|
return m_ComboBox->Create(m_Toolbar->m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateHSplitter()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
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;
|
2023-02-20 18:30:02 +00:00
|
|
|
m_HSplitter->m_Pos = INT_MAX; // set INT_MAX to use lowest possible position (m_MinSecond)
|
2020-07-24 08:07:43 +00:00
|
|
|
m_HSplitter->m_MinFirst = 10;
|
|
|
|
m_HSplitter->m_MinSecond = 140;
|
|
|
|
m_Panel->Children().Append(m_HSplitter);
|
|
|
|
|
|
|
|
return m_HSplitter->Create(m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateListView()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
m_ListView = new CAppsListView();
|
|
|
|
m_ListView->m_VerticalAlignment = UiAlign_Stretch;
|
|
|
|
m_ListView->m_HorizontalAlignment = UiAlign_Stretch;
|
|
|
|
m_HSplitter->First().Append(m_ListView);
|
|
|
|
|
|
|
|
return m_ListView->Create(m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::CreateAppInfoDisplay()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
m_AppsInfo = new CAppInfoDisplay();
|
|
|
|
m_AppsInfo->m_VerticalAlignment = UiAlign_Stretch;
|
|
|
|
m_AppsInfo->m_HorizontalAlignment = UiAlign_Stretch;
|
|
|
|
m_HSplitter->Second().Append(m_AppsInfo);
|
|
|
|
|
|
|
|
return m_AppsInfo->Create(m_hWnd) != NULL;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
void
|
|
|
|
CApplicationView::SetRedraw(BOOL bRedraw)
|
2021-09-30 18:19:21 +00:00
|
|
|
{
|
|
|
|
CWindow::SetRedraw(bRedraw);
|
|
|
|
m_ListView->SetRedraw(bRedraw);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
void
|
|
|
|
CApplicationView::SetFocusOnSearchBar()
|
2021-12-07 17:36:49 +00:00
|
|
|
{
|
|
|
|
m_SearchBar->SetFocus();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CApplicationView::OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
if (wParam == SIZE_MINIMIZED)
|
|
|
|
return;
|
|
|
|
|
2020-07-29 10:50:57 +00:00
|
|
|
/* Size tool bar */
|
|
|
|
m_Toolbar->AutoSize();
|
|
|
|
|
|
|
|
/* Automatically hide captions */
|
|
|
|
DWORD dToolbarTreshold = m_Toolbar->GetMaxButtonsWidth();
|
|
|
|
DWORD dSearchbarMargin = (LOWORD(lParam) - m_SearchBar->m_Width - m_ComboBox->m_Width - TOOLBAR_PADDING * 2);
|
|
|
|
|
|
|
|
if (dSearchbarMargin > dToolbarTreshold)
|
|
|
|
{
|
|
|
|
m_Toolbar->ShowButtonCaption();
|
|
|
|
}
|
|
|
|
else if (dSearchbarMargin < dToolbarTreshold)
|
|
|
|
{
|
|
|
|
m_Toolbar->HideButtonCaption();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT r = {0, 0, LOWORD(lParam), HIWORD(lParam)};
|
2020-07-24 08:07:43 +00:00
|
|
|
HDWP hdwp = NULL;
|
|
|
|
INT count = m_Panel->CountSizableChildren();
|
|
|
|
|
|
|
|
hdwp = BeginDeferWindowPos(count);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
hdwp = m_Panel->OnParentSize(r, hdwp);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
EndDeferWindowPos(hdwp);
|
|
|
|
}
|
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
count = m_SearchBar->CountSizableChildren();
|
|
|
|
hdwp = BeginDeferWindowPos(count);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
hdwp = m_SearchBar->OnParentSize(r, hdwp);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
EndDeferWindowPos(hdwp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_ComboBox->m_Margin.right = m_SearchBar->m_Width + m_SearchBar->m_Margin.right + TOOLBAR_PADDING;
|
|
|
|
count = m_ComboBox->CountSizableChildren();
|
|
|
|
hdwp = BeginDeferWindowPos(count);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
hdwp = m_ComboBox->OnParentSize(r, hdwp);
|
|
|
|
if (hdwp)
|
|
|
|
{
|
|
|
|
EndDeferWindowPos(hdwp);
|
|
|
|
}
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CApplicationView::OnCommand(WPARAM wParam, LPARAM lParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2020-07-29 10:50:57 +00:00
|
|
|
if (lParam)
|
|
|
|
{
|
|
|
|
if ((HWND)lParam == m_SearchBar->GetWindow())
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szBuf;
|
2020-07-29 10:50:57 +00:00
|
|
|
switch (HIWORD(wParam))
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case EN_SETFOCUS:
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szWndText;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
|
|
|
szBuf.LoadStringW(IDS_SEARCH_TEXT);
|
2023-02-20 18:30:02 +00:00
|
|
|
m_SearchBar->GetWindowTextW(szWndText);
|
|
|
|
if (szBuf == szWndText)
|
|
|
|
{
|
|
|
|
m_SearchBar->SetWindowTextW(L"");
|
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case EN_KILLFOCUS:
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
m_SearchBar->GetWindowTextW(szBuf);
|
|
|
|
if (szBuf.IsEmpty())
|
|
|
|
{
|
|
|
|
szBuf.LoadStringW(IDS_SEARCH_TEXT);
|
|
|
|
m_SearchBar->SetWindowTextW(szBuf.GetString());
|
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case EN_CHANGE:
|
2020-07-29 10:50:57 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
CStringW szWndText;
|
|
|
|
|
|
|
|
szBuf.LoadStringW(IDS_SEARCH_TEXT);
|
|
|
|
m_SearchBar->GetWindowTextW(szWndText);
|
|
|
|
if (szBuf == szWndText)
|
|
|
|
{
|
|
|
|
szWndText = L"";
|
|
|
|
m_MainWindow->SearchTextChanged(szWndText);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_MainWindow->SearchTextChanged(szWndText);
|
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
|
2020-08-03 13:54:01 +00:00
|
|
|
return;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
else if ((HWND)lParam == m_ComboBox->GetWindow())
|
|
|
|
{
|
|
|
|
int NotifyCode = HIWORD(wParam);
|
|
|
|
switch (NotifyCode)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case CBN_SELCHANGE:
|
|
|
|
int CurrSelection = m_ComboBox->SendMessageW(CB_GETCURSEL);
|
2020-07-29 10:50:57 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int ViewModeList[] = {LV_VIEW_DETAILS, LV_VIEW_LIST, LV_VIEW_TILE};
|
|
|
|
ATLASSERT(CurrSelection < (int)_countof(ViewModeList));
|
|
|
|
if (!m_ListView->SetViewMode(ViewModeList[CurrSelection]))
|
|
|
|
{
|
|
|
|
MessageBoxW(L"View mode invalid or unimplemented");
|
|
|
|
}
|
|
|
|
break;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
2020-08-03 13:54:01 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if ((HWND)lParam == m_Toolbar->GetWindow())
|
|
|
|
{
|
|
|
|
// the message is sent from Toolbar. fall down to continue process
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
2020-07-29 10:50:57 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2020-08-03 13:54:01 +00:00
|
|
|
// the LOWORD of wParam contains a Menu or Control ID
|
|
|
|
WORD wCommand = LOWORD(wParam);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2020-08-03 13:54:01 +00:00
|
|
|
switch (wCommand)
|
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case ID_INSTALL:
|
|
|
|
case ID_UNINSTALL:
|
|
|
|
case ID_MODIFY:
|
|
|
|
case ID_REGREMOVE:
|
|
|
|
case ID_REFRESH:
|
|
|
|
case ID_RESETDB:
|
|
|
|
case ID_CHECK_ALL:
|
|
|
|
m_MainWindow->SendMessageW(WM_COMMAND, wCommand, 0);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
CApplicationView::CApplicationView(CMainWindow *MainWindow) : m_MainWindow(MainWindow)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CApplicationView::~CApplicationView()
|
|
|
|
{
|
2020-07-29 10:50:57 +00:00
|
|
|
delete m_Toolbar;
|
|
|
|
delete m_SearchBar;
|
2020-07-24 08:07:43 +00:00
|
|
|
delete m_ListView;
|
|
|
|
delete m_AppsInfo;
|
|
|
|
delete m_HSplitter;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
ATL::CWndClassInfo &
|
|
|
|
CApplicationView::GetWndClassInfo()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
|
2023-02-20 18:30:02 +00:00
|
|
|
static ATL::CWndClassInfo wc = {
|
|
|
|
{sizeof(WNDCLASSEX), csStyle, StartWindowProc, 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_BTNFACE + 1), NULL,
|
|
|
|
L"RAppsApplicationView", NULL},
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
IDC_ARROW,
|
|
|
|
TRUE,
|
|
|
|
0,
|
|
|
|
_T("")};
|
2020-07-24 08:07:43 +00:00
|
|
|
return wc;
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
HWND
|
|
|
|
CApplicationView::Create(HWND hwndParent)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
RECT r = {0, 0, 0, 0};
|
2020-07-24 08:07:43 +00:00
|
|
|
|
|
|
|
HMENU menu = GetSubMenu(LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_APPLICATIONMENU)), 0);
|
|
|
|
|
|
|
|
return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, menu);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
|
|
|
CApplicationView::SetDisplayAppType(APPLICATION_VIEW_TYPE AppType)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2020-07-29 10:50:57 +00:00
|
|
|
if (!m_ListView->SetDisplayAppType(AppType))
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-07-29 10:50:57 +00:00
|
|
|
ApplicationViewType = AppType;
|
2020-07-24 08:07:43 +00:00
|
|
|
m_AppsInfo->SetWelcomeText();
|
|
|
|
|
|
|
|
HMENU hMenu = ::GetMenu(m_hWnd);
|
2020-07-29 10:50:57 +00:00
|
|
|
switch (AppType)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
case AppViewTypeInstalledApps:
|
|
|
|
EnableMenuItem(hMenu, ID_REGREMOVE, MF_ENABLED);
|
|
|
|
EnableMenuItem(hMenu, ID_INSTALL, MF_GRAYED);
|
|
|
|
EnableMenuItem(hMenu, ID_UNINSTALL, MF_ENABLED);
|
|
|
|
EnableMenuItem(hMenu, ID_MODIFY, MF_ENABLED);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_INSTALL, FALSE);
|
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_UNINSTALL, TRUE);
|
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, TRUE);
|
|
|
|
break;
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
case AppViewTypeAvailableApps:
|
|
|
|
EnableMenuItem(hMenu, ID_REGREMOVE, MF_GRAYED);
|
|
|
|
EnableMenuItem(hMenu, ID_INSTALL, MF_ENABLED);
|
|
|
|
EnableMenuItem(hMenu, ID_UNINSTALL, MF_GRAYED);
|
|
|
|
EnableMenuItem(hMenu, ID_MODIFY, MF_GRAYED);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
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;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
2023-02-20 18:30:02 +00:00
|
|
|
return TRUE;
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL
|
2023-02-28 00:00:29 +00:00
|
|
|
CApplicationView::AddApplication(CAppInfo *AppInfo, BOOL InitialCheckState)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
return m_ListView->AddApplication(AppInfo, InitialCheckState);
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CApplicationView::SetWatermark(const CStringW &Text)
|
2021-12-30 19:17:32 +00:00
|
|
|
{
|
|
|
|
m_ListView->SetWatermark(Text);
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
void
|
|
|
|
CApplicationView::CheckAll()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
m_ListView->CheckAll();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
PVOID
|
|
|
|
CApplicationView::GetFocusedItemData()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return m_ListView->GetFocusedItemData();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
int
|
|
|
|
CApplicationView::GetItemCount()
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
return m_ListView->GetItemCount();
|
|
|
|
}
|
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CApplicationView::AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &TabOrderList)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2020-07-29 10:50:57 +00:00
|
|
|
m_Toolbar->AppendTabOrderWindow(Direction, TabOrderList);
|
|
|
|
m_ComboBox->AppendTabOrderWindow(Direction, TabOrderList);
|
|
|
|
m_SearchBar->AppendTabOrderWindow(Direction, TabOrderList);
|
2020-07-24 08:07:43 +00:00
|
|
|
m_ListView->AppendTabOrderWindow(Direction, TabOrderList);
|
|
|
|
m_AppsInfo->AppendTabOrderWindow(Direction, TabOrderList);
|
|
|
|
}
|
|
|
|
|
|
|
|
// this function is called when a item of listview get focus.
|
|
|
|
// CallbackParam is the param passed to listview when adding the item (the one getting focus now).
|
2023-02-20 18:30:02 +00:00
|
|
|
VOID
|
|
|
|
CApplicationView::ItemGetFocus(LPVOID CallbackParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-20 18:30:02 +00:00
|
|
|
if (CallbackParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
2023-02-28 00:00:29 +00:00
|
|
|
CAppInfo *Info = static_cast<CAppInfo *>(CallbackParam);
|
2023-02-20 18:30:02 +00:00
|
|
|
m_AppsInfo->ShowAppInfo(Info);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
if (ApplicationViewType == AppViewTypeInstalledApps)
|
|
|
|
{
|
|
|
|
HMENU hMenu = ::GetMenu(m_hWnd);
|
2020-07-24 08:07:43 +00:00
|
|
|
|
2023-02-20 18:30:02 +00:00
|
|
|
BOOL CanModify = Info->CanModify();
|
|
|
|
|
|
|
|
EnableMenuItem(hMenu, ID_MODIFY, CanModify ? MF_ENABLED : MF_GRAYED);
|
|
|
|
m_Toolbar->SendMessageW(TB_ENABLEBUTTON, ID_MODIFY, CanModify);
|
|
|
|
}
|
2020-07-24 08:07:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// this function is called when a item of listview is checked/unchecked
|
2023-02-20 18:30:02 +00:00
|
|
|
// CallbackParam is the param passed to listview when adding the item (the one getting changed now).
|
|
|
|
VOID
|
|
|
|
CApplicationView::ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam)
|
2020-07-24 08:07:43 +00:00
|
|
|
{
|
|
|
|
m_MainWindow->ItemCheckStateChanged(bChecked, CallbackParam);
|
|
|
|
}
|
|
|
|
// **** CApplicationView ****
|