[RAPPS] application-view refactor (#3003)

* [RAPPS] separate application-view from gui.cpp
* [RAPPS] make the code looks more clear
* [RAPPS] fix &  improve tab-order handle
* [RAPPS] now double-click / right-click & install an item will install exactly this app
* [RAPPS] add handling for DWORD timestamp for InstallDate
* [RAPPS] make the code setting column style more clear
* [RAPPS] change the owner of popup-menu
* [RAPPS] now the popup menu (the one when right-click listview) now belongs to application-view
This commit is contained in:
He Yang 2020-07-24 16:07:43 +08:00 committed by Mark Jansen
parent 10c0ff7416
commit e44c9b6630
No known key found for this signature in database
GPG key ID: B39240EE84BEAE8B
11 changed files with 3257 additions and 2741 deletions

View file

@ -7,6 +7,7 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/cryptlib)
include_directories(include)
list(APPEND SOURCE
appview.cpp
asyncinet.cpp
available.cpp
cabinet.cpp
@ -19,9 +20,11 @@ list(APPEND SOURCE
winmain.cpp
unattended.cpp
include/rapps.h
include/appview.h
include/asyncinet.h
include/available.h
include/dialogs.h
include/gui.h
include/installed.h
include/crichedit.h
include/defines.h

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,318 @@
#pragma once
#include "rapps.h"
#include "rosui.h"
#include "crichedit.h"
#include "asyncinet.h"
#include <shlobj_undoc.h>
#include <shlguid_undoc.h>
#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 LISTVIEW_ICON_SIZE 24
// default broken-image icon size
#define BROKENIMG_ICON_SIZE 96
// the boundary of w/h ratio of scrnshot preview window
#define SCRNSHOT_MAX_ASPECT_RAT 2.5
// padding between scrnshot preview and richedit (in pixel)
#define INFO_DISPLAY_PADDING 10
// minimum width of richedit
#define RICHEDIT_MIN_WIDTH 160
// user-defined window message
#define WM_RAPPS_DOWNLOAD_COMPLETE (WM_USER + 1) // notify download complete. wParam is error code, and lParam is a pointer to ScrnshotDownloadParam
#define WM_RAPPS_RESIZE_CHILDREN (WM_USER + 2) // ask parent window to resize children.
enum SCRNSHOT_STATUS
{
SCRNSHOT_PREV_EMPTY, // show nothing
SCRNSHOT_PREV_LOADING, // image is loading (most likely downloading)
SCRNSHOT_PREV_IMAGE, // display image from a file
SCRNSHOT_PREV_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
// retrieve the value using a mask
#define STATEIMAGETOINDEX(x) (((x) & LVIS_STATEIMAGEMASK) >> 12)
// for listview with extend style LVS_EX_CHECKBOXES, State image 1 is the unchecked box, and state image 2 is the checked box.
// see this: https://docs.microsoft.com/en-us/windows/win32/controls/extended-list-view-styles
#define STATEIMAGE_UNCHECKED 1
#define STATEIMAGE_CHECKED 2
class CMainWindow;
enum APPLICATION_VIEW_MODE
{
ApplicationViewEmpty,
ApplicationViewAvailableApps,
ApplicationViewInstalledApps
};
typedef struct __ScrnshotDownloadParam
{
LONGLONG ID;
HANDLE hFile;
HWND hwndNotify;
ATL::CStringW DownloadFileName;
} ScrnshotDownloadParam;
class CAppRichEdit :
public CUiWindow<CRichEdit>
{
private:
VOID LoadAndInsertText(UINT uStringID,
const ATL::CStringW &szText,
DWORD StringFlags,
DWORD TextFlags);
VOID LoadAndInsertText(UINT uStringID,
DWORD StringFlags);
VOID InsertVersionInfo(CAvailableApplicationInfo *Info);
VOID InsertLicenseInfo(CAvailableApplicationInfo *Info);
VOID InsertLanguageInfo(CAvailableApplicationInfo *Info);
public:
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo *Info);
inline VOID InsertTextWithString(UINT StringID, DWORD StringFlags, const ATL::CStringW &Text, DWORD TextFlags);
BOOL ShowInstalledAppInfo(CInstalledApplicationInfo *Info);
VOID SetWelcomeText();
};
int ScrnshotDownloadCallback(
pASYNCINET AsyncInet,
ASYNC_EVENT Event,
WPARAM wParam,
LPARAM lParam,
VOID *Extension
);
class CAppScrnshotPreview :
public CWindowImpl<CAppScrnshotPreview>
{
private:
SCRNSHOT_STATUS ScrnshotPrevStauts = SCRNSHOT_PREV_EMPTY;
Image *pImage = NULL;
HICON hBrokenImgIcon = NULL;
BOOL bLoadingTimerOn = FALSE;
int LoadingAnimationFrame = 0;
int BrokenImgSize = BROKENIMG_ICON_SIZE;
pASYNCINET AsyncInet = NULL;
LONGLONG ContentID = 0; // used to determine whether image has been switched when download complete. Increase by 1 each time the content of this window changed
ATL::CStringW TempImagePath; // currently displayed temp file
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
VOID DisplayLoading();
VOID DisplayFailed();
BOOL DisplayFile(LPCWSTR lpszFileName);
VOID SetStatus(SCRNSHOT_STATUS Status);
VOID PaintOnDC(HDC hdc, int width, int height, BOOL bDrawBkgnd);
float GetLoadingDotWidth(int width, int height);
float GetFrameDotShift(int Frame, int width, int height);
public:
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create(HWND hParent);
VOID PreviousDisplayCleanup();
VOID DisplayEmpty();
BOOL DisplayImage(LPCWSTR lpszLocation);
// calculate requested window width by given height
int GetRequestedWidth(int Height);
~CAppScrnshotPreview();
};
class CAppInfoDisplay :
public CUiWindow<CWindowImpl<CAppInfoDisplay>>
{
LPWSTR pLink = NULL;
private:
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
VOID ResizeChildren();
VOID ResizeChildren(int Width, int Height);
VOID OnLink(ENLINK *Link);
public:
CAppRichEdit *RichEdit = NULL;
CAppScrnshotPreview *ScrnshotPrev = NULL;
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create(HWND hwndParent);
BOOL ShowAvailableAppInfo(CAvailableApplicationInfo *Info);
BOOL ShowInstalledAppInfo(CInstalledApplicationInfo *Info);
VOID SetWelcomeText();
VOID OnCommand(WPARAM wParam, LPARAM lParam);
~CAppInfoDisplay();
};
class CAppsListView :
public CUiWindow<CListView>
{
struct SortContext
{
CAppsListView *lvw;
INT iSubItem;
};
BOOL bIsAscending = TRUE;
BOOL bHasCheckboxes;
INT ItemCount = 0;
INT CheckedItemCount = 0;
INT ColumnCount = 0;
INT nLastHeaderID;
APPLICATION_VIEW_MODE ApplicationViewMode = ApplicationViewEmpty;
public:
CAppsListView();
VOID SetCheckboxesVisible(BOOL bIsVisible);
VOID ColumnClick(LPNMLISTVIEW pnmv);
BOOL AddColumn(INT Index, ATL::CStringW &Text, INT Width, INT Format);
int AddColumn(INT Index, LPWSTR lpText, INT Width, INT Format);
void DeleteColumn(INT Index);
INT AddItem(INT ItemIndex, INT IconIndex, LPCWSTR lpText, LPARAM lParam);
HIMAGELIST GetImageList(int iImageList);
static INT CALLBACK s_CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
INT CompareFunc(LPARAM lParam1, LPARAM lParam2, INT iSubItem);
HWND Create(HWND hwndParent);
BOOL GetCheckState(INT item);
VOID SetCheckState(INT item, BOOL fCheck);
VOID CheckAll();
PVOID GetFocusedItemData();
BOOL SetDisplayMode(APPLICATION_VIEW_MODE Mode);
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID CallbackParam);
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID CallbackParam);
// this function is called when parent window receiving an notification about checkstate changing
VOID ItemCheckStateNotify(int iItem, BOOL bCheck);
};
class CApplicationView :
public CUiWindow<CWindowImpl<CApplicationView>>
{
private:
CUiPanel *m_Panel = NULL;
CAppsListView *m_ListView = NULL;
CAppInfoDisplay *m_AppsInfo = NULL;
CUiSplitPanel *m_HSplitter = NULL;
CMainWindow *m_MainWindow = NULL;
APPLICATION_VIEW_MODE ApplicationViewMode = ApplicationViewEmpty;
BOOL ProcessWindowMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
BOOL CreateHSplitter();
BOOL CreateListView();
BOOL CreateAppInfoDisplay();
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
VOID OnCommand(WPARAM wParam, LPARAM lParam);
public:
CApplicationView(CMainWindow *MainWindow);
~CApplicationView();
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create(HWND hwndParent);
BOOL SetDisplayMode(APPLICATION_VIEW_MODE Mode);
BOOL AddInstalledApplication(CInstalledApplicationInfo *InstAppInfo, LPVOID param);
BOOL AddAvailableApplication(CAvailableApplicationInfo *AvlbAppInfo, BOOL InitCheckState, LPVOID param);
void CheckAll();
PVOID GetFocusedItemData();
int GetItemCount();
VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> &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).
BOOL ItemGetFocus(LPVOID CallbackParam);
// this function is called when a item of listview is checked/unchecked
// CallbackParam is the param passed to listview when adding the item (the one getting focus now).
BOOL ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam);
};

