[RAPPS] Screenshot preview and other trivial fixes (#2894)

* add one more layer of window
* using Path* API to operate path
* always use rappmgr.cab as file name when downloading db. ignore the URL
* add snapshot preview window
* show a broken-image icon when failed to load image
* add a padding between image and content, and make sure always some space is reserved for richedit
* hide the padding if snapshot window does not have a width
* some work to avoid blinking when window resizing
* add WM_PRINTCLIENT handling
This commit is contained in:
He Yang 2020-06-14 21:22:58 +08:00 committed by Mark Jansen
parent eacaf65459
commit fbf119fde1
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
11 changed files with 574 additions and 69 deletions

View file

@ -39,7 +39,7 @@ add_rc_deps(rapps.rc ${rapps_rc_deps})
add_executable(rapps ${SOURCE} rapps.rc)
set_module_type(rapps win32gui UNICODE)
target_link_libraries(rapps uuid wine)
add_importlibs(rapps advapi32 comctl32 gdi32 wininet user32 shell32 shlwapi ole32 setupapi msvcrt kernel32 ntdll)
add_importlibs(rapps advapi32 comctl32 gdi32 wininet user32 shell32 shlwapi ole32 setupapi gdiplus msvcrt kernel32 ntdll)
add_pch(rapps include/rapps.h SOURCE)
add_dependencies(rapps rappsmsg)
add_message_headers(ANSI rappsmsg.mc)

View file

@ -18,23 +18,23 @@
#include <atlstr.h>
// CAvailableApplicationInfo
CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam)
CAvailableApplicationInfo::CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam, AvailableStrings& AvlbStrings)
: m_IsSelected(FALSE), m_LicenseType(LICENSE_NONE), m_SizeBytes(0), m_sFileName(sFileNameParam),
m_IsInstalled(FALSE), m_HasLanguageInfo(FALSE), m_HasInstalledVersion(FALSE)
{
RetrieveGeneralInfo();
RetrieveGeneralInfo(AvlbStrings);
}
VOID CAvailableApplicationInfo::RefreshAppInfo()
VOID CAvailableApplicationInfo::RefreshAppInfo(AvailableStrings& AvlbStrings)
{
if (m_szUrlDownload.IsEmpty())
{
RetrieveGeneralInfo();
RetrieveGeneralInfo(AvlbStrings);
}
}
// Lazily load general info from the file
VOID CAvailableApplicationInfo::RetrieveGeneralInfo()
VOID CAvailableApplicationInfo::RetrieveGeneralInfo(AvailableStrings& AvlbStrings)
{
m_Parser = new CConfigParser(m_sFileName);
@ -52,10 +52,31 @@ VOID CAvailableApplicationInfo::RetrieveGeneralInfo()
GetString(L"License", m_szLicense);
GetString(L"Description", m_szDesc);
GetString(L"URLSite", m_szUrlSite);
GetString(L"CDPath", m_szCDPath);
GetString(L"Language", m_szRegName);
GetString(L"SHA1", m_szSHA1);
static_assert(MAX_SNAPSHOT_NUM < 10000, "MAX_SNAPSHOT_NUM is too big");
for (int i = 0; i < MAX_SNAPSHOT_NUM; i++)
{
WCHAR SnapshotField[sizeof("Snapshot") + 4];
wsprintfW(SnapshotField, L"Snapshot%d", i + 1);
ATL::CStringW SnapshotFileName;
if (!GetString(SnapshotField, SnapshotFileName))
{
continue;
}
// TODO: Add URL Support
// TODO: Does the filename contain anything stuff like "\\" ".." ":" "<" ">" ?
// these stuff may lead to security issues
ATL::CStringW SnapshotName = AvlbStrings.szAppsPath;
PathAppendW(SnapshotName.GetBuffer(MAX_PATH), L"snapshots");
PathAppendW(SnapshotName.GetBuffer(), SnapshotFileName.GetString());
SnapshotName.ReleaseBuffer();
m_szSnapshotFilename.Add(SnapshotName);
}
RetrieveSize();
RetrieveLicenseType();
RetrieveLanguages();
@ -209,6 +230,16 @@ BOOL CAvailableApplicationInfo::HasUpdate() const
return (m_szInstalledVersion.Compare(m_szVersion) < 0) ? TRUE : FALSE;
}
BOOL CAvailableApplicationInfo::RetrieveSnapshot(UINT Index,ATL::CStringW& SnapshotFileName) const
{
if (Index >= (UINT)m_szSnapshotFilename.GetSize())
{
return FALSE;
}
SnapshotFileName = m_szSnapshotFilename[Index];
return TRUE;
}
VOID CAvailableApplicationInfo::SetLastWriteTime(FILETIME* ftTime)
{
RtlCopyMemory(&m_ftCacheStamp, ftTime, sizeof(FILETIME));
@ -231,11 +262,19 @@ AvailableStrings::AvailableStrings()
//FIXME: maybe provide a fallback?
if (GetStorageDirectory(szPath))
{
szAppsPath = szPath + L"\\rapps\\";
szAppsPath = szPath;
PathAppendW(szAppsPath.GetBuffer(MAX_PATH), L"rapps");
szAppsPath.ReleaseBuffer();
szCabName = L"rappmgr.cab";
szCabDir = szPath;
szCabPath = (szCabDir + L"\\") + szCabName;
szSearchPath = szAppsPath + L"*.txt";
szCabPath = szCabDir;
PathAppendW(szCabPath.GetBuffer(MAX_PATH), szCabName);
szCabPath.ReleaseBuffer();
szSearchPath = szAppsPath;
PathAppendW(szSearchPath.GetBuffer(MAX_PATH), L"*.txt");
szSearchPath.ReleaseBuffer();
}
}
// AvailableStrings
@ -273,7 +312,9 @@ VOID CAvailableApps::DeleteCurrentAppsDB()
ATL::CStringW szTmp;
do
{
szTmp = m_Strings.szAppsPath + FindFileData.cFileName;
szTmp = m_Strings.szAppsPath;
PathAppendW(szTmp.GetBuffer(MAX_PATH), FindFileData.cFileName);
szTmp.ReleaseBuffer();
DeleteFileW(szTmp.GetString());
} while (FindNextFileW(hFind, &FindFileData) != 0);
FindClose(hFind);
@ -369,7 +410,7 @@ BOOL CAvailableApps::Enum(INT EnumType, AVAILENUMPROC lpEnumProc, PVOID param)
}
// create a new entry
Info = new CAvailableApplicationInfo(FindFileData.cFileName);
Info = new CAvailableApplicationInfo(FindFileData.cFileName, m_Strings);
// set a timestamp for the next time
Info->SetLastWriteTime(&FindFileData.ftLastWriteTime);
@ -380,7 +421,7 @@ skip_if_cached:
|| EnumType == ENUM_ALL_AVAILABLE
|| (EnumType == ENUM_CAT_SELECTED && Info->m_IsSelected))
{
Info->RefreshAppInfo();
Info->RefreshAppInfo(m_Strings);
if (lpEnumProc)
lpEnumProc(Info, m_Strings.szAppsPath.GetString(), param);

View file

@ -17,15 +17,48 @@
#include <atlbase.h>
#include <atlcom.h>
#include <atltypes.h>
#include <atlwin.h>
#include <wininet.h>
#include <shellutils.h>
#include <rosctrls.h>
#include <gdiplus.h>
#include <math.h>
using namespace Gdiplus;
#define SEARCH_TIMER_ID 'SR'
#define LISTVIEW_ICON_SIZE 24
#define TREEVIEW_ICON_SIZE 24
// default broken-image icon size
#define BROKENIMG_ICON_SIZE 96
// the boundary of w/h ratio of snapshot preview window
#define SNPSHT_MAX_ASPECT_RAT 2.5
// padding between snapshot preview and richedit (in pixel)
#define INFO_DISPLAY_PADDING 10
// minimum width of richedit
#define RICHEDIT_MIN_WIDTH 160
enum SNPSHT_STATUS
{
SNPSHTPREV_EMPTY, // show nothing
SNPSHTPREV_LOADING, // image is loading (most likely downloading)
SNPSHTPREV_FILE, // display image from a file
SNPSHTPREV_FAILED // image can not be shown (download failure or wrong image)
};
#define TIMER_LOADING_ANIMATION 1 // Timer ID
#define LOADING_ANIMATION_PERIOD 3 // Animation cycling period (in seconds)
#define LOADING_ANIMATION_FPS 18 // Animation Frame Per Second
#define PI 3.1415927
INT GetSystemColorDepth()
{
DEVMODEW pDevMode;
@ -257,6 +290,322 @@ public:
}
};
class CAppSnapshotPreview :
public CWindowImpl<CAppSnapshotPreview>
{
private:
SNPSHT_STATUS SnpshtPrevStauts = SNPSHTPREV_EMPTY;
Image* pImage = NULL;
HICON hBrokenImgIcon = NULL;
BOOL bLoadingTimerOn = FALSE;
int LoadingAnimationFrame = 0;
int BrokenImgSize = BROKENIMG_ICON_SIZE;
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT& theResult, DWORD dwMapId)
{
theResult = 0;
switch (Msg)
{
case WM_CREATE:
hBrokenImgIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_BROKEN_IMAGE), IMAGE_ICON, BrokenImgSize, BrokenImgSize, 0);
break;
case WM_SIZE:
{
if (BrokenImgSize != min(min(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)), BROKENIMG_ICON_SIZE))
{
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);
}
}
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(&ps);
CRect rect;
GetClientRect(&rect);
PaintOnDC(hdc,
rect.Width(),
rect.Height(),
ps.fErase);
EndPaint(&ps);
break;
}
case WM_PRINTCLIENT:
{
if (lParam & PRF_CHECKVISIBLE)
{
if (!IsWindowVisible()) break;
}
CRect rect;
GetClientRect(&rect);
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;
}
}
return FALSE;
}
VOID SetStatus(SNPSHT_STATUS Status)
{
SnpshtPrevStauts = Status;
}
VOID PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd)
{
// 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 (SnpshtPrevStauts)
{
case SNPSHTPREV_EMPTY:
{
}
break;
case SNPSHTPREV_LOADING:
{
Graphics graphics(hdcMem);
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;
case SNPSHTPREV_FILE:
{
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);
}
}
break;
case SNPSHTPREV_FAILED:
{
DrawIconEx(hdcMem,
(width - BrokenImgSize) / 2,
(height - BrokenImgSize) / 2,
hBrokenImgIcon,
BrokenImgSize,
BrokenImgSize,
NULL,
NULL,
DI_NORMAL | DI_COMPAT);
}
break;
}
// copy the content form off-screen dc to hdc
BitBlt(hdc, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
DeleteDC(hdcMem);
DeleteObject(hBitmap);
}
float GetLoadingDotWidth(int width, int height)
{
return min(width, height) / 20.0;
}
float GetFrameDotShift(int Frame, int width, int height)
{
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);
}
public:
static ATL::CWndClassInfo& GetWndClassInfo()
{
DWORD csStyle = CS_VREDRAW | CS_HREDRAW;
static ATL::CWndClassInfo wc =
{
{
sizeof(WNDCLASSEX),
csStyle,
StartWindowProc,
0,
0,
NULL,
0,
LoadCursorW(NULL, IDC_ARROW),
(HBRUSH)(COLOR_BTNFACE + 1),
0,
L"RAppsSnapshotPreview",
NULL
},
NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
};
return wc;
}
HWND Create(HWND hParent)
{
RECT r = { 0,0,0,0 };
return CWindowImpl::Create(hParent, r, L"", WS_CHILD | WS_VISIBLE);
}
VOID PreviousDisplayCleanup()
{
if (bLoadingTimerOn)
{
KillTimer(TIMER_LOADING_ANIMATION);
bLoadingTimerOn = FALSE;
}
LoadingAnimationFrame = 0;
if (pImage)
{
delete pImage;
pImage = NULL;
}
}
VOID DisplayEmpty()
{
SetStatus(SNPSHTPREV_EMPTY);
PreviousDisplayCleanup();
}
VOID DisplayLoading()
{
SetStatus(SNPSHTPREV_LOADING);
PreviousDisplayCleanup();
bLoadingTimerOn = TRUE;
SetTimer(TIMER_LOADING_ANIMATION, 1000 / LOADING_ANIMATION_FPS, 0);
}
BOOL DisplayFile(LPCWSTR lpszFileName)
{
SetStatus(SNPSHTPREV_FILE);
PreviousDisplayCleanup();
pImage = Bitmap::FromFile(lpszFileName, 0);
if (pImage->GetLastStatus() != Ok)
{
DisplayFailed();
return FALSE;
}
return TRUE;
}
VOID DisplayFailed()
{
SetStatus(SNPSHTPREV_FAILED);
PreviousDisplayCleanup();
}
int GetRequestedWidth(int Height) // calculate requested window width by given height
{
switch (SnpshtPrevStauts)
{
case SNPSHTPREV_EMPTY:
return 0;
case SNPSHTPREV_LOADING:
return 200;
case SNPSHTPREV_FILE:
if (pImage)
{
// return the width needed to display image inside the window.
// and always keep window w/h ratio inside [ 1/SNPSHT_MAX_ASPECT_RAT, SNPSHT_MAX_ASPECT_RAT ]
return (int)floor((float)Height *
max(min((float)pImage->GetWidth() / (float)pImage->GetHeight(), (float)SNPSHT_MAX_ASPECT_RAT), 1.0/ (float)SNPSHT_MAX_ASPECT_RAT));
}
return 0;
case SNPSHTPREV_FAILED:
return 200;
default:
return 0;
}
}
~CAppSnapshotPreview()
{
PreviousDisplayCleanup();
}
};
class CAppInfoDisplay :
public CUiWindow<CWindowImpl<CAppInfoDisplay>>
{
@ -272,16 +621,18 @@ private:
{
RichEdit = new CAppRichEdit();
RichEdit->Create(hwnd);
SnpshtPrev = new CAppSnapshotPreview();
SnpshtPrev->Create(hwnd);
break;
}
case WM_SIZE:
{
::MoveWindow(RichEdit->m_hWnd, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), TRUE);
ResizeChildren(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
break;
}
case WM_COMMAND:
{
OnCommand(wParam, lParam);
break;
}
@ -304,9 +655,94 @@ private:
return FALSE;
}
VOID ResizeChildren()
{
CRect rect;
GetWindowRect(&rect);
ResizeChildren(rect.Width(), rect.Height());
}
VOID ResizeChildren(int Width, int Height)
{
int SnpshtWidth = SnpshtPrev->GetRequestedWidth(Height);
// make sure richedit always have room to display
SnpshtWidth = min(SnpshtWidth, Width - INFO_DISPLAY_PADDING - RICHEDIT_MIN_WIDTH);
DWORD dwError = ERROR_SUCCESS;
HDWP hDwp = BeginDeferWindowPos(2);
if (hDwp)
{
hDwp = ::DeferWindowPos(hDwp, SnpshtPrev->m_hWnd, NULL,
0, 0, SnpshtWidth, Height, 0);
if (hDwp)
{
// hide the padding if snapshot window width == 0
int RicheditPosX = SnpshtWidth ? (SnpshtWidth + INFO_DISPLAY_PADDING) : 0;
hDwp = ::DeferWindowPos(hDwp, RichEdit->m_hWnd, NULL,
RicheditPosX, 0, Width - RicheditPosX, Height, 0);
if (hDwp)
{
EndDeferWindowPos(hDwp);
}
else
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
}
else
{
dwError = GetLastError();
}
#if DBG
ATLASSERT(dwError == ERROR_SUCCESS);
#endif
UpdateWindow();
}
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;
}
RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM)pLink);
ShowPopupMenuEx(m_hWnd, m_hWnd, IDR_LINKMENU, -1);
}
break;
}
}
public:
CAppRichEdit * RichEdit;
CAppSnapshotPreview * SnpshtPrev;
static ATL::CWndClassInfo& GetWndClassInfo()
{
@ -336,51 +772,38 @@ public:
{
RECT r = { 0,0,0,0 };
return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE);
return CWindowImpl::Create(hwndParent, r, L"", WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
}
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo* Info)
{
ATL::CStringW SnapshotFilename;
if (Info->RetrieveSnapshot(0, SnapshotFilename))
{
SnpshtPrev->DisplayFile(SnapshotFilename);
}
else
{
SnpshtPrev->DisplayEmpty();
}
ResizeChildren();
return RichEdit->ShowAvailableAppInfo(Info);
}
BOOL ShowInstalledAppInfo(PINSTALLED_INFO Info)
{
SnpshtPrev->DisplayEmpty();
ResizeChildren();
return RichEdit->ShowInstalledAppInfo(Info);
}
VOID SetWelcomeText()
{
SnpshtPrev->DisplayEmpty();
ResizeChildren();
RichEdit->SetWelcomeText();
}
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;
}
RichEdit->SendMessageW(EM_SETSEL, Link->chrg.cpMin, Link->chrg.cpMax);
RichEdit->SendMessageW(EM_GETSELTEXT, 0, (LPARAM)pLink);
ShowPopupMenuEx(m_hWnd, m_hWnd, IDR_LINKMENU, -1);
}
break;
}
}
VOID OnCommand(WPARAM wParam, LPARAM lParam)
{
WORD wCommand = LOWORD(wParam);
@ -1804,8 +2227,12 @@ private:
}
/* Load icon from file */
ATL::CStringW szIconPath;
szIconPath.Format(L"%lsicons\\%ls.ico", szFolderPath, Info->m_szName.GetString());
ATL::CStringW szIconPath = szFolderPath;
PathAppendW(szIconPath.GetBuffer(MAX_PATH), L"icons");
PathAppendW(szIconPath.GetBuffer(), Info->m_szName.GetString());
PathAddExtensionW(szIconPath.GetBuffer(), L".ico");
szIconPath.ReleaseBuffer();
hIcon = (HICON) LoadImageW(NULL,
szIconPath.GetString(),
IMAGE_ICON,

View file

@ -7,6 +7,9 @@
#include "misc.h"
#define MAX_SNAPSHOT_NUM 16
enum LicenseType
{
LICENSE_NONE,
@ -22,6 +25,18 @@ inline BOOL IsLicenseType(INT x)
return (x >= LICENSE_MIN && x <= LICENSE_MAX);
}
struct AvailableStrings
{
ATL::CStringW szPath;
ATL::CStringW szCabPath;
ATL::CStringW szAppsPath;
ATL::CStringW szSearchPath;
ATL::CStringW szCabName;
ATL::CStringW szCabDir;
AvailableStrings();
};
struct CAvailableApplicationInfo
{
INT m_Category;
@ -35,8 +50,9 @@ struct CAvailableApplicationInfo
ATL::CStringW m_szSize;
ATL::CStringW m_szUrlSite;
ATL::CStringW m_szUrlDownload;
ATL::CStringW m_szCDPath;
ATL::CSimpleArray<LCID> m_LanguageLCIDs;
ATL::CSimpleArray<ATL::CStringW> m_szSnapshotFilename;
ULONG m_SizeBytes;
// Caching mechanism related entries
@ -48,17 +64,17 @@ struct CAvailableApplicationInfo
ATL::CStringW m_szInstalledVersion;
// Create an object from file
CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam);
CAvailableApplicationInfo(const ATL::CStringW& sFileNameParam, AvailableStrings& m_Strings);
// Load all info from the file
VOID RefreshAppInfo();
VOID RefreshAppInfo(AvailableStrings& m_Strings);
BOOL HasLanguageInfo() const;
BOOL HasNativeLanguage() const;
BOOL HasEnglishLanguage() const;
BOOL IsInstalled() const;
BOOL HasInstalledVersion() const;
BOOL HasUpdate() const;
BOOL RetrieveSnapshot(UINT Index, ATL::CStringW& SnapshotFileName) const;
// Set a timestamp
VOID SetLastWriteTime(FILETIME* ftTime);
@ -71,7 +87,7 @@ private:
inline BOOL GetString(LPCWSTR lpKeyName, ATL::CStringW& ReturnedString);
// Lazily load general info from the file
VOID RetrieveGeneralInfo();
VOID RetrieveGeneralInfo(AvailableStrings& m_Strings);
VOID RetrieveInstalledStatus();
VOID RetrieveInstalledVersion();
VOID RetrieveLanguages();
@ -82,18 +98,6 @@ private:
typedef BOOL(CALLBACK *AVAILENUMPROC)(CAvailableApplicationInfo *Info, LPCWSTR szFolderPath, PVOID param);
struct AvailableStrings
{
ATL::CStringW szPath;
ATL::CStringW szCabPath;
ATL::CStringW szAppsPath;
ATL::CStringW szSearchPath;
ATL::CStringW szCabName;
ATL::CStringW szCabDir;
AvailableStrings();
};
class CAvailableApps
{
static AvailableStrings m_Strings;

View file

@ -9,7 +9,6 @@ INT GetClientWindowWidth(HWND hwnd);
INT GetClientWindowHeight(HWND hwnd);
VOID CopyTextToClipboard(LPCWSTR lpszText);
VOID SetWelcomeText();
VOID ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem);
VOID ShowPopupMenu(HWND hwnd, UINT MenuID, UINT DefaultItem);
BOOL StartProcess(ATL::CStringW &Path, BOOL Wait);

View file

@ -14,6 +14,7 @@
#define IDI_UPDATE_DB 20
#define IDI_CHECK_ALL 21
#define IDI_SELECTEDFORINST 22
#define IDI_BROKEN_IMAGE 23
/* Icons for categories */
#define IDI_CAT_AUDIO 50

View file

@ -650,8 +650,19 @@ unsigned int WINAPI CDownloadManager::ThreadFunc(LPVOID param)
}
// append a \ to the provided file system path, and the filename portion from the URL after that
Path += L"\\";
Path += (LPWSTR) (p + 1);
PathAddBackslashW(Path.GetBuffer(MAX_PATH));
switch (InfoArray[iAppId].DLType)
{
case DLTYPE_DBUPDATE:
case DLTYPE_DBUPDATE_UNOFFICIAL:
PathAppendW(Path.GetBuffer(), L"rappmgr.cab"); // whatever the URL is, use the file name L"rappmgr.cab"
break;
case DLTYPE_APPLICATION:
PathAppendW(Path.GetBuffer(), (LPWSTR)(p + 1)); // use the filename retrieved from URL
break;
}
Path.ReleaseBuffer();
if ((InfoArray[iAppId].DLType == DLTYPE_APPLICATION) && InfoArray[iAppId].szSHA1[0] && GetFileAttributesW(Path.GetString()) != INVALID_FILE_ATTRIBUTES)
{

View file

@ -177,14 +177,15 @@ BOOL StartProcess(LPWSTR lpPath, BOOL Wait)
BOOL GetStorageDirectory(ATL::CStringW& Directory)
{
if (!SHGetSpecialFolderPathW(NULL, Directory.GetBuffer(MAX_PATH), CSIDL_LOCAL_APPDATA, TRUE))
LPWSTR DirectoryStr = Directory.GetBuffer(MAX_PATH);
if (!SHGetSpecialFolderPathW(NULL, DirectoryStr, CSIDL_LOCAL_APPDATA, TRUE))
{
Directory.ReleaseBuffer();
return FALSE;
}
PathAppendW(DirectoryStr, L"rapps");
Directory.ReleaseBuffer();
Directory += L"\\rapps";
return (CreateDirectoryW(Directory.GetString(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS);
}

View file

@ -23,6 +23,8 @@ IDI_APPUPD ICON "res/appupd.ico"
IDI_CATEGORY ICON "res/cat.ico"
IDI_UPDATE_DB ICON "res/updatedb.ico"
IDI_CHECK_ALL ICON "res/select.ico"
IDI_SELECTEDFORINST ICON "res/select.ico"
IDI_BROKEN_IMAGE ICON "res/brokenimg.ico"
/* Categories */
IDI_CAT_AUDIO ICON "res/cats/audio.ico"
@ -41,7 +43,6 @@ IDI_CAT_SCIENCE ICON "res/cats/science.ico"
IDI_CAT_TOOLS ICON "res/cats/tools.ico"
IDI_CAT_VIDEO ICON "res/cats/video.ico"
IDI_CAT_THEMES ICON "res/cats/themes.ico"
IDI_SELECTEDFORINST ICON "res/select.ico"
/* Accelerators -- key bindings */
HOTKEYS ACCELERATORS

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View file

@ -13,6 +13,8 @@
#include <atlcom.h>
#include <gdiplus.h>
HWND hMainWnd;
HINSTANCE hInst;
SETTINGS_INFO SettingsInfo;
@ -28,6 +30,10 @@ END_OBJECT_MAP()
CRAppsModule gModule;
CAtlWinModule gWinModule;
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
static VOID InitializeAtlModule(HINSTANCE hInstance, BOOL bInitialize)
{
if (bInitialize)
@ -40,6 +46,18 @@ static VOID InitializeAtlModule(HINSTANCE hInstance, BOOL bInitialize)
}
}
VOID InitializeGDIPlus(BOOL bInitialize)
{
if (bInitialize)
{
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
}
else
{
Gdiplus::GdiplusShutdown(gdiplusToken);
}
}
VOID FillDefaultSettings(PSETTINGS_INFO pSettingsInfo)
{
ATL::CStringW szDownloadDir;
@ -129,6 +147,7 @@ INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
BOOL bIsFirstLaunch;
InitializeAtlModule(hInstance, TRUE);
InitializeGDIPlus(TRUE);
if (GetUserDefaultUILanguage() == MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT))
{
@ -169,6 +188,7 @@ INT WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLi
if (hMutex)
CloseHandle(hMutex);
InitializeGDIPlus(FALSE);
InitializeAtlModule(hInstance, FALSE);
return 0;