View file

@ -0,0 +1,185 @@
#pragma once
#include "rapps.h"
#include "rosui.h"
#include "crichedit.h"
#include "asyncinet.h"
#include "misc.h"
#include "appview.h"
#include <shlobj_undoc.h>
#include <shlguid_undoc.h>
#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>
#define SEARCH_TIMER_ID 'SR'
#define TREEVIEW_ICON_SIZE 24
class CMainToolbar :
public CUiWindow< CToolbar<> >
{
const INT m_iToolbarHeight;
DWORD m_dButtonsWidthMax;
WCHAR szInstallBtn[MAX_STR_LEN];
WCHAR szUninstallBtn[MAX_STR_LEN];
WCHAR szModifyBtn[MAX_STR_LEN];
WCHAR szSelectAll[MAX_STR_LEN];
VOID AddImageToImageList(HIMAGELIST hImageList, UINT ImageIndex);
HIMAGELIST InitImageList();
public:
CMainToolbar();
VOID OnGetDispInfo(LPTOOLTIPTEXT lpttt);
HWND Create(HWND hwndParent);
VOID HideButtonCaption();
VOID ShowButtonCaption();
DWORD GetMaxButtonsWidth() const;
};
class CSideTreeView :
public CUiWindow<CTreeView>
{
HIMAGELIST hImageTreeView;
public:
CSideTreeView();
HTREEITEM AddItem(HTREEITEM hParent, ATL::CStringW &Text, INT Image, INT SelectedImage, LPARAM lParam);
HTREEITEM AddCategory(HTREEITEM hRootItem, UINT TextIndex, UINT IconIndex);
HIMAGELIST SetImageList();
VOID DestroyImageList();
~CSideTreeView();
};
class CSearchBar :
public CWindow
{
public:
const INT m_Width;
const INT m_Height;
CSearchBar();
VOID SetText(LPCWSTR lpszText);
HWND Create(HWND hwndParent);
};
class CMainWindow :
public CWindowImpl<CMainWindow, CWindow, CFrameWinTraits>
{
CUiPanel *m_ClientPanel = NULL;
CUiSplitPanel *m_VSplitter = NULL;
CMainToolbar *m_Toolbar = NULL;
CSideTreeView *m_TreeView = NULL;
CUiWindow<CStatusBar> *m_StatusBar = NULL;
CApplicationView *m_ApplicationView = NULL;
CUiWindow<CSearchBar> *m_SearchBar = NULL;
CAvailableApps m_AvailableApps;
CInstalledApps m_InstalledApps;
BOOL bSearchEnabled;
BOOL bUpdating = FALSE;
ATL::CStringW szSearchPattern;
INT SelectedEnumType;
public:
CMainWindow();
~CMainWindow();
private:
VOID InitCategoriesList();
BOOL CreateStatusBar();
BOOL CreateToolbar();
BOOL CreateTreeView();
BOOL CreateApplicationView();
BOOL CreateVSplitter();
BOOL CreateSearchBar();
BOOL CreateLayout();
VOID LayoutCleanup();
BOOL InitControls();
VOID OnSize(HWND hwnd, WPARAM wParam, LPARAM lParam);
BOOL RemoveSelectedAppFromRegistry();
BOOL UninstallSelectedApp(BOOL bModify);
BOOL ProcessWindowMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT &theResult, DWORD dwMapId);
BOOL IsSelectedNodeInstalled();
VOID ShowAboutDlg();
VOID OnCommand(WPARAM wParam, LPARAM lParam);
static BOOL SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle);
BOOL CALLBACK EnumInstalledAppProc(CInstalledApplicationInfo *Info);
BOOL CALLBACK EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState);
static BOOL CALLBACK s_EnumInstalledAppProc(CInstalledApplicationInfo *Info, PVOID param);
static BOOL CALLBACK s_EnumAvailableAppProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
static BOOL CALLBACK s_EnumSelectedAppForDownloadProc(CAvailableApplicationInfo *Info, BOOL bInitialCheckState, PVOID param);
VOID UpdateStatusBarText();
VOID UpdateApplicationsList(INT EnumType);
public:
static ATL::CWndClassInfo &GetWndClassInfo();
HWND Create();
// this function is called when a item of application-view is checked/unchecked
// CallbackParam is the param passed to application-view when adding the item (the one getting focus now).
BOOL ItemCheckStateChanged(BOOL bChecked, LPVOID CallbackParam);
// this function is called when application-view is asked to install an application
// if Info is not zero, this app should be installed. otherwise those checked apps should be installed
BOOL InstallApplication(CAvailableApplicationInfo *Info);
void HandleTabOrder(int direction);
};
VOID ShowMainWindow(INT nShowCmd);

View file

@ -14,7 +14,8 @@ public:
ATL::CStringW szKeyName;
CInstalledApplicationInfo(BOOL bIsUserKey, REGSAM RegWowKey, HKEY hKey);
BOOL GetApplicationString(LPCWSTR lpKeyName, ATL::CStringW& String);
BOOL GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String);
BOOL GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue);
BOOL UninstallApplication(BOOL bModify);
LSTATUS RemoveFromRegistry();

View file

@ -3,6 +3,10 @@
#include <windef.h>
#include <atlstr.h>
#define EPOCH_DIFF 116444736000000000 //FILETIME starts from 1601-01-01 UTC, UnixTime starts from 1970-01-01
#define RATE_DIFF 10000000
INT GetWindowWidth(HWND hwnd);
INT GetWindowHeight(HWND hwnd);
INT GetClientWindowWidth(HWND hwnd);
@ -48,3 +52,7 @@ public:
BOOL PathAppendNoDirEscapeW(LPWSTR pszPath, LPCWSTR pszMore);
BOOL IsSystem64Bit();
INT GetSystemColorDepth();
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime);

View file

@ -493,6 +493,12 @@ public:
}
};
virtual VOID AppendTabOrderWindow(int Direction, ATL::CSimpleArray<HWND> & TabOrderList)
{
TabOrderList.Add(T::m_hWnd);
return;
}
virtual ~CUiWindow()
{
if (T::IsWindow())

View file

@ -65,7 +65,7 @@ CInstalledApplicationInfo::~CInstalledApplicationInfo()
}
}
BOOL CInstalledApplicationInfo::GetApplicationString(LPCWSTR lpKeyName, ATL::CStringW& String)
BOOL CInstalledApplicationInfo::GetApplicationRegString(LPCWSTR lpKeyName, ATL::CStringW& String)
{
DWORD dwSize = 0;
String.Empty();
@ -109,6 +109,23 @@ BOOL CInstalledApplicationInfo::GetApplicationString(LPCWSTR lpKeyName, ATL::CSt
return TRUE;
}
BOOL CInstalledApplicationInfo::GetApplicationRegDword(LPCWSTR lpKeyName, DWORD *lpValue)
{
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
if (RegQueryValueExW(hSubKey,
lpKeyName,
NULL,
&dwType,
(LPBYTE)lpValue,
&dwSize) != ERROR_SUCCESS)
{
return FALSE;
}
return TRUE;
}
BOOL CInstalledApplicationInfo::UninstallApplication(BOOL bModify)
{
return StartProcess(bModify ? szModifyPath : szUninstallString, TRUE);
@ -187,24 +204,51 @@ BOOL CInstalledApps::Enum(INT EnumType, APPENUMPROC lpEnumProc, PVOID param)
if (Info->hSubKey)
{
// those items without display name are ignored
if (Info->GetApplicationString(L"DisplayName", Info->szDisplayName))
if (Info->GetApplicationRegString(L"DisplayName", Info->szDisplayName))
{
Info->GetApplicationString(L"DisplayVersion", Info->szDisplayVersion);
Info->GetApplicationString(L"Publisher", Info->szPublisher);
Info->GetApplicationString(L"RegOwner", Info->szRegOwner);
Info->GetApplicationString(L"ProductID", Info->szProductID);
Info->GetApplicationString(L"HelpLink", Info->szHelpLink);
Info->GetApplicationString(L"HelpTelephone", Info->szHelpTelephone);
Info->GetApplicationString(L"Readme", Info->szReadme);
Info->GetApplicationString(L"Contact", Info->szContact);
Info->GetApplicationString(L"URLUpdateInfo", Info->szURLUpdateInfo);
Info->GetApplicationString(L"URLInfoAbout", Info->szURLInfoAbout);
Info->GetApplicationString(L"Comments", Info->szComments);
Info->GetApplicationString(L"InstallDate", Info->szInstallDate);
Info->GetApplicationString(L"InstallLocation", Info->szInstallLocation);
Info->GetApplicationString(L"InstallSource", Info->szInstallSource);
Info->GetApplicationString(L"UninstallString", Info->szUninstallString);
Info->GetApplicationString(L"ModifyPath", Info->szModifyPath);
Info->GetApplicationRegString(L"DisplayVersion", Info->szDisplayVersion);
Info->GetApplicationRegString(L"Publisher", Info->szPublisher);
Info->GetApplicationRegString(L"RegOwner", Info->szRegOwner);
Info->GetApplicationRegString(L"ProductID", Info->szProductID);
Info->GetApplicationRegString(L"HelpLink", Info->szHelpLink);
Info->GetApplicationRegString(L"HelpTelephone", Info->szHelpTelephone);
Info->GetApplicationRegString(L"Readme", Info->szReadme);
Info->GetApplicationRegString(L"Contact", Info->szContact);
Info->GetApplicationRegString(L"URLUpdateInfo", Info->szURLUpdateInfo);
Info->GetApplicationRegString(L"URLInfoAbout", Info->szURLInfoAbout);
Info->GetApplicationRegString(L"Comments", Info->szComments);
if (Info->GetApplicationRegString(L"InstallDate", Info->szInstallDate) == FALSE)
{
// It might be a DWORD (Unix timestamp). try again.
DWORD dwInstallTimeStamp;
if (Info->GetApplicationRegDword(L"InstallDate", &dwInstallTimeStamp))
{
FILETIME InstallFileTime;
SYSTEMTIME InstallSystemTime, InstallLocalTime;
UnixTimeToFileTime(dwInstallTimeStamp, &InstallFileTime);
FileTimeToSystemTime(&InstallFileTime, &InstallSystemTime);
// convert to localtime
SystemTimeToTzSpecificLocalTime(NULL, &InstallSystemTime, &InstallLocalTime);
// convert to readable date string
int cchTimeStrLen = GetDateFormatW(LOCALE_USER_DEFAULT,
0,
&InstallLocalTime,
NULL, 0, 0);
GetDateFormatW(LOCALE_USER_DEFAULT, // use default locale for current user
0,
&InstallLocalTime,
NULL, Info->szInstallDate.GetBuffer(cchTimeStrLen), cchTimeStrLen);
Info->szInstallDate.ReleaseBuffer();
}
}
Info->GetApplicationRegString(L"InstallLocation", Info->szInstallLocation);
Info->GetApplicationRegString(L"InstallSource", Info->szInstallSource);
Info->GetApplicationRegString(L"UninstallString", Info->szUninstallString);
Info->GetApplicationRegString(L"ModifyPath", Info->szModifyPath);
bSuccess = TRUE;
}

View file

@ -486,3 +486,40 @@ BOOL IsSystem64Bit()
bIsSys64ResultCached = TRUE; // next time calling this function, it will directly return bIsSys64Result
return bIsSys64Result;
}
INT GetSystemColorDepth()
{
DEVMODEW pDevMode;
INT ColorDepth;
pDevMode.dmSize = sizeof(pDevMode);
pDevMode.dmDriverExtra = 0;
if (!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &pDevMode))
{
/* TODO: Error message */
return ILC_COLOR;
}
switch (pDevMode.dmBitsPerPel)
{
case 32: ColorDepth = ILC_COLOR32; break;
case 24: ColorDepth = ILC_COLOR24; break;
case 16: ColorDepth = ILC_COLOR16; break;
case 8: ColorDepth = ILC_COLOR8; break;
case 4: ColorDepth = ILC_COLOR4; break;
default: ColorDepth = ILC_COLOR; break;
}
return ColorDepth;
}
void UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime)
{
// Note that LONGLONG is a 64-bit value
LONGLONG ll;
ll = Int32x32To64(dwUnixTime, 10000000) + 116444736000000000;
pFileTime->dwLowDateTime = (DWORD)ll;
pFileTime->dwHighDateTime = ll >> 32;
}

View file

@ -212,7 +212,7 @@ public:
};
CSize CPoint::operator-(POINT point) const throw()
inline CSize CPoint::operator-(POINT point) const throw()
{
return CSize(x - point.x, y - point.y);
}
@ -539,28 +539,28 @@ public:
}
};
CRect CPoint::operator+(const RECT* lpRect) const throw()
inline CRect CPoint::operator+(const RECT* lpRect) const throw()
{
CRect r(lpRect);
r += *this;
return r;
}
CRect CPoint::operator-(const RECT* lpRect) const throw()
inline CRect CPoint::operator-(const RECT* lpRect) const throw()
{
CRect r(lpRect);
r -= *this;
return r;
}
CRect CSize::operator+(const RECT* lpRect) const throw()
inline CRect CSize::operator+(const RECT* lpRect) const throw()
{
CRect r(lpRect);
r += *this;
return r;
}
CRect CSize::operator-(const RECT* lpRect) const throw()
inline CRect CSize::operator-(const RECT* lpRect) const throw()
{
CRect r(lpRect);
r -= *this;