Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
91
Src/Plugins/Library/ml_online/Setup/SetupGroupFilter.h
Normal file
91
Src/Plugins/Library/ml_online/Setup/SetupGroupFilter.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <vector>
|
||||
|
||||
class ifc_omservice;
|
||||
|
||||
class __declspec(novtable) SetupGroupFilter
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
serviceIgnore = 0x00000000,
|
||||
serviceInclude = 0x00000001,
|
||||
serviceForceSubscribe = 0x00000002,
|
||||
serviceForceUnsubscribe = 0x00000004,
|
||||
} FilterResult;
|
||||
protected:
|
||||
SetupGroupFilter(const GUID *filterId);
|
||||
virtual ~SetupGroupFilter();
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(const GUID *filterId, SetupGroupFilter **instance);
|
||||
|
||||
public:
|
||||
virtual ULONG AddRef();
|
||||
virtual ULONG Release();
|
||||
|
||||
virtual HRESULT GetId(GUID *filterId);
|
||||
|
||||
virtual HRESULT Initialize() = 0;
|
||||
virtual HRESULT ProcessService(ifc_omservice *service, UINT *filterResult) = 0;
|
||||
|
||||
protected:
|
||||
typedef std::vector<UINT> ServiceIdList;
|
||||
static BOOL CALLBACK AppendServiceIdCallback(UINT serviceId, void *data);
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
GUID id;
|
||||
};
|
||||
|
||||
|
||||
// {2F45FBDF-4372-4def-B20C-C6F1BAE5AE85}
|
||||
static const GUID FUID_SetupFeaturedGroupFilter =
|
||||
{ 0x2f45fbdf, 0x4372, 0x4def, { 0xb2, 0xc, 0xc6, 0xf1, 0xba, 0xe5, 0xae, 0x85 } };
|
||||
|
||||
|
||||
class SetupFeaturedGroupFilter : public SetupGroupFilter
|
||||
{
|
||||
protected:
|
||||
SetupFeaturedGroupFilter();
|
||||
~SetupFeaturedGroupFilter();
|
||||
public:
|
||||
static HRESULT CreateInstance(SetupFeaturedGroupFilter **instance);
|
||||
|
||||
public:
|
||||
HRESULT Initialize();
|
||||
HRESULT ProcessService(ifc_omservice *service, UINT *filterResult);
|
||||
|
||||
protected:
|
||||
ServiceIdList filterList;
|
||||
};
|
||||
|
||||
// {7CA8722D-8B11-43a0-8F55-533C9DE3D73E}
|
||||
static const GUID FUID_SetupKnownGroupFilter =
|
||||
{ 0x7ca8722d, 0x8b11, 0x43a0, { 0x8f, 0x55, 0x53, 0x3c, 0x9d, 0xe3, 0xd7, 0x3e } };
|
||||
|
||||
|
||||
class SetupKnownGroupFilter : public SetupGroupFilter
|
||||
{
|
||||
protected:
|
||||
SetupKnownGroupFilter();
|
||||
~SetupKnownGroupFilter();
|
||||
public:
|
||||
static HRESULT CreateInstance(SetupKnownGroupFilter **instance);
|
||||
|
||||
public:
|
||||
HRESULT Initialize();
|
||||
HRESULT ProcessService(ifc_omservice *service, UINT *filterResult);
|
||||
|
||||
protected:
|
||||
ServiceIdList filterList;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPFILTER_HEADER
|
71
Src/Plugins/Library/ml_online/Setup/setup.cpp
Normal file
71
Src/Plugins/Library/ml_online/Setup/setup.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
#define GUID_DEFINE
|
||||
#include "../../winamp/setup/svc_setup.h"
|
||||
#undef GUID_DEFINE
|
||||
|
||||
#include "./setupPage.h"
|
||||
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
|
||||
static HRESULT Setup_RegisterPage()
|
||||
{
|
||||
HRESULT hr;
|
||||
svc_setup *setupSvc;
|
||||
SetupPage *page;
|
||||
|
||||
|
||||
if (FAILED(WasabiApi_LoadDefaults()) ||
|
||||
NULL == OMBROWSERMNGR ||
|
||||
NULL == OMSERVICEMNGR ||
|
||||
NULL == OMUTILITY)
|
||||
{
|
||||
return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
setupSvc = QueryWasabiInterface(svc_setup, UID_SVC_SETUP);
|
||||
if (NULL == setupSvc)
|
||||
return E_POINTER;
|
||||
|
||||
page = SetupPage::CreateInstance();
|
||||
if (NULL == page)
|
||||
hr = E_OUTOFMEMORY;
|
||||
else
|
||||
{
|
||||
// try to insert before 'feedback' (if present)
|
||||
// otherwise dump at the end of the pages list.
|
||||
int index = 0xFFFFF;
|
||||
if (FAILED(setupSvc->GetPageCount(&index)))
|
||||
index = 0xFFFFF;
|
||||
else if (index > 0 && index == 3)
|
||||
index--;
|
||||
|
||||
hr = setupSvc->InsertPage(page, &index);
|
||||
if (SUCCEEDED(hr))
|
||||
setupSvc->AddJob((ifc_setupjob*)page);
|
||||
|
||||
page->Release();
|
||||
}
|
||||
|
||||
ReleaseWasabiInterface(UID_SVC_SETUP, setupSvc);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
EXTERN_C _declspec(dllexport) BOOL RegisterSetup(HINSTANCE hInstance, api_service *waServices)
|
||||
{
|
||||
// check the current date and if past November 30th 2013
|
||||
// then we will prevent the online page from being shown
|
||||
time_t now = time(0);
|
||||
struct tm *tn = localtime(&now);
|
||||
tn->tm_sec = tn->tm_min = tn->tm_hour = 0;
|
||||
|
||||
if (mktime(tn) >= 1387497600)
|
||||
return FALSE;
|
||||
|
||||
if (FAILED(WasabiApi_Initialize(hInstance, waServices)))
|
||||
return FALSE;
|
||||
|
||||
BOOL result = SUCCEEDED(Setup_RegisterPage());
|
||||
WasabiApi_Release();
|
||||
return result;
|
||||
}
|
80
Src/Plugins/Library/ml_online/Setup/setupDetails.cpp
Normal file
80
Src/Plugins/Library/ml_online/Setup/setupDetails.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
#include "./common.h"
|
||||
#include "./setupDetails.h"
|
||||
#include "./setupServicePanel.h"
|
||||
|
||||
EXTERN_C ATOM DETAILS_PROP = 0;
|
||||
HMODULE hEditModule = NULL;
|
||||
|
||||
|
||||
BOOL SetupDetails_Initialize()
|
||||
{
|
||||
if (0 == DETAILS_PROP)
|
||||
{
|
||||
DETAILS_PROP = GlobalAddAtom(L"omSetupDetailsProp");
|
||||
if (0 == DETAILS_PROP) return FALSE;
|
||||
}
|
||||
|
||||
if (NULL == (hEditModule = LoadLibrary(L"riched20.dll")))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupDetails_Uninitialize()
|
||||
{
|
||||
if (NULL != hEditModule)
|
||||
{
|
||||
FreeLibrary(hEditModule);
|
||||
hEditModule = NULL;
|
||||
}
|
||||
|
||||
if (0 != DETAILS_PROP)
|
||||
{
|
||||
GlobalDeleteAtom(DETAILS_PROP);
|
||||
DETAILS_PROP = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupDetails_SetDescription(HWND hEdit, LPCWSTR pszText)
|
||||
{
|
||||
SetWindowText(hEdit, pszText);
|
||||
|
||||
DWORD originalStyle = GetWindowStyle(hEdit);
|
||||
DWORD windowStyle = originalStyle & ~WS_VSCROLL;
|
||||
|
||||
INT lineCount = (INT)SendMessage(hEdit, EM_GETLINECOUNT, 0, 0L);
|
||||
if (lineCount > 0)
|
||||
{
|
||||
INT charIndex = (INT)SendMessage(hEdit, EM_LINEINDEX, (WPARAM)(lineCount - 1), 0L);
|
||||
if (-1 != charIndex)
|
||||
{
|
||||
LRESULT result = SendMessage(hEdit, EM_POSFROMCHAR, charIndex, 0L);
|
||||
POINTS pts = MAKEPOINTS(result);
|
||||
RECT clientRect;
|
||||
if (GetClientRect(hEdit, &clientRect) && pts.y > (clientRect.bottom - 14))
|
||||
{
|
||||
windowStyle |= WS_VSCROLL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (windowStyle != originalStyle)
|
||||
{
|
||||
SetWindowLongPtr(hEdit, GWL_STYLE, windowStyle);
|
||||
SetWindowPos(hEdit, NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED);
|
||||
}
|
||||
|
||||
ShowWindow(hEdit, SW_HIDE);
|
||||
if (0 != ShowWindow(hEdit, (L'\0' != *pszText) ? SW_SHOWNA : SW_HIDE))
|
||||
InvalidateRect(hEdit, NULL, TRUE);
|
||||
}
|
||||
|
||||
HWND SetupDetails_CreateServiceView(HWND hParent, LPCWSTR pszName, ifc_omservice *service)
|
||||
{
|
||||
return ServicePanel::CreateInstance(hParent, pszName, service, NULL);
|
||||
}
|
||||
|
||||
BOOL SetupDetails_GetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
return (BOOL)SendMessage(hwnd, NSDM_GETUNIQUENAME, (WPARAM)cchBufferMax, (LPARAM)pszBuffer);
|
||||
}
|
30
Src/Plugins/Library/ml_online/Setup/setupDetails.h
Normal file
30
Src/Plugins/Library/ml_online/Setup/setupDetails.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
|
||||
class ifc_omservice;
|
||||
class SetupGroup;
|
||||
class SetupListboxItem;
|
||||
|
||||
#define NSDM_FIRST (WM_APP + 7)
|
||||
#define NSDM_GETUNIQUENAME (NSDM_FIRST + 0)
|
||||
|
||||
EXTERN_C ATOM DETAILS_PROP;
|
||||
|
||||
BOOL SetupDetails_Initialize();
|
||||
void SetupDetails_Uninitialize();
|
||||
|
||||
|
||||
HWND SetupDetails_CreateServiceView(HWND hParent, LPCWSTR pszName, ifc_omservice *service);
|
||||
HWND SetupDetails_CreateGroupView(HWND hParent, LPCWSTR pszName, SetupGroup *group);
|
||||
BOOL SetupDetails_GetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
|
||||
// internal
|
||||
void SetupDetails_SetDescription(HWND hEdit, LPCWSTR pszText);
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPDETAILS_HEADER
|
284
Src/Plugins/Library/ml_online/Setup/setupDetailsGroup.cpp
Normal file
284
Src/Plugins/Library/ml_online/Setup/setupDetailsGroup.cpp
Normal file
|
@ -0,0 +1,284 @@
|
|||
#include "./setupDetails.h"
|
||||
#include "../common.h"
|
||||
#include "../resource.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
#include "../../winamp/commandLink.h"
|
||||
#include "./setupGroup.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#ifndef IDC_HELPLINK
|
||||
#define IDC_HELPLINK 10000
|
||||
#endif
|
||||
|
||||
struct GROUPDETAILSCREATEPARAM
|
||||
{
|
||||
GROUPDETAILSCREATEPARAM() : group(NULL), name(NULL) {}
|
||||
|
||||
SetupGroup *group;
|
||||
LPCWSTR name;
|
||||
};
|
||||
|
||||
struct GROUPDETAILS
|
||||
{
|
||||
GROUPDETAILS() : group(NULL), name(NULL), fontTitle(NULL) {}
|
||||
|
||||
SetupGroup *group;
|
||||
LPWSTR name;
|
||||
HFONT fontTitle;
|
||||
};
|
||||
|
||||
#define GetDetails(__hwnd) ((GROUPDETAILS*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
|
||||
|
||||
static INT_PTR WINAPI GroupDetails_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
HWND SetupDetails_CreateGroupView(HWND hParent, LPCWSTR pszName, SetupGroup *group)
|
||||
{
|
||||
GROUPDETAILSCREATEPARAM param;
|
||||
param.group = group;
|
||||
param.name = pszName;
|
||||
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_GROUPDETAILS, hParent, GroupDetails_DialogProc, (LPARAM)¶m);
|
||||
}
|
||||
|
||||
static void GroupDetails_SetTitle(HWND hwnd, SetupGroup *group)
|
||||
{
|
||||
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
|
||||
if (NULL == hTitle) return;
|
||||
|
||||
WCHAR szBuffer[128] = {0};
|
||||
if (NULL == group ||
|
||||
FAILED(group->GetLongName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
szBuffer[0] = L'\0';
|
||||
}
|
||||
|
||||
GROUPDETAILS *details = GetDetails(hwnd);
|
||||
if (NULL != details && NULL == details->fontTitle)
|
||||
{
|
||||
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||||
LOGFONT lf;
|
||||
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
|
||||
lf.lfWidth = 0;
|
||||
lf.lfWeight = FW_DONTCARE;
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
|
||||
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
|
||||
details->fontTitle = CreateFontIndirect(&lf);
|
||||
}
|
||||
|
||||
if (NULL != details->fontTitle)
|
||||
{
|
||||
SendMessage(hTitle, WM_SETFONT, (WPARAM)details->fontTitle, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowText(hTitle, szBuffer);
|
||||
InvalidateRect(hTitle, NULL, TRUE);
|
||||
}
|
||||
|
||||
static void GroupDetails_SetDescription(HWND hwnd, SetupGroup *group)
|
||||
{
|
||||
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
|
||||
if (NULL == hDescription) return;
|
||||
|
||||
WCHAR szBuffer[4096] = {0};
|
||||
if (NULL == group ||
|
||||
FAILED(group->GetDescription(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
szBuffer[0] = L'\0';
|
||||
}
|
||||
|
||||
SetupDetails_SetDescription(hDescription, szBuffer);
|
||||
}
|
||||
|
||||
static BOOL GroupDetails_ShowHelp(HWND hwnd)
|
||||
{
|
||||
INT result = (INT)(INT_PTR)ShellExecuteW(hwnd, L"open",
|
||||
L"https://help.winamp.com/hc/articles/8112753225364-Online-Services-Security",
|
||||
NULL, NULL, SW_SHOWNORMAL);
|
||||
return (result > 32);
|
||||
}
|
||||
|
||||
static void GroupDetails_UpdateLayout(HWND hwnd, BOOL fRedraw)
|
||||
{
|
||||
RECT clientRect, rect;
|
||||
if(FALSE == GetClientRect(hwnd, &clientRect))
|
||||
return;
|
||||
|
||||
|
||||
UINT commonFlags = SWP_NOACTIVATE | SWP_NOZORDER;
|
||||
if (FALSE != fRedraw) commonFlags |= SWP_NOREDRAW;
|
||||
|
||||
LONG bottomLine = clientRect.bottom;
|
||||
|
||||
HWND hControl;
|
||||
SIZE linkSize;
|
||||
RECT linkMargins;
|
||||
|
||||
if (NULL != (hControl = GetDlgItem(hwnd, IDC_HELPLINK)) &&
|
||||
CommandLink_GetIdealSize(hControl, &linkSize))
|
||||
{
|
||||
if (!CommandLink_GetMargins(hControl, &linkMargins))
|
||||
SetRectEmpty(&linkMargins);
|
||||
|
||||
if (linkSize.cy > 0)
|
||||
bottomLine -= linkSize.cy;
|
||||
|
||||
SetWindowPos(hControl, NULL, clientRect.left + 4, bottomLine, linkSize.cx, linkSize.cy, commonFlags);
|
||||
}
|
||||
else
|
||||
{
|
||||
ZeroMemory(&linkSize, sizeof(linkSize));
|
||||
SetRectEmpty(&linkMargins);
|
||||
}
|
||||
|
||||
if (NULL != (hControl = GetDlgItem(hwnd, IDC_HELPTEXT)))
|
||||
{
|
||||
LONG x = clientRect.left + 4 + linkSize.cx/* - linkMargins.right*/;
|
||||
LONG y = 0;
|
||||
|
||||
HDC hdc = GetDCEx(hControl, NULL, DCX_CACHE | DCX_WINDOW | DCX_NORESETATTRS);
|
||||
if (NULL != hdc)
|
||||
{
|
||||
HFONT font = (HFONT)SendMessage(hControl, WM_GETFONT, 0, 0L);
|
||||
HFONT originalFont = (HFONT)SelectObject(hdc, font);
|
||||
|
||||
TEXTMETRICW tm;
|
||||
if (GetTextMetricsW(hdc, &tm))
|
||||
y = tm.tmHeight;
|
||||
|
||||
SelectObject(hdc, originalFont);
|
||||
ReleaseDC(hControl, hdc);
|
||||
}
|
||||
|
||||
SetWindowPos(hControl, NULL, x, clientRect.bottom - linkMargins.bottom - y, clientRect.right - x, y, commonFlags);
|
||||
}
|
||||
|
||||
if (NULL != (hControl = GetDlgItem(hwnd, IDC_DESCRIPTION)) &&
|
||||
FALSE != GetWindowRect(hControl, &rect))
|
||||
{
|
||||
MapWindowPoints(HWND_DESKTOP, hwnd, (POINT*)&rect, 2);
|
||||
SetWindowPos(hControl, NULL, rect.left, rect.right, rect.right - rect.left, bottomLine - rect.top,
|
||||
commonFlags | SWP_NOMOVE);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR GroupDetails_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
|
||||
{
|
||||
GROUPDETAILSCREATEPARAM *param = (GROUPDETAILSCREATEPARAM*)lParam;
|
||||
|
||||
GROUPDETAILS *details = (GROUPDETAILS*)calloc(1, sizeof(GROUPDETAILS));
|
||||
if (NULL == details) return FALSE;
|
||||
|
||||
if (!SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), details))
|
||||
return FALSE;
|
||||
|
||||
if (NULL != param)
|
||||
{
|
||||
if (NULL != param->group)
|
||||
{
|
||||
details->group = param->group;
|
||||
details->group->AddRef();
|
||||
}
|
||||
|
||||
details->name = Plugin_CopyString(param->name);
|
||||
}
|
||||
|
||||
HINSTANCE winampInstance = (NULL != WASABI_API_APP) ? WASABI_API_APP->main_gethInstance() : NULL;
|
||||
if (NULL != winampInstance)
|
||||
{
|
||||
WCHAR szBuffer[256] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_CLICKHERE, szBuffer, ARRAYSIZE(szBuffer));
|
||||
HWND hLink = CreateWindowExW(WS_EX_NOPARENTNOTIFY | WS_EX_TRANSPARENT, NWC_COMMANDLINKW, szBuffer,
|
||||
WS_VISIBLE | WS_CHILD | WS_TABSTOP | CLS_ALWAYSUNDERLINE | CLS_DEFAULTCOLORS /* | CLS_HOTTRACK */,
|
||||
0, 0, 0, 0, hwnd, (HMENU)IDC_HELPLINK, winampInstance, NULL);
|
||||
|
||||
if (NULL != hLink)
|
||||
{
|
||||
SendMessageW(hLink, WM_SETFONT, (WPARAM)SendMessageW(hwnd, WM_GETFONT, 0, 0L), 0L);
|
||||
}
|
||||
}
|
||||
|
||||
GroupDetails_UpdateLayout(hwnd, FALSE);
|
||||
|
||||
if (NULL != param)
|
||||
{
|
||||
GroupDetails_SetTitle(hwnd, param->group);
|
||||
GroupDetails_SetDescription(hwnd, param->group);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void GroupDetails_OnDestroy(HWND hwnd)
|
||||
{
|
||||
GROUPDETAILS *details = GetDetails(hwnd);
|
||||
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
|
||||
|
||||
if (NULL != details)
|
||||
{
|
||||
if (NULL != details->group)
|
||||
details->group->Release();
|
||||
if (NULL != details->fontTitle)
|
||||
DeleteObject(details->fontTitle);
|
||||
|
||||
Plugin_FreeString(details->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INT_PTR GroupDetails_OnDialogColor(HWND hwnd, HDC hdc, HWND hControl)
|
||||
{
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static INT_PTR GroupDetails_OnStaticColor(HWND hwnd, HDC hdc, HWND hControl)
|
||||
{
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT GroupDetails_OnNotify(HWND hwnd, INT controlId, NMHDR *pnmh)
|
||||
{
|
||||
switch(controlId)
|
||||
{
|
||||
case IDC_HELPLINK:
|
||||
if (NM_CLICK == pnmh->code)
|
||||
GroupDetails_ShowHelp(hwnd);
|
||||
return TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL GroupDetails_OnGetUniqueName(HWND hwnd, LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return FALSE;
|
||||
|
||||
GROUPDETAILS *details = GetDetails(hwnd);
|
||||
return SUCCEEDED(StringCchCopy(pszBuffer, cchBufferMax,
|
||||
(NULL != details && NULL != details->name) ? details->name : L""));
|
||||
}
|
||||
static INT_PTR WINAPI GroupDetails_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return GroupDetails_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: GroupDetails_OnDestroy(hwnd); break;
|
||||
case WM_CTLCOLORDLG: return GroupDetails_OnDialogColor(hwnd, (HDC)wParam, (HWND)lParam);
|
||||
case WM_CTLCOLORSTATIC: return GroupDetails_OnStaticColor(hwnd, (HDC)wParam, (HWND)lParam);
|
||||
case WM_NOTIFY: MSGRESULT(hwnd, GroupDetails_OnNotify(hwnd, (INT)wParam, (NMHDR*)lParam));
|
||||
|
||||
case NSDM_GETUNIQUENAME: MSGRESULT(hwnd, GroupDetails_OnGetUniqueName(hwnd, (LPWSTR)lParam, (UINT)wParam));
|
||||
}
|
||||
return 0;
|
||||
}
|
596
Src/Plugins/Library/ml_online/Setup/setupDetailsService.cpp
Normal file
596
Src/Plugins/Library/ml_online/Setup/setupDetailsService.cpp
Normal file
|
@ -0,0 +1,596 @@
|
|||
#include "./setupDetails.h"
|
||||
#include "../common.h"
|
||||
#include "../resource.h"
|
||||
#include "../wasabi.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omservicedetails.h>
|
||||
#include <ifc_omcachemanager.h>
|
||||
#include <ifc_omserviceevent.h>
|
||||
#include <ifc_omcachegroup.h>
|
||||
#include <ifc_omcacherecord.h>
|
||||
#include <ifc_imageloader.h>
|
||||
#include <ifc_omgraphics.h>
|
||||
#include <ifc_omserviceeventmngr.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
|
||||
|
||||
#define GetPanel(__hwnd) ((ServicePanel*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
|
||||
|
||||
#define GET_IDETAILS(__service, __details)\
|
||||
(NULL != (service) && SUCCEEDED((service)->QueryInterface(IFC_OmServiceDetails, (void**)&(__details))))
|
||||
|
||||
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
|
||||
HWND OmSetupDetails_CreateServiceView(HWND hParent, ifc_omservice *service)
|
||||
{
|
||||
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_SERVICEDETAILS, hParent, ServicePanel_DialogProc, (LPARAM)service);
|
||||
}
|
||||
|
||||
static HFONT ServicePanel_PickTitleFont(HWND hwnd, LPCWSTR pszTitle, INT cchTitle, INT maxWidth)
|
||||
{
|
||||
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||||
|
||||
LOGFONT lf;
|
||||
if (0 == GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
return NULL;
|
||||
|
||||
HFONT titleFont = NULL;
|
||||
if (cchTitle > 0)
|
||||
{
|
||||
LOGFONT lf;
|
||||
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
|
||||
lf.lfWidth = 0;
|
||||
lf.lfWeight = FW_DONTCARE;
|
||||
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
|
||||
|
||||
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != hdc)
|
||||
{
|
||||
HFONT origFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
|
||||
SIZE textSize;
|
||||
|
||||
INT heightLimit = (lf.lfHeight < 0) ? 1 : -1;
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
|
||||
do
|
||||
{
|
||||
textSize.cx = 0;
|
||||
if (NULL != titleFont) DeleteObject(titleFont);
|
||||
titleFont = CreateFontIndirect(&lf);
|
||||
if (NULL != titleFont)
|
||||
{
|
||||
SelectObject(hdc, titleFont);
|
||||
GetTextExtentPoint32(hdc, pszTitle, cchTitle, &textSize);
|
||||
}
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
|
||||
|
||||
} while(textSize.cx > maxWidth && lf.lfHeight != heightLimit);
|
||||
|
||||
if (0 == textSize.cx)
|
||||
{
|
||||
DeleteObject(titleFont);
|
||||
titleFont = NULL;
|
||||
}
|
||||
|
||||
SelectObject(hdc, origFont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == titleFont &&
|
||||
0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
titleFont = CreateFontIndirect(&lf);
|
||||
}
|
||||
return titleFont;
|
||||
}
|
||||
|
||||
static void ServicePanel_SetServiceName(HWND hwnd, ifc_omservice *service)
|
||||
{
|
||||
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
|
||||
if (NULL == hTitle) return;
|
||||
|
||||
WCHAR szBuffer[128];
|
||||
if (NULL == service ||
|
||||
FAILED(service->GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
szBuffer[0] = L'\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
SERVICEDETAILS *details = GetDetails(hwnd);
|
||||
if (NULL != details)
|
||||
{
|
||||
INT cchBuffer = lstrlen(szBuffer);
|
||||
RECT rc;
|
||||
GetClientRect(hTitle, &rc);
|
||||
HFONT titleFont = ServicePanel_PickTitleFont(hwnd, szBuffer, cchBuffer, rc.right - rc.left);
|
||||
if (NULL != titleFont)
|
||||
{
|
||||
if (NULL != details->fontTitle) DeleteObject(details->fontTitle);
|
||||
details->fontTitle = titleFont;
|
||||
SendMessage(hTitle, WM_SETFONT, (WPARAM)details->fontTitle, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowText(hTitle, szBuffer);
|
||||
InvalidateRect(hTitle, NULL, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static void ServicePanel_SetServiceDescription(HWND hwnd, ifc_omservice *service)
|
||||
{
|
||||
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
|
||||
if (NULL == hDescription) return;
|
||||
|
||||
WCHAR szBuffer[4096] = {0};
|
||||
|
||||
ifc_omservicedetails *details = 0;
|
||||
if (GET_IDETAILS(service, details))
|
||||
{
|
||||
details->GetDescription(szBuffer, ARRAYSIZE(szBuffer));
|
||||
details->Release();
|
||||
}
|
||||
|
||||
OmSetupDetails_SetDescription(hDescription, szBuffer);
|
||||
}
|
||||
|
||||
static LPCWSTR ServicePanel_FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
ZeroMemory(&st, sizeof(SYSTEMTIME));
|
||||
LPCWSTR cursor;
|
||||
|
||||
cursor = pszDate;
|
||||
INT index = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
INT iVal;
|
||||
|
||||
if (FALSE == StrToIntEx(cursor, STIF_DEFAULT, &iVal) || iVal < 1)
|
||||
{
|
||||
index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == index)
|
||||
{
|
||||
if (iVal < 2000 || iVal > 2100)
|
||||
break;
|
||||
st.wYear = iVal;
|
||||
index++;
|
||||
}
|
||||
else if (1 == index)
|
||||
{
|
||||
if (iVal < 1 || iVal > 12)
|
||||
break;
|
||||
st.wMonth = iVal;
|
||||
index++;
|
||||
}
|
||||
else if (2 == index)
|
||||
{
|
||||
if (iVal < 1 || iVal > 31)
|
||||
break;
|
||||
st.wDay = iVal;
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
while(L'\0' != *cursor && L'-' != *cursor) cursor++;
|
||||
if (L'-' == *cursor) cursor++;
|
||||
if (L'\0' == *cursor)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (3 == index &&
|
||||
0 != GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszBuffer, cchBufferMax))
|
||||
{
|
||||
return pszBuffer;
|
||||
}
|
||||
|
||||
return pszDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static HRESULT ServicePanel_GetFullName(ifc_omservicedetails *details, LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
|
||||
*pszBuffer = L'\0';
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
if (NULL != details)
|
||||
{
|
||||
hr = details->GetAuthorFirst(pszBuffer, cchBufferMax);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT cchBuffer = lstrlen(pszBuffer);
|
||||
LPWSTR cursor = pszBuffer + cchBuffer;
|
||||
size_t remaining = cchBufferMax - cchBuffer;
|
||||
|
||||
if (cursor != pszBuffer)
|
||||
{
|
||||
hr = StringCchCopyEx(cursor, remaining, L" ", &cursor, &remaining, 0);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = details->GetAuthorLast(cursor, (UINT)remaining);
|
||||
if (FAILED(hr) || L'\0' == *cursor)
|
||||
{
|
||||
pszBuffer[cchBuffer] = L'\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static void ServicePanel_SetServiceMeta(HWND hwnd, ifc_omservice *service)
|
||||
{
|
||||
HWND hMeta = GetDlgItem(hwnd, IDC_SERVICEMETA);
|
||||
if (NULL == hMeta) return;
|
||||
|
||||
WCHAR szBuffer[512] = {0};
|
||||
|
||||
ifc_omservicedetails *svcdetails = 0;
|
||||
if (GET_IDETAILS(service, svcdetails))
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
LPWSTR cursor = szBuffer;
|
||||
WCHAR szValue[256] = {0}, szPrefix[64] = {0};
|
||||
size_t remaining = ARRAYSIZE(szBuffer);
|
||||
|
||||
if (SUCCEEDED(ServicePanel_GetFullName(svcdetails, szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_BYAUTHOR, szPrefix, ARRAYSIZE(szPrefix));
|
||||
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
L"%s%s", szPrefix, szValue);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(svcdetails->GetUpdated(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
|
||||
{
|
||||
if (cursor != szBuffer)
|
||||
hr = StringCchCopyEx(cursor, remaining, L"\r\n", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
WCHAR szDate[128] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_LASTUPDATED, szPrefix, ARRAYSIZE(szPrefix));
|
||||
StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
L"%s%s", szPrefix, ServicePanel_FormatDate(szValue, szDate, ARRAYSIZE(szDate)));
|
||||
}
|
||||
}
|
||||
|
||||
svcdetails->Release();
|
||||
|
||||
}
|
||||
|
||||
SERVICEDETAILS *details = GetDetails(hwnd);
|
||||
if (NULL != details && NULL == details->fontMeta)
|
||||
{
|
||||
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||||
LOGFONT lf;
|
||||
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma");
|
||||
lf.lfWidth = 0;
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
|
||||
lf.lfQuality = ANTIALIASED_QUALITY;
|
||||
details->fontMeta = CreateFontIndirect(&lf);
|
||||
}
|
||||
|
||||
if (NULL != details->fontMeta)
|
||||
{
|
||||
SendMessage(hMeta, WM_SETFONT, (WPARAM)details->fontMeta, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowText(hMeta, szBuffer);
|
||||
if (0 != ShowWindow(hMeta, (L'\0' != szBuffer[0]) ? SW_SHOWNA : SW_HIDE))
|
||||
InvalidateRect(hMeta, NULL, TRUE);
|
||||
}
|
||||
|
||||
static void ServicePanel_SetThumbnail(HWND hwnd, ifc_omservice *service)
|
||||
{
|
||||
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
|
||||
if (NULL == hThumbnail) return;
|
||||
|
||||
SendMessage(hThumbnail, WM_SETREDRAW, FALSE, 0L);
|
||||
|
||||
HBITMAP hBitmap;
|
||||
|
||||
BITMAPINFOHEADER header;
|
||||
void *pixelData;
|
||||
|
||||
WCHAR szPath[2048];
|
||||
|
||||
ifc_omservicedetails *details = 0;
|
||||
if (GET_IDETAILS(service, details))
|
||||
{
|
||||
if (SUCCEEDED(details->GetThumbnail(szPath, ARRAYSIZE(szPath))))
|
||||
{
|
||||
ifc_omcachemanager *cacheManager;
|
||||
if (SUCCEEDED(OMUTILITY->GetCacheManager(&cacheManager)))
|
||||
{
|
||||
ifc_omcachegroup *cacheGroup;
|
||||
if (SUCCEEDED(cacheManager->Find(L"thumbnail", TRUE, &cacheGroup, NULL)))
|
||||
{
|
||||
ifc_omcacherecord *cacheRecord;
|
||||
if (SUCCEEDED(cacheGroup->Find(szPath, TRUE, &cacheRecord, FALSE)))
|
||||
{
|
||||
cacheRecord->Release();
|
||||
}
|
||||
cacheGroup->Release();
|
||||
}
|
||||
cacheManager->Release();
|
||||
}
|
||||
}
|
||||
details->Release();
|
||||
}
|
||||
|
||||
ifc_omimageloader *imageLoader;
|
||||
if (SUCCEEDED(OMUTILITY->QueryImageLoader(NULL, szPath, FALSE, &imageLoader)))
|
||||
{
|
||||
if (FAILED(imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData)))
|
||||
hBitmap = NULL;
|
||||
imageLoader->Release();
|
||||
}
|
||||
|
||||
if (NULL == hBitmap &&
|
||||
SUCCEEDED(OMUTILITY->QueryImageLoader(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_SERVICE64X64_IMAGE), FALSE, &imageLoader)))
|
||||
{
|
||||
if (FAILED(imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData)))
|
||||
hBitmap = NULL;
|
||||
imageLoader->Release();
|
||||
}
|
||||
|
||||
HBITMAP hTest = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
|
||||
if (NULL != hTest)
|
||||
DeleteObject(hTest);
|
||||
|
||||
if (NULL != hBitmap)
|
||||
{
|
||||
hTest = (HBITMAP)SendMessage(hThumbnail, STM_GETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if (hTest != hBitmap)
|
||||
{ // this is XP and up image copy was created and alpha channel will be handled properly
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
else
|
||||
{ // fix alpha channel
|
||||
if (32 == header.biBitCount)
|
||||
{
|
||||
HDC hdcFixed = CreateCompatibleDC(NULL);
|
||||
if (NULL != hdcFixed)
|
||||
{
|
||||
BITMAPINFOHEADER headerFixed;
|
||||
CopyMemory(&headerFixed, &header, sizeof(BITMAPINFOHEADER));
|
||||
BYTE *pixelsFixed;
|
||||
INT cx = header.biWidth;
|
||||
INT cy = abs(header.biHeight);
|
||||
HBITMAP bitmapFixed = CreateDIBSection(NULL, (LPBITMAPINFO)&headerFixed, DIB_RGB_COLORS, (void**)&pixelsFixed, NULL, 0);
|
||||
|
||||
if (NULL != bitmapFixed)
|
||||
{
|
||||
HBITMAP bitmapOrig = (HBITMAP)SelectObject(hdcFixed, bitmapFixed);
|
||||
HBRUSH hb = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdcFixed, (LPARAM)hwnd);
|
||||
if (NULL == hb)
|
||||
hb = GetSysColorBrush(COLOR_3DFACE);
|
||||
RECT rect;
|
||||
SetRect(&rect, 0, 0, cx, cy);
|
||||
FillRect(hdcFixed, &rect, hb);
|
||||
|
||||
ifc_omgraphics *graphics;
|
||||
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
|
||||
{
|
||||
HDC hdcSrc = CreateCompatibleDC(NULL);
|
||||
if (NULL != hdcSrc)
|
||||
{
|
||||
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
|
||||
BLENDFUNCTION bf;
|
||||
bf.BlendOp = AC_SRC_OVER;
|
||||
bf.BlendFlags = 0;
|
||||
bf.SourceConstantAlpha = 0xFF;
|
||||
bf.AlphaFormat = AC_SRC_ALPHA;
|
||||
|
||||
RECT blendRect;
|
||||
SetRect(&blendRect, 0, 0, cx, cy);
|
||||
|
||||
graphics->Premultiply((BYTE*)pixelData, cx, cy);
|
||||
graphics->AlphaBlend(hdcFixed, &blendRect, hdcSrc, &blendRect, bf);
|
||||
|
||||
SelectObject(hdcSrc, bitmapSrcOrig);
|
||||
DeleteDC(hdcSrc);
|
||||
}
|
||||
graphics->Release();
|
||||
}
|
||||
|
||||
SelectObject(hdcFixed, bitmapOrig);
|
||||
SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmapFixed);
|
||||
DeleteObject(hBitmap);
|
||||
|
||||
}
|
||||
DeleteDC(hdcFixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RECT clientRect;
|
||||
if (GetClientRect(hThumbnail, &clientRect))
|
||||
{
|
||||
INT cx = clientRect.right - clientRect.left;
|
||||
INT cy = clientRect.bottom - clientRect.top;
|
||||
if (64 != cx || 64 != cy)
|
||||
{
|
||||
SetWindowPos(hThumbnail, NULL, 0, 0, 64, 64, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(hThumbnail, WM_SETREDRAW, TRUE, 0L);
|
||||
|
||||
if (0 != ShowWindow(hThumbnail, (NULL != hBitmap) ? SW_SHOWNA : SW_HIDE))
|
||||
InvalidateRect(hThumbnail, NULL, TRUE);
|
||||
}
|
||||
|
||||
|
||||
static void CALLBACK ServicePanel_OnServiceNotify(UINT serviceUid, UINT callbackType, UINT callbackParam, ULONG_PTR user)
|
||||
{
|
||||
HWND hwnd = (HWND)user;
|
||||
if (NULL == hwnd) return;
|
||||
|
||||
SERVICEDETAILS *details = GetDetails(hwnd);
|
||||
|
||||
if (NULL == details ||
|
||||
NULL == details->service ||
|
||||
serviceUid != details->service->GetId())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch(callbackType)
|
||||
{
|
||||
case OmService::eventServiceModified:
|
||||
if (0 != (OmService::modifiedName & callbackParam))
|
||||
ServicePanel_SetServiceName(hwnd, details->service);
|
||||
if (0 != (OmService::modifiedDescription & callbackParam))
|
||||
ServicePanel_SetServiceDescription(hwnd, details->service);
|
||||
if (0 != ((OmService::modifiedAuthor | OmService::modifiedDate) & callbackParam))
|
||||
ServicePanel_SetServiceMeta(hwnd, details->service);
|
||||
if (0 != (OmService::modifiedThumbnail & callbackParam))
|
||||
ServicePanel_SetThumbnail(hwnd, details->service);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR ServicePanel_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
|
||||
{
|
||||
ifc_omservice *service = (ifc_omservice*)lParam;
|
||||
|
||||
SERVICEDETAILS *details = (SERVICEDETAILS*)malloc(sizeof(SERVICEDETAILS));
|
||||
if (NULL == details) return FALSE;
|
||||
ZeroMemory(details, sizeof(SERVICEDETAILS));
|
||||
|
||||
if (!SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), details))
|
||||
return FALSE;
|
||||
|
||||
details->service = service;
|
||||
details->service->AddRef();
|
||||
|
||||
ServicePanel_SetServiceName(hwnd, service);
|
||||
ServicePanel_SetServiceDescription(hwnd, service);
|
||||
ServicePanel_SetThumbnail(hwnd, service);
|
||||
ServicePanel_SetServiceMeta(hwnd, service);
|
||||
|
||||
if (NULL != service)
|
||||
{
|
||||
ifc_omserviceeventmngr *eventManager;
|
||||
if (SUCCEEDED(service->GetEventManager(&eventManager)))
|
||||
{
|
||||
if (SUCCEEDED(eventManager->RegisterHandler(eventHander)))
|
||||
{
|
||||
details->eventHandler = eventHandler;
|
||||
}
|
||||
else
|
||||
{
|
||||
eventHandler->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void ServicePanel_OnDestroy(HWND hwnd)
|
||||
{
|
||||
OMSERVICEMNGR->UnregisterCallback(ServicePanel_OnServiceNotify, (ULONG_PTR)hwnd);
|
||||
|
||||
SERVICEDETAILS *details = GetDetails(hwnd);
|
||||
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
|
||||
|
||||
if (NULL != details)
|
||||
{
|
||||
if (NULL != details->service)
|
||||
details->service->Release();
|
||||
if (NULL != details->fontTitle)
|
||||
DeleteObject(details->fontTitle);
|
||||
if (NULL != details->fontMeta)
|
||||
DeleteObject(details->fontMeta);
|
||||
}
|
||||
|
||||
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
|
||||
if (NULL != hThumbnail)
|
||||
{
|
||||
HBITMAP hBitmap = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if (NULL != hBitmap)
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static INT_PTR ServicePanel_OnDialogColor(HWND hwnd, HDC hdc, HWND hControl)
|
||||
{
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static INT_PTR ServicePanel_OnStaticColor(HWND hwnd, HDC hdc, HWND hControl)
|
||||
{
|
||||
INT_PTR result = 0;
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
result = (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
|
||||
|
||||
INT controlId = GetDlgCtrlID(hControl);
|
||||
switch(controlId)
|
||||
{
|
||||
case IDC_SERVICEMETA:
|
||||
{
|
||||
COLORREF rgbBk = GetBkColor(hdc);
|
||||
COLORREF rgbFg = GetTextColor(hdc);
|
||||
|
||||
ifc_omgraphics *graphics;
|
||||
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
|
||||
{
|
||||
graphics->BlendColor(rgbFg, rgbBk, 180, &rgbFg);
|
||||
graphics->Release();
|
||||
}
|
||||
|
||||
SetTextColor(hdc, rgbFg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return ServicePanel_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: ServicePanel_OnDestroy(hwnd); break;
|
||||
case WM_CTLCOLORDLG: return ServicePanel_OnDialogColor(hwnd, (HDC)wParam, (HWND)lParam);
|
||||
case WM_CTLCOLORSTATIC: return ServicePanel_OnStaticColor(hwnd, (HDC)wParam, (HWND)lParam);
|
||||
}
|
||||
return 0;
|
||||
}
|
929
Src/Plugins/Library/ml_online/Setup/setupGroup.cpp
Normal file
929
Src/Plugins/Library/ml_online/Setup/setupGroup.cpp
Normal file
|
@ -0,0 +1,929 @@
|
|||
#include "./setupGroup.h"
|
||||
#include "./setupGroupFilter.h"
|
||||
#include "./setupListboxLabel.h"
|
||||
#include "./setupDetails.h"
|
||||
#include "./setupPage.h"
|
||||
#include "../common.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include "../resource.h"
|
||||
#include "../serviceHost.h"
|
||||
#include "../serviceHelper.h"
|
||||
|
||||
#include "../../nu/menuHelpers.h"
|
||||
#include <vector>
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omstorage.h>
|
||||
#include <ifc_omstorageasync.h>
|
||||
#include <ifc_omserviceenum.h>
|
||||
#include <ifc_omfilestorage.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
#include <algorithm>
|
||||
|
||||
typedef std::vector<ifc_omservice*> ServiceList;
|
||||
|
||||
#define GROUP_MARGINCX 0
|
||||
#define GROUP_MARGINCY 1
|
||||
|
||||
#define TEXT_OFFSET_LEFT 2
|
||||
#define TEXT_OFFSET_BOTTOM 2
|
||||
#define TEXT_ALIGN (TA_LEFT | TA_BOTTOM)
|
||||
|
||||
SetupGroup::SetupGroup(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle)
|
||||
: ref(1), id(groupId), name(NULL), flags(0), emptyLabel(NULL), errorCode(S_OK), hPage(NULL),
|
||||
longName(NULL), description(NULL), address(NULL), loadResult(NULL), style(fStyle), loadComplete(NULL)
|
||||
{
|
||||
name = Plugin_DuplicateResString(pszName);
|
||||
address = Plugin_DuplicateResString(pszAddress);
|
||||
this->storageId = (NULL != storageId) ? *storageId : GUID_NULL;
|
||||
this->filterId = (NULL != filterId) ? *filterId : GUID_NULL;
|
||||
|
||||
InitializeCriticalSection(&lock);
|
||||
}
|
||||
|
||||
SetupGroup::~SetupGroup()
|
||||
{
|
||||
Plugin_FreeResString(name);
|
||||
Plugin_FreeResString(address);
|
||||
|
||||
SetLongName(NULL);
|
||||
SetDescription(NULL);
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
list[index]->Release();
|
||||
}
|
||||
|
||||
if (NULL != emptyLabel)
|
||||
emptyLabel->Release();
|
||||
|
||||
if (NULL != loadResult)
|
||||
{
|
||||
ifc_omstorage *storage;
|
||||
HRESULT hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
storage->RequestAbort(loadResult, TRUE);
|
||||
}
|
||||
|
||||
loadResult->Release();
|
||||
loadResult = NULL;
|
||||
}
|
||||
|
||||
if (NULL != loadComplete)
|
||||
CloseHandle(loadComplete);
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
DeleteCriticalSection(&lock);
|
||||
|
||||
}
|
||||
|
||||
SetupGroup *SetupGroup::CreateInstance(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle)
|
||||
{
|
||||
return new SetupGroup(groupId, pszName, pszAddress, storageId, filterId, fStyle);
|
||||
}
|
||||
|
||||
ULONG SetupGroup::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupGroup::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
return r;
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::GetName(LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
|
||||
HRESULT hr;
|
||||
if (NULL != name)
|
||||
{
|
||||
if (IS_INTRESOURCE(name))
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)name, pszBuffer, cchBufferMax);
|
||||
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StringCchCopyW(pszBuffer, cchBufferMax, name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StringCchCopyW(pszBuffer, cchBufferMax, L"Unknown");
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::GetLongName(LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
|
||||
HRESULT hr;
|
||||
if (NULL == longName)
|
||||
return GetName(pszBuffer, cchBufferMax);
|
||||
|
||||
if (IS_INTRESOURCE(longName))
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)longName, pszBuffer, cchBufferMax);
|
||||
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StringCchCopyW(pszBuffer, cchBufferMax, longName);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::GetDescription(LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (NULL != description && IS_INTRESOURCE(description))
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)description, pszBuffer, cchBufferMax);
|
||||
hr = (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = StringCchCopyEx(pszBuffer, cchBufferMax, description, NULL, NULL, STRSAFE_IGNORE_NULLS);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
size_t SetupGroup::GetRecordCount()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
size_t SetupGroup::GetListboxCount()
|
||||
{
|
||||
if (0 != (flagCollapsed & flags)) return 0;
|
||||
size_t listSize = list.size();
|
||||
|
||||
if (0 == listSize)
|
||||
{
|
||||
return (NULL != emptyLabel && FALSE == emptyLabel->IsNameNull()) ? 1 : 0;
|
||||
}
|
||||
|
||||
return listSize;
|
||||
}
|
||||
|
||||
SetupListboxItem *SetupGroup::GetListboxItem(size_t index)
|
||||
{
|
||||
if (0 != (flagCollapsed & flags)) return NULL;
|
||||
size_t listSize = list.size();
|
||||
|
||||
if (0 == listSize)
|
||||
{
|
||||
return (NULL != emptyLabel && FALSE == emptyLabel->IsNameNull()) ? emptyLabel : NULL;
|
||||
}
|
||||
return list[index];
|
||||
}
|
||||
|
||||
BOOL SetupGroup::IsModified()
|
||||
{
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (list[index]->IsModified())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupGroup::IsExpanded()
|
||||
{
|
||||
return (0 == (flagCollapsed & flags));
|
||||
}
|
||||
|
||||
void SetupGroup::SetExpanded(BOOL fExpanded)
|
||||
{
|
||||
if ((FALSE == fExpanded) == (FALSE == IsExpanded()))
|
||||
return;
|
||||
|
||||
if (FALSE == fExpanded)
|
||||
flags |= flagCollapsed;
|
||||
else
|
||||
flags &= ~flagCollapsed;
|
||||
}
|
||||
|
||||
void SetupGroup::Clear(BOOL fInvalidate)
|
||||
{
|
||||
size_t index = list.size();
|
||||
if (0 == index) return;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
while(index--)
|
||||
{
|
||||
SetupRecord *record = list[index];
|
||||
if (NULL != record)
|
||||
{
|
||||
record->Release();
|
||||
}
|
||||
}
|
||||
list.clear();
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_EMPTYGROUP), FALSE);
|
||||
|
||||
if (FALSE != fInvalidate && NULL != hPage)
|
||||
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)id, NULL);
|
||||
}
|
||||
|
||||
static void CALLBACK SetupGroup_LoadCallback(ifc_omstorageasync *result)
|
||||
{
|
||||
if (NULL == result) return;
|
||||
SetupGroup *group;
|
||||
if (SUCCEEDED(result->GetData((void**)&group)) && NULL != group)
|
||||
{
|
||||
group->OnLoadCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
__inline static int __cdecl SetupGroup_AlphabeticalSorter(const void *elem1, const void *elem2)
|
||||
{
|
||||
SetupRecord *record1 = (SetupRecord*)elem1;
|
||||
SetupRecord *record2 = (SetupRecord*)elem2;
|
||||
|
||||
if (NULL == record1 || NULL == record2)
|
||||
return (INT)(INT_PTR)(record1 - record2);
|
||||
|
||||
ifc_omservice *svc1 = record1->GetService();
|
||||
ifc_omservice *svc2 = record2->GetService();
|
||||
|
||||
if (NULL == svc1 || NULL == svc2)
|
||||
return (INT)(INT_PTR)(svc1 - svc2);
|
||||
|
||||
WCHAR szBuffer1[256] = {0}, szBuffer2[256] = {0};
|
||||
if (FAILED(svc1->GetName(szBuffer1, ARRAYSIZE(szBuffer1))))
|
||||
szBuffer1[0] = L'\0';
|
||||
if (FAILED(svc2->GetName(szBuffer2, ARRAYSIZE(szBuffer2))))
|
||||
szBuffer2[0] = L'\0';
|
||||
|
||||
return CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, szBuffer1, -1, szBuffer2, -1) - 2;
|
||||
}
|
||||
|
||||
__inline static bool __cdecl SetupGroup_AlphabeticalSorter_V2(const void* elem1, const void* elem2)
|
||||
{
|
||||
return SetupGroup_AlphabeticalSorter(elem1, elem2) < 0;
|
||||
}
|
||||
void SetupGroup::OnLoadCompleted()
|
||||
{
|
||||
ifc_omstorage *storage;
|
||||
HRESULT hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ifc_omserviceenum *serviceEnum;
|
||||
hr = storage->EndLoad(loadResult, &serviceEnum);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
SetupGroupFilter *filter;
|
||||
if (FAILED(SetupGroupFilter::CreateInstance(&filterId, &filter)))
|
||||
{
|
||||
filter = NULL;
|
||||
}
|
||||
else if (FAILED(filter->Initialize()))
|
||||
{
|
||||
filter->Release();
|
||||
filter = NULL;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
ifc_omservice *service;
|
||||
UINT filterResult, defaultFilter;
|
||||
defaultFilter = SetupGroupFilter::serviceInclude;
|
||||
if (0 != (styleDefaultUnsubscribed & style))
|
||||
defaultFilter |= SetupGroupFilter::serviceForceUnsubscribe;
|
||||
else if (0 != (styleDefaultSubscribed & style))
|
||||
defaultFilter |= SetupGroupFilter::serviceForceSubscribe;
|
||||
|
||||
while(S_OK == serviceEnum->Next(1, &service, NULL))
|
||||
{
|
||||
|
||||
filterResult = defaultFilter;
|
||||
if (NULL != filter && FAILED(filter->ProcessService(service, &filterResult)))
|
||||
filterResult = defaultFilter;
|
||||
|
||||
if (0 == (SetupGroupFilter::serviceInclude & filterResult))
|
||||
{
|
||||
service->Release();
|
||||
service = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 != (SetupGroupFilter::serviceForceUnsubscribe & filterResult))
|
||||
ServiceHelper_Subscribe(service, TRUE, 0);
|
||||
else if (0 != (SetupGroupFilter::serviceForceSubscribe & filterResult))
|
||||
ServiceHelper_Subscribe(service, FALSE, 0);
|
||||
|
||||
if (0 != (styleSaveAll & style))
|
||||
ServiceHelper_MarkModified(service, (UINT)-1, (UINT)-1);
|
||||
|
||||
SetupRecord *record = SetupRecord::CreateInstance(service);
|
||||
if (NULL != record)
|
||||
{
|
||||
if (0 != (SetupGroupFilter::serviceForceUnsubscribe & filterResult))
|
||||
record->SetSelected(FALSE);
|
||||
else if (0 != (SetupGroupFilter::serviceForceSubscribe & filterResult))
|
||||
record->SetSelected(TRUE);
|
||||
list.push_back(record);
|
||||
}
|
||||
|
||||
service->Release();
|
||||
}
|
||||
|
||||
if (0 != (styleSortAlphabetically & style))
|
||||
{
|
||||
//qsort(list.first(), list.size(), sizeof(SetupRecord*), SetupGroup_AlphabeticalSorter);
|
||||
std::sort(list.begin(), list.end(), SetupGroup_AlphabeticalSorter_V2);
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
serviceEnum->Release();
|
||||
if (NULL != filter)
|
||||
filter->Release();
|
||||
}
|
||||
|
||||
storage->Release();
|
||||
}
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
loadResult->Release();
|
||||
loadResult = NULL;
|
||||
|
||||
if (NULL != loadComplete)
|
||||
{
|
||||
SetEvent(loadComplete);
|
||||
CloseHandle(loadComplete);
|
||||
loadComplete = NULL;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
LPCWSTR pszText = MAKEINTRESOURCE(((FAILED(hr)) ? IDS_SETUP_GROUPLOADFAILED : IDS_SETUP_EMPTYGROUP));
|
||||
SetEmptyText( pszText, TRUE);
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::RequestReload()
|
||||
{
|
||||
if (NULL == OMSERVICEMNGR)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (NULL != loadResult)
|
||||
hr = E_PENDING;
|
||||
else
|
||||
{
|
||||
if (NULL != loadComplete)
|
||||
{
|
||||
CloseHandle(loadComplete);
|
||||
loadComplete = NULL;
|
||||
}
|
||||
|
||||
Clear(FALSE);
|
||||
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_LOADINGGROUP), TRUE);
|
||||
|
||||
ifc_omstorage *storage;
|
||||
hr = OMSERVICEMNGR->QueryStorage(&storageId, &storage);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ServiceHost *serviceHost;
|
||||
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
|
||||
serviceHost = NULL;
|
||||
|
||||
hr = storage->BeginLoad(address, serviceHost, SetupGroup_LoadCallback, this, &loadResult);
|
||||
storage->Release();
|
||||
|
||||
if (NULL != serviceHost)
|
||||
serviceHost->Release();
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SetEmptyText(MAKEINTRESOURCE(IDS_SETUP_GROUPLOADFAILED), TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void SetupGroup::SetPageWnd(HWND hPage)
|
||||
{
|
||||
this->hPage = hPage;
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::SignalLoadCompleted(HANDLE event)
|
||||
{
|
||||
HRESULT hr;
|
||||
if (NULL == event) return E_INVALIDARG;
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (NULL == loadResult)
|
||||
{
|
||||
SetEvent(event);
|
||||
hr = S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NULL != loadComplete)
|
||||
CloseHandle(loadComplete);
|
||||
|
||||
if (FALSE == DuplicateHandle(GetCurrentProcess(), event, GetCurrentProcess(), &loadComplete, 0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
hr = HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupGroup::Save(SetupLog *log)
|
||||
{
|
||||
HRESULT hr(S_OK);
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (FAILED(list[index]->Save(log)))
|
||||
hr = E_FAIL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
void SetupGroup::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
|
||||
{
|
||||
COLORREF rgbBk, rgbText;
|
||||
|
||||
|
||||
if (0 != (ODS_DISABLED & state))
|
||||
{
|
||||
rgbBk = GetBkColor(hdc);
|
||||
rgbText = GetSysColor(COLOR_GRAYTEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != (ODS_SELECTED & state))
|
||||
{
|
||||
if (0 == (ODS_INACTIVE & state))
|
||||
{
|
||||
rgbBk = GetSysColor(COLOR_HIGHLIGHT);
|
||||
rgbText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgbBk = GetSysColor(COLOR_3DFACE);
|
||||
rgbText = GetSysColor(COLOR_WINDOWTEXT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rgbBk = GetSysColor(COLOR_WINDOW);
|
||||
rgbText = GetSysColor(COLOR_WINDOWTEXT);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
|
||||
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
|
||||
}
|
||||
|
||||
HBRUSH SetupGroup::GetBrush(HDC hdc, UINT state)
|
||||
{
|
||||
if (0 != (ODS_DISABLED & state))
|
||||
{
|
||||
return GetSysColorBrush(COLOR_WINDOW);
|
||||
}
|
||||
if (0 != (ODS_COMBOBOXEDIT & state))
|
||||
{
|
||||
return GetSysColorBrush(COLOR_WINDOWTEXT);
|
||||
}
|
||||
if (0 != (ODS_SELECTED & state))
|
||||
{
|
||||
return GetSysColorBrush( (0 == (ODS_INACTIVE & state)) ? COLOR_HIGHLIGHT : COLOR_3DFACE);
|
||||
}
|
||||
|
||||
return GetSysColorBrush(COLOR_WINDOW);
|
||||
}
|
||||
|
||||
BOOL SetupGroup::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
|
||||
{
|
||||
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL == hdc) return FALSE;
|
||||
|
||||
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
|
||||
SIZE imageSize;
|
||||
if (!instance->GetExpandboxMetrics(hdc, IsExpanded(), &imageSize))
|
||||
ZeroMemory(&imageSize, sizeof(SIZE));
|
||||
|
||||
if (NULL != cy)
|
||||
{
|
||||
*cy = 0;
|
||||
TEXTMETRIC tm;
|
||||
if (GetTextMetrics(hdc, &tm))
|
||||
{
|
||||
*cy = tm.tmHeight + tm.tmExternalLeading;
|
||||
if (imageSize.cy > (INT)*cy) *cy = imageSize.cy;
|
||||
*cy += GROUP_MARGINCY*2;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != cx)
|
||||
{
|
||||
*cx = imageSize.cx;
|
||||
WCHAR szBuffer[128] = {0};
|
||||
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
INT cchBuffer = lstrlenW(szBuffer);
|
||||
SIZE textSize;
|
||||
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
|
||||
{
|
||||
*cx += textSize.cx;
|
||||
}
|
||||
}
|
||||
if (0 != *cx) *cx += GROUP_MARGINCX*2;
|
||||
}
|
||||
|
||||
SelectObject(hdc, originalFont);
|
||||
ReleaseDC(instance->GetHwnd(), hdc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void SetupGroup_DrawFrame(HDC hdc, const RECT *prc, INT width, COLORREF rgbFrame)
|
||||
{
|
||||
if (width > 0)
|
||||
{
|
||||
COLORREF rgbOld = SetBkColor(hdc, rgbFrame);
|
||||
|
||||
RECT rcPart;
|
||||
SetRect(&rcPart, prc->left, prc->top, prc->right, prc->top + width);
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
|
||||
SetRect(&rcPart, prc->left, prc->bottom - width, prc->right, prc->bottom);
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
|
||||
SetRect(&rcPart, prc->left, prc->top + width, prc->left + width, prc->bottom - width);
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
|
||||
SetRect(&rcPart, prc->right - width, prc->top + width, prc->right, prc->bottom - width);
|
||||
ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rcPart, NULL, 0, NULL);
|
||||
|
||||
if (rgbOld != rgbFrame)
|
||||
SetBkColor(hdc, rgbOld);
|
||||
}
|
||||
}
|
||||
BOOL SetupGroup::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
|
||||
{
|
||||
LONG paintLeft = prc->left + GROUP_MARGINCX;
|
||||
RECT partRect;
|
||||
|
||||
SetRectEmpty(&partRect);
|
||||
|
||||
COLORREF rgbBk, rgbText;
|
||||
GetColors(hdc, state, &rgbBk, &rgbText);
|
||||
|
||||
COLORREF origBk = SetBkColor(hdc, rgbBk);
|
||||
COLORREF origText = SetTextColor(hdc, rgbText);
|
||||
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
|
||||
|
||||
HRGN backRgn, rgn;
|
||||
backRgn = CreateRectRgnIndirect(prc);
|
||||
rgn = CreateRectRgn(0,0,0,0);
|
||||
|
||||
SetRectEmpty(&partRect);
|
||||
if (instance->GetExpandboxMetrics(hdc, IsExpanded(), (((SIZE*)&partRect) + 1)))
|
||||
{
|
||||
INT space = (prc->bottom - prc->top) - (partRect.bottom- partRect.top);
|
||||
INT offsetY = space / 2 + space%2;
|
||||
if (offsetY < 0) offsetY = 0;
|
||||
OffsetRect(&partRect, paintLeft, prc->top + offsetY);
|
||||
if (instance->DrawExpandbox(hdc, IsExpanded(), &partRect, rgbBk, rgbText))
|
||||
{
|
||||
paintLeft = partRect.right;
|
||||
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
}
|
||||
}
|
||||
|
||||
WCHAR szBuffer[128] = {0};
|
||||
INT cchBuffer = 0;
|
||||
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
cchBuffer = lstrlenW(szBuffer);
|
||||
|
||||
SetRect(&partRect, paintLeft, prc->top, prc->right, prc->bottom);
|
||||
if (ExtTextOut(hdc, partRect.left + TEXT_OFFSET_LEFT, partRect.bottom - TEXT_OFFSET_BOTTOM,
|
||||
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
|
||||
{
|
||||
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
}
|
||||
|
||||
|
||||
|
||||
COLORREF rgbLine = ColorAdjustLuma(rgbBk, -150, TRUE);
|
||||
if (rgbLine != rgbBk)
|
||||
{
|
||||
RECT lineRect;
|
||||
SetRect(&lineRect, prc->left, prc->bottom - 1, prc->right, prc->bottom);
|
||||
|
||||
SetBkColor(hdc, rgbLine);
|
||||
if (ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &lineRect, NULL, 0, NULL))
|
||||
{
|
||||
if (SetRectRgn(rgn, lineRect.left, lineRect.top, lineRect.right, lineRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
}
|
||||
|
||||
SetBkColor(hdc, rgbBk);
|
||||
}
|
||||
|
||||
if (0 != (flagMenuActive & flags))
|
||||
{
|
||||
COLORREF rgbFrame = rgbLine; //ColorAdjustLuma(GetSysColor(COLOR_HIGHLIGHT), 100, TRUE);
|
||||
SetupGroup_DrawFrame(hdc, prc, 1, rgbFrame);
|
||||
if (SetRectRgn(rgn, prc->left + 1, prc->top + 1, prc->right - 1, prc->bottom - 1))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_AND);
|
||||
}
|
||||
|
||||
|
||||
if (NULL != backRgn)
|
||||
{
|
||||
FillRgn(hdc, backRgn, GetBrush(hdc, state));
|
||||
DeleteObject(backRgn);
|
||||
}
|
||||
if (NULL != rgn)
|
||||
DeleteObject(rgn);
|
||||
|
||||
|
||||
|
||||
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
|
||||
DrawFocusRect(hdc, prc);
|
||||
|
||||
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
|
||||
if (origBk != rgbBk) SetBkColor(hdc, origBk);
|
||||
if (origText != rgbText) SetTextColor(hdc, origText);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
INT_PTR SetupGroup::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
|
||||
{
|
||||
switch(vKey)
|
||||
{
|
||||
case VK_SPACE:
|
||||
InvertExpanded(instance);
|
||||
return -2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
BOOL SetupGroup::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupGroup::MouseLeave(SetupListbox *instance, const RECT *prcItem)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupGroup::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupGroup::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupGroup::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
InvertExpanded(instance);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupGroup::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupGroup::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
HMENU hMenu = instance->GetContextMenu(SetupListbox::menuGroupContext);
|
||||
if (NULL == hMenu)
|
||||
return FALSE;
|
||||
|
||||
hMenu = MenuHelper_DuplcateMenu(hMenu);
|
||||
if (NULL == hMenu) return FALSE;
|
||||
|
||||
MENUITEMINFO mi;
|
||||
mi.cbSize = sizeof(MENUITEMINFO);
|
||||
mi.fMask = MIIM_STATE;
|
||||
GetMenuItemInfo(hMenu, ID_GROUP_TOGGLE, FALSE, &mi);
|
||||
|
||||
mi.fMask = 0;
|
||||
if (0 == (MFS_DEFAULT & mi.fState))
|
||||
{
|
||||
mi.fMask |= MIIM_STATE;
|
||||
mi.fState |= MFS_DEFAULT;
|
||||
}
|
||||
|
||||
WCHAR szBuffer[128] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(((IsExpanded()) ? IDS_COLLAPSE : IDS_EXPAND), szBuffer, ARRAYSIZE(szBuffer));
|
||||
mi.fMask |= MIIM_STRING;
|
||||
mi.dwTypeData = szBuffer;
|
||||
|
||||
if (0 != mi.fMask)
|
||||
SetMenuItemInfo(hMenu, ID_GROUP_TOGGLE, FALSE, &mi);
|
||||
|
||||
if (0 == list.size())
|
||||
{
|
||||
EnableMenuItem(hMenu, ID_GROUP_SELECTALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
||||
EnableMenuItem(hMenu, ID_GROUP_UNSELECTALL, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
||||
}
|
||||
|
||||
if (0 != (flagLoading & flags))
|
||||
{
|
||||
EnableMenuItem(hMenu, ID_GROUP_RELOAD, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
||||
}
|
||||
|
||||
MapWindowPoints(instance->GetHwnd(), HWND_DESKTOP, &pt, 1);
|
||||
|
||||
flags |= flagMenuActive;
|
||||
instance->InvalidateRect(prcItem, TRUE);
|
||||
|
||||
INT cmd = TrackPopupMenuEx(hMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD, pt.x, pt.y, instance->GetHwnd(), NULL);
|
||||
if (0 != cmd)
|
||||
{
|
||||
Command(instance, cmd, 0);
|
||||
}
|
||||
|
||||
DestroyMenu(hMenu);
|
||||
|
||||
flags &= ~flagMenuActive;
|
||||
instance->InvalidateRect(prcItem, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupGroup::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
|
||||
{
|
||||
}
|
||||
|
||||
void SetupGroup::InvertExpanded(SetupListbox *instance)
|
||||
{
|
||||
if (FALSE != IsExpanded())
|
||||
ValidateSelection(instance);
|
||||
|
||||
SetExpanded(!IsExpanded());
|
||||
if (NULL != instance)
|
||||
{
|
||||
instance->UpdateCount();
|
||||
UpdateWindow(instance->GetHwnd());
|
||||
}
|
||||
}
|
||||
void SetupGroup::SelectAll(SetupListbox *instance, BOOL fSelect)
|
||||
{
|
||||
size_t index = list.size();
|
||||
|
||||
INT baseIndex;
|
||||
if (NULL == instance || FALSE == instance->GetIndex(this, &baseIndex))
|
||||
baseIndex = -1;
|
||||
else
|
||||
baseIndex++;
|
||||
|
||||
while(index--)
|
||||
{
|
||||
SetupRecord *record = list[index];
|
||||
if (NULL != record && !record->IsDisabled())
|
||||
{
|
||||
if ((FALSE == fSelect) != (FALSE == record->IsSelected()))
|
||||
{
|
||||
record->SetSelected(fSelect);
|
||||
if (0 == (flagCollapsed & flags) && NULL != instance && -1 != baseIndex)
|
||||
{
|
||||
instance->InvalidateItem((INT)(baseIndex + index), TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetupGroup::SetEmptyText(LPCWSTR pszText, BOOL fInvalidate)
|
||||
{
|
||||
if (NULL == emptyLabel)
|
||||
emptyLabel = SetupListboxLabel::CreateInstance(pszText);
|
||||
else
|
||||
emptyLabel->SetName(pszText);
|
||||
|
||||
if (FALSE != fInvalidate && NULL != hPage)
|
||||
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)id, NULL);
|
||||
}
|
||||
|
||||
HWND SetupGroup::CreateDetailsView(HWND hParent)
|
||||
{
|
||||
WCHAR szName[64] = {0};
|
||||
if (FALSE == GetUniqueName(szName, ARRAYSIZE(szName)))
|
||||
szName[0] = L'\0';
|
||||
|
||||
return SetupDetails_CreateGroupView(hParent, szName, this);
|
||||
}
|
||||
|
||||
BOOL SetupGroup::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer ||
|
||||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"grp_id_%d", id)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void SetupGroup::SetLongName(LPCWSTR pszText)
|
||||
{
|
||||
if (NULL != longName && !IS_INTRESOURCE(longName))
|
||||
Plugin_FreeString(longName);
|
||||
longName = NULL;
|
||||
|
||||
if (NULL != pszText)
|
||||
longName = (IS_INTRESOURCE(pszText)) ? (LPWSTR)pszText : Plugin_CopyString(pszText);
|
||||
}
|
||||
|
||||
void SetupGroup::SetDescription(LPCWSTR pszText)
|
||||
{
|
||||
if (NULL != description && !IS_INTRESOURCE(description))
|
||||
Plugin_FreeString(description);
|
||||
description = NULL;
|
||||
if (NULL != pszText)
|
||||
description = (IS_INTRESOURCE(pszText)) ? (LPWSTR)pszText : Plugin_CopyString(pszText);
|
||||
}
|
||||
|
||||
void SetupGroup::ValidateSelection(SetupListbox *instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return;
|
||||
|
||||
SetupListboxItem *selection = instance->GetSelection();
|
||||
if (NULL != selection)
|
||||
{
|
||||
EnterCriticalSection(&lock);
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (list[index] == selection)
|
||||
{
|
||||
instance->SetSelection(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
}
|
||||
}
|
||||
|
||||
void SetupGroup::Command(SetupListbox *instance, INT commandId, INT eventId)
|
||||
{
|
||||
switch(commandId)
|
||||
{
|
||||
case ID_GROUP_TOGGLE:
|
||||
InvertExpanded(instance);
|
||||
break;
|
||||
case ID_GROUP_SELECTALL:
|
||||
SelectAll(instance, TRUE);
|
||||
break;
|
||||
case ID_GROUP_UNSELECTALL:
|
||||
SelectAll(instance, FALSE);
|
||||
break;
|
||||
case ID_GROUP_RELOAD:
|
||||
ValidateSelection(instance);
|
||||
RequestReload();
|
||||
break;
|
||||
}
|
||||
}
|
131
Src/Plugins/Library/ml_online/Setup/setupGroup.h
Normal file
131
Src/Plugins/Library/ml_online/Setup/setupGroup.h
Normal file
|
@ -0,0 +1,131 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "./setupRecord.h"
|
||||
#include "./setupListbox.h"
|
||||
#include <vector>
|
||||
|
||||
class SetupListboxLabel;
|
||||
class SetupLog;
|
||||
class SetupPage;
|
||||
class ifc_omstorage;
|
||||
|
||||
class SetupGroup : public SetupListboxItem
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
styleDefaultUnsubscribed = 0x00000001,
|
||||
styleDefaultSubscribed = 0x00000002,
|
||||
styleSortAlphabetically = 0x00000008,
|
||||
styleSaveAll = 0x00000010,
|
||||
} GroupStyles;
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
flagCollapsed = 0x0001,
|
||||
flagMenuActive = 0x0002,
|
||||
flagLoading = 0x0004,
|
||||
} GroupFlags;
|
||||
|
||||
protected:
|
||||
SetupGroup(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle);
|
||||
~SetupGroup();
|
||||
|
||||
public:
|
||||
static SetupGroup *CreateInstance(INT groupId, LPCWSTR pszName, LPCWSTR pszAddress, const GUID *storageId, const GUID *filterId, UINT fStyle);
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
INT GetId() { return id; }
|
||||
HRESULT GetName(LPWSTR pszBuffer, INT cchBufferMax);
|
||||
HRESULT GetLongName(LPWSTR pszBuffer, INT cchBufferMax);
|
||||
HRESULT GetDescription(LPWSTR pszBuffer, INT cchBufferMax);
|
||||
|
||||
size_t GetRecordCount();
|
||||
SetupRecord *GetRecord(size_t index) { return list[index]; }
|
||||
|
||||
size_t GetListboxCount();
|
||||
SetupListboxItem *GetListboxItem(size_t index);
|
||||
|
||||
BOOL IsModified();
|
||||
|
||||
BOOL IsExpanded();
|
||||
void SetExpanded(BOOL fExpanded);
|
||||
void SelectAll(SetupListbox *instance, BOOL fSelect);
|
||||
|
||||
HRESULT RequestReload();
|
||||
HRESULT Save(SetupLog *log);
|
||||
|
||||
|
||||
void SetEmptyText(LPCWSTR pszText, BOOL fInvalidate);
|
||||
void SetLongName(LPCWSTR pszText);
|
||||
void SetDescription(LPCWSTR pszText);
|
||||
|
||||
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
|
||||
HBRUSH GetBrush(HDC hdc, UINT state);
|
||||
|
||||
HRESULT SignalLoadCompleted(HANDLE event);
|
||||
void ValidateSelection(SetupListbox *instance);
|
||||
|
||||
/* SetupListboxItem */
|
||||
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
|
||||
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
|
||||
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
|
||||
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
|
||||
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
|
||||
BOOL IsDisabled() { return FALSE; }
|
||||
void Command(SetupListbox *instance, INT commandId, INT eventId);
|
||||
HWND CreateDetailsView(HWND hParent);
|
||||
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
|
||||
void SetError(HRESULT code) { errorCode = code; }
|
||||
HRESULT GetError() { return errorCode; }
|
||||
|
||||
void Clear(BOOL fInvalidate);
|
||||
|
||||
void SetPageWnd(HWND hPage);
|
||||
|
||||
protected:
|
||||
void InvertExpanded(SetupListbox *instance);
|
||||
void OnLoadCompleted();
|
||||
|
||||
|
||||
private:
|
||||
friend static void CALLBACK SetupGroup_LoadCallback(ifc_omstorageasync *result);
|
||||
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
INT id;
|
||||
LPWSTR name;
|
||||
LPWSTR longName;
|
||||
LPWSTR description;
|
||||
UINT style;
|
||||
UINT flags;
|
||||
LPWSTR address;
|
||||
GUID storageId;
|
||||
GUID filterId;
|
||||
HRESULT errorCode;
|
||||
std::vector<SetupRecord*> list;
|
||||
SetupListboxLabel *emptyLabel;
|
||||
CRITICAL_SECTION lock;
|
||||
ifc_omstorageasync *loadResult;
|
||||
HWND hPage;
|
||||
HANDLE loadComplete;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUP_HEADER
|
226
Src/Plugins/Library/ml_online/Setup/setupGroupFilter.cpp
Normal file
226
Src/Plugins/Library/ml_online/Setup/setupGroupFilter.cpp
Normal file
|
@ -0,0 +1,226 @@
|
|||
#include "./setupGroupFilter.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include "../serviceHost.h"
|
||||
#include "../config.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omstorage.h>
|
||||
#include <ifc_omserviceenum.h>
|
||||
#include <ifc_omfilestorage.h>
|
||||
|
||||
|
||||
SetupGroupFilter::SetupGroupFilter(const GUID *filterId)
|
||||
: ref(1)
|
||||
{
|
||||
id = (NULL != filterId) ? *filterId : GUID_NULL;
|
||||
}
|
||||
|
||||
SetupGroupFilter::~SetupGroupFilter()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT SetupGroupFilter::CreateInstance(const GUID *filterId, SetupGroupFilter **instance)
|
||||
{
|
||||
if (NULL == filterId)
|
||||
{
|
||||
*instance = NULL;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (FALSE != IsEqualGUID(*filterId, FUID_SetupFeaturedGroupFilter))
|
||||
return SetupFeaturedGroupFilter::CreateInstance((SetupFeaturedGroupFilter**)instance);
|
||||
if (FALSE != IsEqualGUID(*filterId, FUID_SetupKnownGroupFilter))
|
||||
return SetupKnownGroupFilter::CreateInstance((SetupKnownGroupFilter**)instance);
|
||||
|
||||
*instance = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG SetupGroupFilter::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupGroupFilter::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
return r;
|
||||
}
|
||||
|
||||
HRESULT SetupGroupFilter::GetId(GUID *filterId)
|
||||
{
|
||||
if (NULL == filterId)
|
||||
return E_POINTER;
|
||||
*filterId = id;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL CALLBACK SetupGroupFilter::AppendServiceIdCallback(UINT serviceId, void *data)
|
||||
{
|
||||
ServiceIdList *list = (ServiceIdList*)data;
|
||||
if (NULL == list) return FALSE;
|
||||
list->push_back(serviceId);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SetupFeaturedGroupFilter::SetupFeaturedGroupFilter()
|
||||
: SetupGroupFilter(&FUID_SetupFeaturedGroupFilter)
|
||||
{
|
||||
}
|
||||
|
||||
SetupFeaturedGroupFilter::~SetupFeaturedGroupFilter()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT SetupFeaturedGroupFilter::CreateInstance(SetupFeaturedGroupFilter **instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = new SetupFeaturedGroupFilter();
|
||||
if (NULL == *instance) return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupFeaturedGroupFilter::Initialize()
|
||||
{
|
||||
HRESULT hr;
|
||||
ifc_omstorage *storage;
|
||||
|
||||
filterList.clear();
|
||||
|
||||
if (NULL == OMSERVICEMNGR)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageIni, &storage);
|
||||
if(FAILED(hr))
|
||||
return hr;
|
||||
|
||||
ServiceHost *serviceHost;
|
||||
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
|
||||
serviceHost = NULL;
|
||||
|
||||
ifc_omserviceenum *serviceEnum;
|
||||
hr = storage->Load(L"*.ini", serviceHost, &serviceEnum);
|
||||
if(SUCCEEDED(hr))
|
||||
{
|
||||
ifc_omservice *service;
|
||||
while(S_OK == serviceEnum->Next(1, &service, NULL) && NULL != service)
|
||||
{
|
||||
filterList.push_back(service->GetId());
|
||||
}
|
||||
serviceEnum->Release();
|
||||
}
|
||||
storage->Release();
|
||||
|
||||
ServiceIdList promoList;
|
||||
Config_ReadServiceIdList("Setup", "featuredExtra", ',', AppendServiceIdCallback, &promoList);
|
||||
|
||||
ServiceIdList historyList;
|
||||
Config_ReadServiceIdList("Setup", "featuredHistory", ',', AppendServiceIdCallback, &historyList);
|
||||
|
||||
size_t index = historyList.size();
|
||||
size_t filterIndex, filterSize = filterList.size();
|
||||
|
||||
while(index--)
|
||||
{
|
||||
size_t promoSize = promoList.size();
|
||||
for(filterIndex = 0; filterIndex < promoSize; filterIndex++)
|
||||
{
|
||||
if (promoList[filterIndex] == historyList[index])
|
||||
{
|
||||
promoList.erase(promoList.begin() + filterIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (filterIndex == promoSize)
|
||||
{
|
||||
for(filterIndex = 0; filterIndex < filterSize; filterIndex++)
|
||||
{
|
||||
if (filterList[filterIndex] == historyList[index])
|
||||
break;
|
||||
}
|
||||
|
||||
if (filterIndex == filterSize)
|
||||
filterList.push_back(historyList[index]);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupFeaturedGroupFilter::ProcessService(ifc_omservice *service, UINT *filterResult)
|
||||
{
|
||||
if (NULL == service)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (NULL == filterResult)
|
||||
return E_POINTER;
|
||||
|
||||
size_t index = filterList.size();
|
||||
while(index--)
|
||||
{
|
||||
if (filterList[index] == service->GetId())
|
||||
{
|
||||
filterList.erase(filterList.begin() + index);
|
||||
*filterResult = serviceIgnore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
SetupKnownGroupFilter::SetupKnownGroupFilter()
|
||||
: SetupGroupFilter(&FUID_SetupKnownGroupFilter)
|
||||
{
|
||||
}
|
||||
|
||||
SetupKnownGroupFilter::~SetupKnownGroupFilter()
|
||||
{
|
||||
}
|
||||
|
||||
HRESULT SetupKnownGroupFilter::CreateInstance(SetupKnownGroupFilter **instance)
|
||||
{
|
||||
if (NULL == instance)
|
||||
return E_POINTER;
|
||||
|
||||
*instance = new SetupKnownGroupFilter();
|
||||
if (NULL == *instance) return E_OUTOFMEMORY;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupKnownGroupFilter::Initialize()
|
||||
{
|
||||
Config_ReadServiceIdList("Setup", "featuredExtra", ',', AppendServiceIdCallback, &filterList);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupKnownGroupFilter::ProcessService(ifc_omservice *service, UINT *filterResult)
|
||||
{
|
||||
if (NULL == service)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (NULL == filterResult)
|
||||
return E_POINTER;
|
||||
|
||||
size_t index = filterList.size();
|
||||
while(index--)
|
||||
{
|
||||
if (filterList[index] == service->GetId())
|
||||
{
|
||||
filterList.erase(filterList.begin() + index);
|
||||
*filterResult &= ~serviceForceUnsubscribe;
|
||||
*filterResult |= serviceForceSubscribe;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
190
Src/Plugins/Library/ml_online/Setup/setupGroupList.cpp
Normal file
190
Src/Plugins/Library/ml_online/Setup/setupGroupList.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include "./setupGroupList.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include <strsafe.h>
|
||||
|
||||
SetupGroupList::SetupGroupList()
|
||||
: ref(1)
|
||||
{
|
||||
}
|
||||
|
||||
SetupGroupList::~SetupGroupList()
|
||||
{
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
list[index]->Release();
|
||||
}
|
||||
}
|
||||
|
||||
SetupGroupList *SetupGroupList::CreateInstance()
|
||||
{
|
||||
return new SetupGroupList();
|
||||
}
|
||||
|
||||
ULONG SetupGroupList::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupGroupList::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL SetupGroupList::AddGroup(SetupGroup *group)
|
||||
{
|
||||
if (NULL == group) return FALSE;
|
||||
list.push_back(group);
|
||||
group->AddRef();
|
||||
return TRUE;
|
||||
}
|
||||
size_t SetupGroupList::GetGroupCount()
|
||||
{
|
||||
return list.size();
|
||||
}
|
||||
|
||||
BOOL SetupGroupList::IsModified()
|
||||
{
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (list[index]->IsModified())
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupGroupList::FindGroupIndex(SetupGroup *group, size_t *groupIndex)
|
||||
{
|
||||
if (NULL == group) return FALSE;
|
||||
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (list[index] == group)
|
||||
{
|
||||
if (NULL != groupIndex)
|
||||
*groupIndex = index;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
HRESULT SetupGroupList::FindGroupById(UINT groupId, SetupGroup **group)
|
||||
{
|
||||
if (NULL == group) return E_POINTER;
|
||||
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (list[index]->GetId() == groupId)
|
||||
{
|
||||
*group = list[index];
|
||||
(*group)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
size_t SetupGroupList::GetListboxCount()
|
||||
{
|
||||
size_t recordCount = list.size();
|
||||
size_t index = recordCount;
|
||||
while(index--)
|
||||
{
|
||||
recordCount += list[index]->GetListboxCount();
|
||||
}
|
||||
return recordCount;
|
||||
}
|
||||
|
||||
HRESULT SetupGroupList::Save(SetupLog *log)
|
||||
{
|
||||
HRESULT hr(S_OK);
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
if (FAILED(list[index]->Save(log)))
|
||||
hr = E_FAIL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupGroupList::FindListboxItem(size_t listboxId, SetupListboxItem **listboxItem)
|
||||
{
|
||||
if (NULL == listboxItem) return E_POINTER;
|
||||
|
||||
size_t index = 0;
|
||||
size_t groupCount = list.size();
|
||||
|
||||
SetupGroup *group;
|
||||
for (size_t i = 0; i < groupCount; i++)
|
||||
{
|
||||
group = list[i];
|
||||
if (index == listboxId)
|
||||
{
|
||||
*listboxItem = (SetupListboxItem*)group;
|
||||
return S_OK;
|
||||
}
|
||||
index++;
|
||||
|
||||
size_t itemCount;
|
||||
if (0 != (itemCount = group->GetListboxCount()))
|
||||
{
|
||||
if (listboxId < (index + itemCount))
|
||||
{
|
||||
size_t itemIndex = (listboxId - index);
|
||||
*listboxItem = group->GetListboxItem(itemIndex);
|
||||
return S_OK;
|
||||
}
|
||||
index += itemCount;
|
||||
}
|
||||
}
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
INT SetupGroupList::GetListboxItem(SetupListboxItem *item)
|
||||
{
|
||||
if (NULL == item) return LB_ERR;
|
||||
size_t index = 0;
|
||||
size_t groupCount = list.size();
|
||||
SetupGroup *group;
|
||||
SetupListboxItem *groupItem;
|
||||
|
||||
for (size_t i = 0; i < groupCount; i++)
|
||||
{
|
||||
group = list[i];
|
||||
if (item == group)
|
||||
return (INT)index;
|
||||
|
||||
index++;
|
||||
size_t itemCount = group->GetListboxCount();
|
||||
for (size_t j = 0; j < itemCount; j++)
|
||||
{
|
||||
groupItem = group->GetListboxItem(j);
|
||||
if (groupItem == item)
|
||||
return (INT)index;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return LB_ERR;
|
||||
}
|
||||
|
||||
void SetupGroupList::SetPageWnd(HWND hPage)
|
||||
{
|
||||
size_t index = list.size();
|
||||
while(index--)
|
||||
{
|
||||
list[index]->SetPageWnd(hPage);
|
||||
}
|
||||
}
|
52
Src/Plugins/Library/ml_online/Setup/setupGroupList.h
Normal file
52
Src/Plugins/Library/ml_online/Setup/setupGroupList.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "./setupGroup.h"
|
||||
#include <vector>
|
||||
|
||||
class SetupListboxItem;
|
||||
class SetupLog;
|
||||
|
||||
class SetupGroupList
|
||||
{
|
||||
|
||||
protected:
|
||||
SetupGroupList();
|
||||
~SetupGroupList();
|
||||
|
||||
public:
|
||||
static SetupGroupList *CreateInstance();
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
BOOL AddGroup(SetupGroup *group);
|
||||
SetupGroup *GetGroup(size_t index) { return list[index]; }
|
||||
size_t GetGroupCount();
|
||||
BOOL FindGroupIndex(SetupGroup *group, size_t *groupIndex);
|
||||
HRESULT FindGroupById(UINT groupId, SetupGroup **group);
|
||||
|
||||
|
||||
BOOL IsModified();
|
||||
|
||||
HRESULT Save(SetupLog *log);
|
||||
|
||||
size_t GetListboxCount();
|
||||
INT GetListboxItem(SetupListboxItem *item);
|
||||
HRESULT FindListboxItem(size_t listboxId, SetupListboxItem **listboxItem);
|
||||
|
||||
void SetPageWnd(HWND hPage);
|
||||
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
std::vector<SetupGroup*> list;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPGROUPLIST_HEADER
|
282
Src/Plugins/Library/ml_online/Setup/setupImage.cpp
Normal file
282
Src/Plugins/Library/ml_online/Setup/setupImage.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
#include "./setupImage.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
static BOOL SetupImage_CopyImage(HDC hdc, HBITMAP bitmapDst, INT x, INT y, INT cx, INT cy, HBITMAP bitmapSrc, INT srcX, INT srcY)
|
||||
{
|
||||
BOOL resultOk = FALSE;
|
||||
HDC hdcDst = CreateCompatibleDC(hdc);
|
||||
HDC hdcSrc = CreateCompatibleDC(hdc);
|
||||
|
||||
if (NULL != hdcDst && NULL != hdcSrc)
|
||||
{
|
||||
HBITMAP bitmapDstOrig = (HBITMAP)SelectObject(hdcDst, bitmapDst);
|
||||
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, bitmapSrc);
|
||||
|
||||
resultOk = BitBlt(hdcDst, x, y, cx, cy, hdcSrc, srcX, srcY, SRCCOPY);
|
||||
|
||||
SelectObject(hdcDst, bitmapDstOrig);
|
||||
SelectObject(hdcSrc, bitmapSrcOrig);
|
||||
}
|
||||
|
||||
if (NULL != hdcDst) DeleteDC(hdcDst);
|
||||
if (NULL != hdcSrc) DeleteDC(hdcSrc);
|
||||
|
||||
return resultOk;
|
||||
}
|
||||
|
||||
static BOOL SetupImage_ColorizeImage(BYTE *pPixels, LONG x, LONG y, LONG cx, LONG cy, WORD bpp, LONG dstX, LONG dstY, COLORREF rgbBk, COLORREF rgbFg, BOOL removeAlpha)
|
||||
{
|
||||
LONG pitch;
|
||||
INT step;
|
||||
BYTE rFg, gFg, bFg;
|
||||
LPBYTE srcCursor, srcLine;
|
||||
LPBYTE dstLine;
|
||||
|
||||
if (bpp < 24) return FALSE;
|
||||
|
||||
step = (bpp>>3);
|
||||
pitch = cx*step;
|
||||
while (pitch%4) pitch++;
|
||||
|
||||
rFg = GetRValue(rgbFg); gFg = GetGValue(rgbFg); bFg = GetBValue(rgbFg);
|
||||
|
||||
INT bK = (bFg - GetBValue(rgbBk));
|
||||
INT gK = (gFg - GetGValue(rgbBk));
|
||||
INT rK = (rFg - GetRValue(rgbBk));
|
||||
|
||||
srcLine = pPixels + pitch * y + x*step;
|
||||
dstLine = pPixels + pitch * dstY + dstX*step;
|
||||
|
||||
if (24 == bpp)
|
||||
{
|
||||
for (; cy-- != 0; srcLine += pitch, dstLine += pitch )
|
||||
{
|
||||
LONG i;
|
||||
LPBYTE dstCursor;
|
||||
for (i = cx, srcCursor = srcLine, dstCursor = dstLine ; i-- != 0; srcCursor += 3, dstCursor +=3)
|
||||
{
|
||||
dstCursor[0] = bFg - (bK*(255 - srcCursor[0])>>8);
|
||||
dstCursor[1] = gFg - (gK*(255 - srcCursor[1])>>8);
|
||||
dstCursor[2] = rFg - (rK*(255 - srcCursor[2])>>8);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing for now
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
SetupImage::SetupImage(HDC hdc, HBITMAP bitmapSource, INT maxColors)
|
||||
: ref(1), bitmap(NULL), pixels(NULL),
|
||||
table(NULL), tableSize(0), tableCount(0), insertCursor(0), readCursor(0)
|
||||
{
|
||||
ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
|
||||
|
||||
BITMAP bm;
|
||||
if (sizeof(BITMAP) != GetObject(bitmapSource, sizeof(BITMAP), &bm))
|
||||
return;
|
||||
|
||||
if (bm.bmHeight < 0)
|
||||
bm.bmHeight = -bm.bmHeight;
|
||||
|
||||
header.biSize = sizeof(BITMAPINFOHEADER);
|
||||
header.biCompression = BI_RGB;
|
||||
header.biBitCount = 24;
|
||||
header.biPlanes = 1;
|
||||
header.biWidth = bm.bmWidth;
|
||||
header.biHeight = -(bm.bmHeight * (maxColors + 1));
|
||||
|
||||
bitmap = CreateDIBSection(hdc, (LPBITMAPINFO)&header, DIB_RGB_COLORS, (void**)&pixels, NULL, 0);
|
||||
if (NULL == bitmap)
|
||||
return;
|
||||
|
||||
if (FALSE == SetupImage_CopyImage(hdc, bitmap, 0, 0, bm.bmWidth, bm.bmHeight, bitmapSource, 0, 0))
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
bitmap = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
tableSize = maxColors;
|
||||
table = (IMAGEINDEX*)calloc(tableSize, sizeof(IMAGEINDEX));
|
||||
if (NULL == table)
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
bitmap = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetupImage::~SetupImage()
|
||||
{
|
||||
if (NULL != bitmap)
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
bitmap = NULL;
|
||||
}
|
||||
|
||||
if (NULL != table)
|
||||
{
|
||||
free(table);
|
||||
table = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SetupImage *SetupImage::CreateInstance(HDC hdc, HBITMAP bitmapSource, INT maxColors)
|
||||
{
|
||||
if (NULL == bitmapSource || maxColors < 1 || maxColors > 120)
|
||||
return NULL;
|
||||
|
||||
SetupImage *instance = new SetupImage(hdc, bitmapSource, maxColors);
|
||||
if (NULL == instance) return NULL;
|
||||
if (NULL == instance->bitmap || NULL == instance->table)
|
||||
{
|
||||
instance->Release();
|
||||
instance = NULL;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
SetupImage *SetupImage::CreateFromPluginBitmap(HDC hdc, LPCWSTR pszModuleName, LPCWSTR resourceName, INT maxColors)
|
||||
{
|
||||
SetupImage *instance = NULL;
|
||||
WCHAR szPath[MAX_PATH] = {0};
|
||||
|
||||
if (0 != GetModuleFileName(WASABI_API_ORIG_HINST, szPath, ARRAYSIZE(szPath)))
|
||||
{
|
||||
PathRemoveFileSpec(szPath);
|
||||
PathAppend(szPath, pszModuleName);
|
||||
HMODULE hModule = LoadLibraryEx(szPath, NULL, LOAD_LIBRARY_AS_DATAFILE | 0x00000020/*LOAD_LIBRARY_AS_IMAGE_RESOURCE*/);
|
||||
if (NULL != hModule)
|
||||
{
|
||||
HBITMAP bitmapSource = (HBITMAP)LoadImage(hModule, resourceName, IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
|
||||
if (NULL != bitmapSource)
|
||||
instance = CreateInstance(hdc, bitmapSource, maxColors);
|
||||
FreeLibrary(hModule);
|
||||
}
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
ULONG SetupImage::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupImage::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL SetupImage::GetSize(SIZE *pSize)
|
||||
{
|
||||
if (NULL == pSize) return FALSE;
|
||||
|
||||
INT cy = header.biHeight;
|
||||
if (cy < 0) cy = -cy;
|
||||
|
||||
pSize->cx = header.biWidth;
|
||||
pSize->cy = cy / (tableSize + 1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupImage::DrawImage(HDC hdc, INT x, INT y, INT cx, INT cy, INT srcX, INT srcY, COLORREF rgbBk, COLORREF rgbFg)
|
||||
{
|
||||
BYTE bitmapIndex = 0xFF;
|
||||
|
||||
SIZE imageSize;
|
||||
if (!GetSize(&imageSize))
|
||||
return FALSE;
|
||||
|
||||
for(BYTE i = readCursor; i < tableCount; i++)
|
||||
{
|
||||
if (table[i].rgbBk == rgbBk && table[i].rgbFg == rgbFg)
|
||||
{
|
||||
bitmapIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0xFF == bitmapIndex)
|
||||
{
|
||||
if (readCursor > tableCount)
|
||||
readCursor = tableCount;
|
||||
for(BYTE i = 0; i < readCursor; i++)
|
||||
{
|
||||
if (table[i].rgbBk == rgbBk && table[i].rgbFg == rgbFg)
|
||||
{
|
||||
bitmapIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (0xFF == bitmapIndex)
|
||||
{
|
||||
if (tableCount < tableSize)
|
||||
{
|
||||
insertCursor = tableCount;
|
||||
tableCount++;
|
||||
}
|
||||
else if (++insertCursor == tableCount)
|
||||
insertCursor = 0;
|
||||
|
||||
INT targetY = (insertCursor + 1) * imageSize.cy;
|
||||
|
||||
if (!SetupImage_ColorizeImage(pixels, 0, 0, imageSize.cx, imageSize.cy,
|
||||
header.biBitCount, 0, targetY, rgbBk, rgbFg, TRUE))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
table[insertCursor].rgbBk = rgbBk;
|
||||
table[insertCursor].rgbFg = rgbFg;
|
||||
bitmapIndex = insertCursor;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
readCursor = bitmapIndex;
|
||||
srcY += ((bitmapIndex + 1) * imageSize.cy);
|
||||
|
||||
INT dstY = y;
|
||||
INT dstCY = cy;
|
||||
|
||||
INT imageHeight = header.biHeight;
|
||||
if (imageHeight < 0)
|
||||
{
|
||||
header.biHeight = -imageHeight;
|
||||
dstY += (cy - 1);
|
||||
dstCY = -cy;
|
||||
}
|
||||
|
||||
BOOL resultOk = StretchDIBits(hdc, x, dstY, cx, dstCY, srcX, srcY, cx, cy,
|
||||
pixels, (BITMAPINFO*)&header, DIB_RGB_COLORS, SRCCOPY);
|
||||
|
||||
if (imageHeight < 0)
|
||||
header.biHeight = imageHeight;
|
||||
|
||||
return resultOk;
|
||||
}
|
||||
|
||||
BOOL SetupImage::ResetCache()
|
||||
{
|
||||
if (NULL != table)
|
||||
ZeroMemory(&table, sizeof(IMAGEINDEX) * tableSize);
|
||||
tableCount = 0;
|
||||
insertCursor = 0;
|
||||
readCursor = 0;
|
||||
return TRUE;
|
||||
}
|
50
Src/Plugins/Library/ml_online/Setup/setupImage.h
Normal file
50
Src/Plugins/Library/ml_online/Setup/setupImage.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class SetupImage
|
||||
{
|
||||
private:
|
||||
typedef struct __IMAGEINDEX
|
||||
{
|
||||
COLORREF rgbBk;
|
||||
COLORREF rgbFg;
|
||||
} IMAGEINDEX;
|
||||
|
||||
protected:
|
||||
SetupImage(HDC hdc, HBITMAP bitmapSource, INT maxColors);
|
||||
~SetupImage();
|
||||
|
||||
public:
|
||||
static SetupImage *CreateInstance(HDC hdc, HBITMAP bitmapSource, INT maxColors);
|
||||
static SetupImage *CreateFromPluginBitmap(HDC hdc, LPCWSTR pszModuleName, LPCWSTR resourceName, INT maxColors);
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
BOOL GetSize(SIZE *pSize);
|
||||
BOOL DrawImage(HDC hdc, INT x, INT y, INT cx, INT cy, INT srcX, INT srcY, COLORREF rgbBk, COLORREF rgbFg);
|
||||
|
||||
BOOL ResetCache();
|
||||
|
||||
private:
|
||||
ULONG ref;
|
||||
HBITMAP bitmap;
|
||||
BYTE *pixels;
|
||||
BITMAPINFOHEADER header;
|
||||
|
||||
|
||||
IMAGEINDEX *table;
|
||||
BYTE tableSize;
|
||||
BYTE tableCount;
|
||||
BYTE insertCursor;
|
||||
BYTE readCursor;
|
||||
};
|
||||
|
||||
#endif // NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPIMAGE_HEADER
|
878
Src/Plugins/Library/ml_online/Setup/setupListbox.cpp
Normal file
878
Src/Plugins/Library/ml_online/Setup/setupListbox.cpp
Normal file
|
@ -0,0 +1,878 @@
|
|||
#include "./setupPage.h"
|
||||
#include "./setupListbox.h"
|
||||
#include "./setupGroupList.h"
|
||||
#include "./setupImage.h"
|
||||
#include "../common.h"
|
||||
#include "../resource.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
#include "../../nu/windowsTheme.h"
|
||||
|
||||
#include <vssym32.h>
|
||||
|
||||
//#include <tmschema.h>
|
||||
|
||||
static ATOM SERVICELIST_PROP = 0;
|
||||
|
||||
#define SLF_UNICODE 0x0001
|
||||
#define SLF_DRAGMOVE 0x0002
|
||||
|
||||
typedef BOOL (SetupListboxItem::*ITEMMOUSEPROC)(SetupListbox*, const RECT*, UINT, POINT);
|
||||
|
||||
class Listbox : public SetupListbox
|
||||
{
|
||||
|
||||
protected:
|
||||
Listbox(HWND hListbox, SetupGroupList *groupList);
|
||||
~Listbox();
|
||||
|
||||
public:
|
||||
static HRESULT AttachToWindow(HWND hwndListbox, SetupGroupList *groupList, SetupListbox **pInstance);
|
||||
|
||||
public:
|
||||
HWND GetHwnd() { return hwnd; }
|
||||
HFONT GetFont() { return (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0L); }
|
||||
LRESULT CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
BOOL MeasureItem(INT itemId, UINT *cx, UINT *cy);
|
||||
BOOL DrawItem(HDC hdc, const RECT *itemRect, INT itemId, UINT itemState, UINT itemAction);
|
||||
INT_PTR KeyToItem(INT vKey, INT caretPos);
|
||||
INT_PTR CharToItem(INT vKey, INT caretPos);
|
||||
|
||||
BOOL DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect);
|
||||
BOOL GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize);
|
||||
|
||||
INT GetCheckboxThemeState(BOOL checked, UINT state);
|
||||
INT HitTest(POINT pt, RECT *prcItem);
|
||||
|
||||
void SetCapture(SetupListboxItem *item);
|
||||
SetupListboxItem *GetCapture();
|
||||
void ReleaseCapture();
|
||||
BOOL InvalidateRect(const RECT *prcInvalidate, BOOL fErase);
|
||||
BOOL InvalidateItem(INT itemId, BOOL fErase);
|
||||
void UpdateCount();
|
||||
|
||||
BOOL DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg);
|
||||
BOOL GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize);
|
||||
|
||||
INT GetPageCount();
|
||||
INT GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut);
|
||||
INT GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut);
|
||||
|
||||
SetupListboxItem *GetSelection();
|
||||
BOOL SetSelection(SetupListboxItem *item);
|
||||
BOOL GetIndex(SetupListboxItem *item, INT *iItem);
|
||||
|
||||
BOOL DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt);
|
||||
HMENU GetContextMenu(UINT menuId);
|
||||
|
||||
protected:
|
||||
friend static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
void OnDestroy();
|
||||
void GetItemRect(INT itemId, RECT *prcItem);
|
||||
|
||||
SetupImage *GetExpandboxImage(HDC hdc, BOOL fExpanded);
|
||||
|
||||
void OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc);
|
||||
void OnMouseLeave();
|
||||
void OnEraseBkGround(HDC hdc);
|
||||
void OnCaptureChanged(HWND hwndGained);
|
||||
void NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain);
|
||||
void OnCommand(INT commandId, INT eventId, HWND hControl);
|
||||
|
||||
protected:
|
||||
HWND hwnd;
|
||||
UINT flags;
|
||||
WNDPROC originalProc;
|
||||
UXTHEME buttonTheme;
|
||||
SetupGroupList *groups;
|
||||
INT mouseoverId;
|
||||
INT capturedId;
|
||||
SetupImage *expandedImage;
|
||||
SetupImage *collapsedImage;
|
||||
};
|
||||
|
||||
#define GetList(__hwnd) ((Listbox*)GetPropW((__hwnd), MAKEINTATOM(SERVICELIST_PROP)))
|
||||
|
||||
|
||||
|
||||
|
||||
HRESULT SetupListbox::CreateInstance(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance)
|
||||
{
|
||||
return Listbox::AttachToWindow(hListbox, groupList, pInstance);
|
||||
}
|
||||
|
||||
SetupListbox *SetupListbox::GetInstance(HWND hListbox)
|
||||
{
|
||||
return GetList(hListbox);
|
||||
}
|
||||
|
||||
Listbox::Listbox(HWND hListbox, SetupGroupList *groupList)
|
||||
: hwnd(hListbox), flags(0), originalProc(NULL), buttonTheme(NULL), groups(groupList),
|
||||
mouseoverId(LB_ERR), capturedId(LB_ERR), expandedImage(NULL), collapsedImage(NULL)
|
||||
{
|
||||
if (IsWindowUnicode(hwnd))
|
||||
flags |= SLF_UNICODE;
|
||||
|
||||
buttonTheme = (UxIsAppThemed()) ? UxOpenThemeData(hwnd, L"Button") : NULL;
|
||||
|
||||
groups->AddRef();
|
||||
UpdateCount();
|
||||
|
||||
}
|
||||
|
||||
Listbox::~Listbox()
|
||||
{
|
||||
if (NULL != hwnd)
|
||||
{
|
||||
RemoveProp(hwnd, MAKEINTATOM(SERVICELIST_PROP));
|
||||
if (NULL != originalProc)
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONGX86)(LONG_PTR)originalProc);
|
||||
CallPrevProc(WM_DESTROY, 0, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != groups)
|
||||
groups->Release();
|
||||
|
||||
if (NULL != buttonTheme)
|
||||
UxCloseThemeData(buttonTheme);
|
||||
|
||||
if (NULL != expandedImage)
|
||||
expandedImage->Release();
|
||||
|
||||
if (NULL != collapsedImage)
|
||||
collapsedImage->Release();
|
||||
}
|
||||
|
||||
HRESULT Listbox::AttachToWindow(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance)
|
||||
{
|
||||
if (0 == SERVICELIST_PROP)
|
||||
{
|
||||
SERVICELIST_PROP = GlobalAddAtom(TEXT("omSetupListbox"));
|
||||
if (0 == SERVICELIST_PROP) return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
|
||||
if(NULL == hListbox || !IsWindow(hListbox) || NULL == groupList)
|
||||
return E_INVALIDARG;
|
||||
|
||||
Listbox *list = new Listbox(hListbox, groupList);
|
||||
if (NULL == list)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
list->originalProc = (WNDPROC)(LONG_PTR)SetWindowLongPtr(hListbox, GWLP_WNDPROC,
|
||||
(LONGX86)(LONG_PTR)Listbox_WindowProc);
|
||||
|
||||
if (NULL == list->originalProc || !SetProp(hListbox, MAKEINTATOM(SERVICELIST_PROP), list))
|
||||
{
|
||||
if (NULL != list->originalProc)
|
||||
SetWindowLongPtr(hListbox, GWLP_WNDPROC, (LONGX86)(LONG_PTR)list->originalProc);
|
||||
delete(list);
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
if (NULL != pInstance)
|
||||
*pInstance = list;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LRESULT Listbox::CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return (0 != (SLF_UNICODE & flags)) ?
|
||||
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
|
||||
DefWindowProcA(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT Listbox::CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
return (0 != (SLF_UNICODE & flags)) ?
|
||||
CallWindowProcW(originalProc, hwnd, uMsg, wParam, lParam) :
|
||||
CallWindowProcA(originalProc, hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
void Listbox::UpdateCount()
|
||||
{
|
||||
SendMessage(hwnd, WM_SETREDRAW, FALSE, 0L);
|
||||
|
||||
INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L);
|
||||
|
||||
size_t recordCount = (NULL != groups) ? groups->GetListboxCount() : 0;
|
||||
SendMessage(hwnd, LB_SETCOUNT, (WPARAM)recordCount, 0L);
|
||||
|
||||
SetupListboxItem *item;
|
||||
UINT cy, maxCY = 0;
|
||||
for (size_t i = 0; i < recordCount; i++)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(i, &item)) &&
|
||||
item->MeasureItem(this, NULL, &cy) && cy > maxCY)
|
||||
{
|
||||
maxCY = cy;
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(hwnd, LB_SETITEMHEIGHT, (WPARAM)0, (LPARAM)maxCY);
|
||||
|
||||
if (recordCount > 0)
|
||||
{
|
||||
if (iSelected < 0)
|
||||
iSelected = 0;
|
||||
|
||||
if ((size_t)iSelected >= recordCount)
|
||||
iSelected = (INT)(recordCount - 1);
|
||||
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iSelected, TRUE);
|
||||
SendMessage(hwnd, LB_SETANCHORINDEX, (WPARAM)iSelected, 0L);
|
||||
SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iSelected, 0L);
|
||||
}
|
||||
|
||||
SendMessage(hwnd, WM_SETREDRAW, TRUE, 0L);
|
||||
}
|
||||
|
||||
BOOL Listbox::MeasureItem(INT itemId, UINT *cx, UINT *cy)
|
||||
{
|
||||
SetupListboxItem *item;
|
||||
HRESULT hr = groups->FindListboxItem(itemId, &item);
|
||||
return (SUCCEEDED(hr)) ? item->MeasureItem(this, cx, cy) : FALSE;
|
||||
}
|
||||
|
||||
BOOL Listbox::DrawItem(HDC hdc, const RECT *prcItem, INT itemId, UINT itemState, UINT itemAction)
|
||||
{
|
||||
SetupListboxItem *item;
|
||||
HRESULT hr = groups->FindListboxItem(itemId, &item);
|
||||
if (FAILED(hr)) return FALSE;
|
||||
|
||||
if (0 != (ODS_SELECTED & itemState) && GetFocus() != hwnd)
|
||||
itemState |= ODS_INACTIVE;
|
||||
|
||||
if (item->IsDisabled())
|
||||
itemState |= ODS_DISABLED;
|
||||
|
||||
return item->DrawItem(this, hdc, prcItem, itemState);
|
||||
}
|
||||
|
||||
INT Listbox::GetPageCount()
|
||||
{
|
||||
RECT clientRect;
|
||||
if (NULL == hwnd || !GetClientRect(hwnd, &clientRect))
|
||||
return 0;
|
||||
|
||||
INT itemHeight = (INT)SendMessage(hwnd, LB_GETITEMHEIGHT, 0, 0L);
|
||||
return (clientRect.bottom - clientRect.top) / itemHeight;
|
||||
}
|
||||
|
||||
INT Listbox::GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut)
|
||||
{
|
||||
INT iLast = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
|
||||
if (iLast >= 0) iLast--;
|
||||
|
||||
SetupListboxItem *testItem;
|
||||
while(iItem++ < iLast)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem)))
|
||||
{
|
||||
if (FALSE == testItem->IsDisabled()) break;
|
||||
}
|
||||
}
|
||||
if (NULL != itemOut)
|
||||
{
|
||||
*itemOut = (iItem <= iLast) ? testItem : NULL;
|
||||
}
|
||||
return (iItem <= iLast) ? iItem : LB_ERR;
|
||||
}
|
||||
|
||||
INT Listbox::GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut)
|
||||
{
|
||||
SetupListboxItem *testItem;
|
||||
while(iItem-- > 0)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(iItem, &testItem)))
|
||||
{
|
||||
if (FALSE == testItem->IsDisabled()) break;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != itemOut)
|
||||
{
|
||||
*itemOut = (iItem >= 0) ? testItem : NULL;
|
||||
}
|
||||
return (iItem >= 0) ? iItem : LB_ERR;
|
||||
}
|
||||
|
||||
SetupListboxItem *Listbox::GetSelection()
|
||||
{
|
||||
INT iSelected = (INT)SendMessage(hwnd, LB_GETCURSEL, 0, 0L);
|
||||
if (LB_ERR == iSelected)
|
||||
return NULL;
|
||||
|
||||
SetupListboxItem *item;
|
||||
return (SUCCEEDED(groups->FindListboxItem(iSelected, &item))) ? item : NULL;
|
||||
}
|
||||
|
||||
BOOL Listbox::SetSelection(SetupListboxItem *item)
|
||||
{
|
||||
INT iItem = LB_ERR;
|
||||
if (NULL != item)
|
||||
{
|
||||
iItem = groups->GetListboxItem(item);
|
||||
if (LB_ERR == iItem)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL resultOk = (LB_ERR != SendMessage(hwnd, LB_SETCURSEL, (WPARAM)iItem, 0L));
|
||||
if (LB_ERR == iItem) resultOk = TRUE;
|
||||
|
||||
if (LB_ERR != iItem)
|
||||
{
|
||||
HWND hParent = GetParent(hwnd);
|
||||
if (NULL != hParent)
|
||||
SendMessage(hParent, WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwnd), LBN_SELCHANGE), (LPARAM)hwnd);
|
||||
}
|
||||
return resultOk;
|
||||
}
|
||||
|
||||
BOOL Listbox::GetIndex(SetupListboxItem *item, INT *iItem)
|
||||
{
|
||||
if (NULL == iItem)
|
||||
return FALSE;
|
||||
|
||||
*iItem = (NULL != item && NULL != groups) ? groups->GetListboxItem(item) : LB_ERR;
|
||||
return (LB_ERR != *iItem);
|
||||
}
|
||||
|
||||
INT_PTR Listbox::KeyToItem(INT vKey, INT iCaret)
|
||||
{
|
||||
SetupListboxItem *item;
|
||||
HRESULT hr = groups->FindListboxItem(iCaret, &item);
|
||||
if (FAILED(hr)) return -1;
|
||||
|
||||
RECT itemRect;
|
||||
GetItemRect(iCaret, &itemRect);
|
||||
INT_PTR result = item->KeyToItem(this, &itemRect, vKey);
|
||||
if (-1 != result) return result;
|
||||
|
||||
INT iTarget, iCount;
|
||||
|
||||
switch(vKey)
|
||||
{
|
||||
case VK_UP:
|
||||
case VK_LEFT:
|
||||
iTarget = GetPrevEnabledItem(iCaret, NULL);
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
|
||||
return -2;
|
||||
|
||||
case VK_DOWN:
|
||||
case VK_RIGHT:
|
||||
iTarget = GetNextEnabledItem(iCaret, NULL);
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)iCaret, 0L);
|
||||
return -2;
|
||||
|
||||
case VK_HOME:
|
||||
if (iCaret > 0)
|
||||
{
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
|
||||
iTarget = GetNextEnabledItem(-1, NULL);
|
||||
if (iTarget >= iCaret) iTarget = LB_ERR;
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
|
||||
}
|
||||
return -2;
|
||||
|
||||
case VK_PRIOR:
|
||||
if (iCaret > 0)
|
||||
{
|
||||
INT iTop = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L);
|
||||
if (iTop == iCaret)
|
||||
{
|
||||
INT iPage = iCaret - GetPageCount() + 1;
|
||||
iTop = (iPage <= 0) ? 0 : (iPage - 1);
|
||||
}
|
||||
|
||||
iTarget = GetPrevEnabledItem(iTop + 1, NULL);
|
||||
|
||||
if (LB_ERR == iTarget)
|
||||
{
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)0, 0L);
|
||||
iTarget = GetNextEnabledItem(iTop, NULL);
|
||||
if (iTarget > iCaret) iTarget = LB_ERR;
|
||||
}
|
||||
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
|
||||
}
|
||||
return -2;
|
||||
|
||||
case VK_END:
|
||||
iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
|
||||
if (iCount > 0 && iCaret != (iCount - 1))
|
||||
{
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L);
|
||||
iTarget = GetPrevEnabledItem(iCount, NULL);
|
||||
if (iTarget <= iCaret) iTarget = LB_ERR;
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
|
||||
}
|
||||
return -2;
|
||||
|
||||
case VK_NEXT:
|
||||
iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
|
||||
if (iCount > 0 && iCaret != (iCount - 1))
|
||||
{
|
||||
INT iPage = GetPageCount();
|
||||
INT iBottom = (INT)SendMessage(hwnd, LB_GETTOPINDEX, 0, 0L) + iPage - 1;
|
||||
if (iBottom == iCaret)
|
||||
{
|
||||
iBottom += iPage;
|
||||
if (iBottom >= iCount) iBottom = iCount -1;
|
||||
}
|
||||
iTarget = GetNextEnabledItem(iBottom - 1, NULL);
|
||||
if (LB_ERR == iTarget)
|
||||
{
|
||||
SendMessage(hwnd, LB_SETTOPINDEX, (WPARAM)(iCount - 1), 0L);
|
||||
iTarget = GetPrevEnabledItem(iBottom, NULL);
|
||||
if (iTarget < iCaret) iTarget = LB_ERR;
|
||||
}
|
||||
|
||||
if (LB_ERR != iTarget) return iTarget;
|
||||
SendMessage(hwnd, LB_SETCARETINDEX, (WPARAM)iCaret, FALSE);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
INT_PTR Listbox::CharToItem(INT vKey, INT caretPos)
|
||||
{
|
||||
return -2;
|
||||
//SetupListboxItem *item;
|
||||
//HRESULT hr = groups->FindListboxItem(caretPos, &item);
|
||||
//return (SUCCEEDED(hr)) ? item->CharToItem(this, vKey) : -1;
|
||||
}
|
||||
|
||||
INT Listbox::GetCheckboxThemeState(BOOL checked, UINT state)
|
||||
{
|
||||
if (FALSE != checked)
|
||||
{
|
||||
if (0 != (ODS_DISABLED & state)) return CBS_CHECKEDDISABLED;
|
||||
if (0 != (ODS_HOTLIGHT & state)) return CBS_CHECKEDHOT;
|
||||
if (0 != (ODS_SELECTED & state)) return CBS_CHECKEDPRESSED;
|
||||
return CBS_CHECKEDNORMAL;
|
||||
}
|
||||
|
||||
if (0 != (ODS_DISABLED & state)) return CBS_UNCHECKEDDISABLED;
|
||||
if (0 != (ODS_HOTLIGHT & state)) return CBS_UNCHECKEDHOT;
|
||||
if (0 != (ODS_SELECTED & state)) return CBS_UNCHECKEDPRESSED;
|
||||
return CBS_UNCHECKEDNORMAL;
|
||||
}
|
||||
|
||||
BOOL Listbox::DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect)
|
||||
{
|
||||
if (NULL != buttonTheme)
|
||||
{
|
||||
INT stateId = GetCheckboxThemeState(checked, state);
|
||||
if (SUCCEEDED(UxDrawThemeBackground(buttonTheme, hdc, BP_CHECKBOX, stateId, pRect, pClipRect)))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
UINT stateId = DFCS_BUTTONCHECK;
|
||||
if (FALSE != checked) stateId |= DFCS_CHECKED;
|
||||
if (0 != (ODS_DISABLED & state)) stateId |= DFCS_INACTIVE;
|
||||
if (0 != (ODS_HOTLIGHT & state)) stateId |= DFCS_HOT;
|
||||
if (0 != (ODS_SELECTED & state)) stateId |= DFCS_PUSHED;
|
||||
|
||||
return DrawFrameControl(hdc, (LPRECT)pRect,DFC_BUTTON, stateId);
|
||||
}
|
||||
|
||||
BOOL Listbox::GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize)
|
||||
{
|
||||
if (NULL != buttonTheme)
|
||||
{
|
||||
HDC hdcMine = NULL;
|
||||
|
||||
if (NULL == hdc)
|
||||
{
|
||||
hdcMine = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
hdc = hdcMine;
|
||||
}
|
||||
|
||||
INT stateId = GetCheckboxThemeState(checked, state);
|
||||
HRESULT hr = UxGetThemePartSize(buttonTheme, hdc, BP_CHECKBOX,
|
||||
stateId, NULL, TS_DRAW, pSize);
|
||||
|
||||
if (NULL != hdcMine)
|
||||
ReleaseDC(hwnd, hdcMine);
|
||||
if (SUCCEEDED(hr)) return TRUE;
|
||||
}
|
||||
pSize->cx = 13;
|
||||
pSize->cy = 13;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Listbox::OnDestroy()
|
||||
{
|
||||
delete(this);
|
||||
}
|
||||
|
||||
|
||||
INT Listbox::HitTest(POINT pt, RECT *prcItem)
|
||||
{
|
||||
RECT itemRect;
|
||||
INT itemId = (INT)SendMessage(hwnd, LB_ITEMFROMPOINT, 0, MAKELONG(pt.x, pt.y));
|
||||
|
||||
if (LB_ERR == itemId ||
|
||||
LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect) ||
|
||||
FALSE == PtInRect(&itemRect, pt))
|
||||
{
|
||||
return LB_ERR;
|
||||
}
|
||||
|
||||
if (NULL != prcItem)
|
||||
CopyRect(prcItem, &itemRect);
|
||||
|
||||
return itemId;
|
||||
}
|
||||
|
||||
void Listbox::GetItemRect(INT itemId, RECT *prcItem)
|
||||
{
|
||||
if (LB_ERR == ::SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)prcItem))
|
||||
SetRectEmpty(prcItem);
|
||||
}
|
||||
|
||||
BOOL Listbox::DoDragAndDrop(UINT mouseEvent, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
if (WM_MOUSEMOVE == mouseEvent &&
|
||||
0 != ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) & mouseFlags))
|
||||
{
|
||||
flags |= SLF_DRAGMOVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags &= ~SLF_DRAGMOVE;
|
||||
}
|
||||
return (0 != (SLF_DRAGMOVE & flags));
|
||||
}
|
||||
|
||||
void Listbox::OnMouseEvent(UINT mouseEvent, UINT mouseFlags, POINTS pts, BOOL fDefaultHandler, ITEMMOUSEPROC proc)
|
||||
{
|
||||
POINT pt;
|
||||
POINTSTOPOINT(pt, pts);
|
||||
SetupListboxItem *item;
|
||||
RECT itemRect;
|
||||
|
||||
if (LB_ERR != capturedId)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(capturedId, &item)))
|
||||
{
|
||||
GetItemRect(capturedId, &itemRect);
|
||||
if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt)))
|
||||
{
|
||||
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
|
||||
}
|
||||
return;
|
||||
}
|
||||
capturedId = LB_ERR;
|
||||
}
|
||||
|
||||
if (DoDragAndDrop(mouseEvent, mouseFlags, pt))
|
||||
return;
|
||||
|
||||
INT itemId = HitTest(pt, &itemRect);
|
||||
if (mouseoverId != itemId)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item)))
|
||||
{
|
||||
RECT leaveRect;
|
||||
GetItemRect(mouseoverId, &leaveRect);
|
||||
item->MouseLeave(this, &leaveRect);
|
||||
}
|
||||
mouseoverId = itemId;
|
||||
|
||||
TRACKMOUSEEVENT tm;
|
||||
tm.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||
tm.hwndTrack = hwnd;
|
||||
tm.dwFlags = TME_LEAVE;
|
||||
if (LB_ERR == mouseoverId)
|
||||
tm.dwFlags |= TME_CANCEL;
|
||||
TrackMouseEvent(&tm);
|
||||
}
|
||||
|
||||
if (LB_ERR != mouseoverId)
|
||||
{
|
||||
if (SUCCEEDED(groups->FindListboxItem(mouseoverId, &item)))
|
||||
{
|
||||
BOOL callListbox = FALSE;
|
||||
if (FALSE != item->IsDisabled())
|
||||
{
|
||||
switch(mouseEvent)
|
||||
{
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case 0x020C /*WM_XBUTTONUP*/:
|
||||
callListbox = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FALSE == ((item->*proc)(this, &itemRect, mouseFlags, pt)))
|
||||
{
|
||||
callListbox = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE != callListbox)
|
||||
{
|
||||
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE != fDefaultHandler)
|
||||
{
|
||||
CallPrevProc(mouseEvent, (WPARAM)mouseFlags, *((LPARAM*)&pts));
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::OnMouseLeave()
|
||||
{
|
||||
if (LB_ERR != mouseoverId)
|
||||
{
|
||||
SetupListboxItem *item;
|
||||
INT itemId = mouseoverId;
|
||||
mouseoverId = LB_ERR;
|
||||
if (SUCCEEDED(groups->FindListboxItem(itemId, &item)))
|
||||
{
|
||||
RECT itemRect;
|
||||
GetItemRect(itemId, &itemRect);
|
||||
if (item->MouseLeave(this, &itemRect))
|
||||
return;
|
||||
}
|
||||
}
|
||||
CallPrevProc(WM_MOUSELEAVE, 0, 0L);
|
||||
}
|
||||
|
||||
void Listbox::SetCapture(SetupListboxItem *item)
|
||||
{
|
||||
INT prevCapturedId = capturedId;
|
||||
capturedId = (NULL != item) ? groups->GetListboxItem(item) : LB_ERR;
|
||||
|
||||
NotifyReleaseCapture(prevCapturedId, item);
|
||||
|
||||
if (LB_ERR != capturedId && ::GetCapture() != hwnd)
|
||||
::SetCapture(hwnd);
|
||||
}
|
||||
|
||||
SetupListboxItem *Listbox::GetCapture()
|
||||
{
|
||||
SetupListboxItem *capturedItem;
|
||||
if (LB_ERR == capturedId || FAILED(groups->FindListboxItem(capturedId, &capturedItem)))
|
||||
capturedItem = NULL;
|
||||
|
||||
return capturedItem;
|
||||
}
|
||||
|
||||
void Listbox::ReleaseCapture()
|
||||
{
|
||||
if (LB_ERR != capturedId)
|
||||
{
|
||||
INT prevCapturedId = capturedId;
|
||||
capturedId = LB_ERR;
|
||||
|
||||
NotifyReleaseCapture(prevCapturedId, NULL);
|
||||
if (::GetCapture() == hwnd)
|
||||
::ReleaseCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::NotifyReleaseCapture(INT itemId, SetupListboxItem *itemGain)
|
||||
{
|
||||
if (LB_ERR == itemId)
|
||||
return;
|
||||
|
||||
SetupListboxItem *item;
|
||||
if (SUCCEEDED(groups->FindListboxItem(itemId, &item)))
|
||||
{
|
||||
RECT itemRect;
|
||||
GetItemRect(itemId, &itemRect);
|
||||
item->CaptureChanged(this, &itemRect, itemGain);
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::OnCaptureChanged(HWND hwndGained)
|
||||
{
|
||||
if (hwnd != hwndGained && LB_ERR != capturedId)
|
||||
{
|
||||
INT prevCapturedId = capturedId;
|
||||
capturedId = LB_ERR;
|
||||
NotifyReleaseCapture(prevCapturedId, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL Listbox::InvalidateRect(const RECT *prcInvalidate, BOOL fErase)
|
||||
{
|
||||
return ::InvalidateRect(hwnd, prcInvalidate, fErase);
|
||||
}
|
||||
|
||||
BOOL Listbox::InvalidateItem(INT itemId, BOOL fErase)
|
||||
{
|
||||
if (itemId < 0) return FALSE;
|
||||
|
||||
RECT itemRect;
|
||||
if (LB_ERR == SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)itemId, (LPARAM)&itemRect))
|
||||
return FALSE;
|
||||
|
||||
return ::InvalidateRect(hwnd, &itemRect, fErase);
|
||||
}
|
||||
|
||||
void Listbox::OnEraseBkGround(HDC hdc)
|
||||
{
|
||||
INT iCount = (INT)SendMessage(hwnd, LB_GETCOUNT, 0, 0L);
|
||||
RECT clientRect, itemRect;
|
||||
|
||||
GetClientRect(hwnd, &clientRect);
|
||||
if (iCount > 0 &&
|
||||
LB_ERR != SendMessage(hwnd, LB_GETITEMRECT, (WPARAM)(iCount - 1), (LPARAM)&itemRect))
|
||||
{
|
||||
clientRect.top = itemRect.top;
|
||||
}
|
||||
|
||||
if (clientRect.top < clientRect.bottom)
|
||||
{
|
||||
HBRUSH hb = NULL;
|
||||
HWND hParent = GetParent(hwnd);
|
||||
if (NULL != hParent)
|
||||
{
|
||||
hb = (HBRUSH)SendMessage(hParent, WM_CTLCOLORLISTBOX, (WPARAM)hdc, (LPARAM)hwnd);
|
||||
}
|
||||
if (NULL == hb)
|
||||
{
|
||||
hb = GetSysColorBrush(COLOR_WINDOW);
|
||||
}
|
||||
FillRect(hdc, &clientRect, hb);
|
||||
}
|
||||
}
|
||||
|
||||
void Listbox::OnCommand(INT commandId, INT eventId, HWND hControl)
|
||||
{
|
||||
if (NULL == hControl)
|
||||
{
|
||||
SetupListboxItem *item = GetSelection();
|
||||
if (NULL != item)
|
||||
{
|
||||
item->Command(this, commandId, eventId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
SetupImage *Listbox::GetExpandboxImage(HDC hdc, BOOL fExpanded)
|
||||
{
|
||||
if (fExpanded)
|
||||
{
|
||||
if (NULL == expandedImage)
|
||||
expandedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(137), 3);
|
||||
return expandedImage;
|
||||
}
|
||||
|
||||
if (NULL == collapsedImage)
|
||||
collapsedImage = SetupImage::CreateFromPluginBitmap(hdc, L"gen_ml.dll", MAKEINTRESOURCE(135), 3);
|
||||
return collapsedImage;
|
||||
}
|
||||
|
||||
BOOL Listbox::DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg)
|
||||
{
|
||||
SetupImage *image = GetExpandboxImage(hdc, fExpanded);
|
||||
return (NULL != image) ?
|
||||
image->DrawImage(hdc, pRect->left, pRect->top,
|
||||
pRect->right - pRect->left, pRect->bottom- pRect->top,
|
||||
0, 0, rgbBk, rgbFg)
|
||||
: FALSE;
|
||||
}
|
||||
|
||||
BOOL Listbox::GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize)
|
||||
{
|
||||
SetupImage *image = GetExpandboxImage(hdc, fExpanded);
|
||||
return (NULL != image) ? image->GetSize(pSize) : FALSE;
|
||||
}
|
||||
|
||||
HMENU Listbox::GetContextMenu(UINT menuId)
|
||||
{
|
||||
HMENU baseMenu = WASABI_API_LOADMENUW(IDR_SETUPMENU);
|
||||
if (NULL == baseMenu)
|
||||
return NULL;
|
||||
|
||||
switch(menuId)
|
||||
{
|
||||
case menuGroupContext:
|
||||
return GetSubMenu(baseMenu, 0);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LRESULT Listbox::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
OnDestroy();
|
||||
return 0;
|
||||
case WM_MOUSEMOVE:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::MouseMove);
|
||||
return 0;
|
||||
case WM_LBUTTONDOWN:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDown);
|
||||
return 0;
|
||||
case WM_LBUTTONUP:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::LButtonUp);
|
||||
return 0;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::LButtonDblClk);
|
||||
return 0;
|
||||
case WM_RBUTTONDOWN:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), FALSE, &SetupListboxItem::RButtonDown);
|
||||
return 0;
|
||||
case WM_RBUTTONUP:
|
||||
OnMouseEvent(uMsg, (UINT)wParam, MAKEPOINTS(lParam), TRUE, &SetupListboxItem::RButtonUp);
|
||||
return 0;
|
||||
case WM_MOUSELEAVE:
|
||||
OnMouseLeave();
|
||||
return 0;
|
||||
case WM_CAPTURECHANGED:
|
||||
OnCaptureChanged((HWND)lParam);
|
||||
break;
|
||||
case WM_ERASEBKGND:
|
||||
OnEraseBkGround((HDC)wParam);
|
||||
return TRUE;
|
||||
case WM_COMMAND:
|
||||
OnCommand(LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CallPrevProc(uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
static LRESULT WINAPI Listbox_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Listbox *list = GetList(hwnd);
|
||||
if (NULL != list)
|
||||
return list->WindowProc(uMsg, wParam, lParam);
|
||||
|
||||
return (IsWindowUnicode(hwnd)) ?
|
||||
DefWindowProcW(hwnd, uMsg, wParam, lParam) :
|
||||
DefWindowProcA(hwnd, uMsg, wParam, lParam);
|
||||
|
||||
}
|
84
Src/Plugins/Library/ml_online/Setup/setupListbox.h
Normal file
84
Src/Plugins/Library/ml_online/Setup/setupListbox.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class SetupGroupList;
|
||||
class SetupListboxItem;
|
||||
|
||||
class __declspec(novtable) SetupListbox
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
menuGroupContext = 0,
|
||||
} contextMenu;
|
||||
|
||||
public:
|
||||
static HRESULT CreateInstance(HWND hListbox, SetupGroupList *groupList, SetupListbox **pInstance);
|
||||
static SetupListbox *GetInstance(HWND hListbox);
|
||||
|
||||
public:
|
||||
virtual HWND GetHwnd() = 0;
|
||||
virtual HFONT GetFont() = 0;
|
||||
virtual LRESULT CallDefaultProc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
|
||||
virtual LRESULT CallPrevProc(UINT uMsg, WPARAM wParam, LPARAM lParam) = 0;
|
||||
|
||||
virtual BOOL MeasureItem(INT itemId, UINT *cx, UINT *cy) = 0;
|
||||
virtual BOOL DrawItem(HDC hdc, const RECT *prcItem, INT itemId, UINT itemState, UINT itemAction) = 0;
|
||||
virtual INT_PTR KeyToItem(INT vKey, INT caretPos) = 0;
|
||||
virtual INT_PTR CharToItem(INT vKey, INT caretPos) = 0;
|
||||
|
||||
virtual BOOL DrawCheckbox(HDC hdc, BOOL checked, UINT state, const RECT *pRect, const RECT *pClipRect) = 0;
|
||||
virtual BOOL GetCheckboxMetrics(HDC hdc, BOOL checked, UINT state, SIZE *pSize) = 0;
|
||||
virtual void SetCapture(SetupListboxItem *item) = 0;
|
||||
virtual SetupListboxItem *GetCapture() = 0;
|
||||
virtual void ReleaseCapture() = 0;
|
||||
|
||||
virtual BOOL InvalidateRect(const RECT *prcInvalidate, BOOL fErase) = 0;
|
||||
virtual BOOL InvalidateItem(INT iItem, BOOL fErase) = 0;
|
||||
virtual void UpdateCount() = 0;
|
||||
|
||||
|
||||
virtual BOOL DrawExpandbox(HDC hdc, BOOL fExpanded, const RECT *pRect, COLORREF rgbBk, COLORREF rgbFg) = 0;
|
||||
virtual BOOL GetExpandboxMetrics(HDC hdc, BOOL fExpanded, SIZE *pSize) = 0;
|
||||
|
||||
virtual INT GetPageCount() = 0;
|
||||
virtual INT GetNextEnabledItem(INT iItem, SetupListboxItem **itemOut) = 0;
|
||||
virtual INT GetPrevEnabledItem(INT iItem, SetupListboxItem **itemOut) = 0;
|
||||
virtual SetupListboxItem *GetSelection() = 0;
|
||||
virtual BOOL SetSelection(SetupListboxItem *item) = 0;
|
||||
virtual BOOL GetIndex(SetupListboxItem *item, INT *iItem) = 0;
|
||||
|
||||
virtual HMENU GetContextMenu(UINT menuId) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class __declspec(novtable) SetupListboxItem
|
||||
{
|
||||
|
||||
public:
|
||||
virtual BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy) = 0;
|
||||
virtual BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state) = 0;
|
||||
virtual INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey) = 0;
|
||||
virtual BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem) = 0;
|
||||
virtual BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt) = 0;
|
||||
virtual void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured) = 0;
|
||||
virtual BOOL IsDisabled() = 0;
|
||||
virtual void Command(SetupListbox *instance, INT commandId, INT eventId) = 0;
|
||||
|
||||
virtual HWND CreateDetailsView(HWND hParent) = 0;
|
||||
virtual BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax) = 0;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_HEADER
|
228
Src/Plugins/Library/ml_online/Setup/setupListboxLabel.cpp
Normal file
228
Src/Plugins/Library/ml_online/Setup/setupListboxLabel.cpp
Normal file
|
@ -0,0 +1,228 @@
|
|||
#include "./setupListboxLabel.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include "../common.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define LABEL_MARGINCX 0
|
||||
#define LABEL_MARGINCY 1
|
||||
|
||||
#define TEXT_OFFSET_LEFT 2
|
||||
#define TEXT_OFFSET_BOTTOM 2
|
||||
#define TEXT_ALIGN (TA_CENTER | TA_BOTTOM)
|
||||
|
||||
SetupListboxLabel::SetupListboxLabel(LPCWSTR pszName)
|
||||
: ref(1), name(NULL)
|
||||
{
|
||||
SetName(pszName);
|
||||
}
|
||||
|
||||
SetupListboxLabel::~SetupListboxLabel()
|
||||
{
|
||||
SetName(NULL);
|
||||
}
|
||||
|
||||
SetupListboxLabel *SetupListboxLabel::CreateInstance(LPCWSTR pszName)
|
||||
{
|
||||
return new SetupListboxLabel(pszName);
|
||||
}
|
||||
|
||||
ULONG SetupListboxLabel::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupListboxLabel::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
return r;
|
||||
}
|
||||
|
||||
HRESULT SetupListboxLabel::GetName(LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
|
||||
if (NULL != name && IS_INTRESOURCE(name))
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF((INT)(INT_PTR)name, pszBuffer, cchBufferMax);
|
||||
return (L'\0' != *pszBuffer) ? S_OK : E_FAIL;
|
||||
}
|
||||
return StringCchCopyExW(pszBuffer, cchBufferMax, name, NULL, NULL, STRSAFE_IGNORE_NULLS);
|
||||
}
|
||||
HRESULT SetupListboxLabel::SetName(LPCWSTR pszName)
|
||||
{
|
||||
if (NULL != name && !IS_INTRESOURCE(name))
|
||||
Plugin_FreeString(name);
|
||||
|
||||
if (IS_INTRESOURCE(pszName))
|
||||
{
|
||||
name = (LPWSTR)pszName;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = Plugin_CopyString(pszName);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL SetupListboxLabel::IsNameNull()
|
||||
{
|
||||
return (NULL == name);
|
||||
}
|
||||
|
||||
void SetupListboxLabel::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
|
||||
{
|
||||
COLORREF rgbBk, rgbText;
|
||||
|
||||
rgbBk = GetSysColor(COLOR_WINDOW);
|
||||
rgbText = GetSysColor( (0 == (ODS_DISABLED & state)) ? COLOR_GRAYTEXT : COLOR_GRAYTEXT);
|
||||
|
||||
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
|
||||
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
|
||||
}
|
||||
|
||||
HBRUSH SetupListboxLabel::GetBrush(HDC hdc, UINT state)
|
||||
{
|
||||
return GetSysColorBrush(COLOR_WINDOW);
|
||||
}
|
||||
|
||||
BOOL SetupListboxLabel::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
|
||||
{
|
||||
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL == hdc) return FALSE;
|
||||
|
||||
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
|
||||
|
||||
if (NULL != cy)
|
||||
{
|
||||
*cy = 0;
|
||||
TEXTMETRIC tm;
|
||||
if (GetTextMetrics(hdc, &tm))
|
||||
*cy = tm.tmHeight + tm.tmExternalLeading + LABEL_MARGINCY*2;
|
||||
}
|
||||
|
||||
if (NULL != cx)
|
||||
{
|
||||
*cx = 0;
|
||||
WCHAR szBuffer[128] = {0};
|
||||
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
INT cchBuffer = lstrlenW(szBuffer);
|
||||
SIZE textSize;
|
||||
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
|
||||
{
|
||||
*cx = textSize.cx + LABEL_MARGINCX*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SelectObject(hdc, originalFont);
|
||||
ReleaseDC(instance->GetHwnd(), hdc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupListboxLabel::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
|
||||
{
|
||||
LONG paintLeft = prc->left + LABEL_MARGINCX;
|
||||
|
||||
COLORREF rgbBk, rgbText;
|
||||
GetColors(hdc, state, &rgbBk, &rgbText);
|
||||
|
||||
COLORREF origBk = SetBkColor(hdc, rgbBk);
|
||||
COLORREF origText = SetTextColor(hdc, rgbText);
|
||||
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
|
||||
|
||||
HRGN backRgn, rgn;
|
||||
backRgn = CreateRectRgnIndirect(prc);
|
||||
rgn = CreateRectRgn(0,0,0,0);
|
||||
|
||||
RECT partRect;
|
||||
WCHAR szBuffer[128] = {0};
|
||||
INT cchBuffer = 0;
|
||||
|
||||
if (SUCCEEDED(GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
cchBuffer = lstrlenW(szBuffer);
|
||||
|
||||
SetRect(&partRect, paintLeft, prc->top, prc->right - LABEL_MARGINCX, prc->bottom);
|
||||
if (ExtTextOut(hdc, partRect.left + (partRect.right - partRect.left)/2, partRect.bottom - TEXT_OFFSET_BOTTOM,
|
||||
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
|
||||
{
|
||||
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
}
|
||||
|
||||
if (NULL != backRgn)
|
||||
{
|
||||
FillRgn(hdc, backRgn, GetBrush(hdc, state));
|
||||
DeleteObject(backRgn);
|
||||
}
|
||||
if (NULL != rgn)
|
||||
DeleteObject(rgn);
|
||||
|
||||
|
||||
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
|
||||
DrawFocusRect(hdc, prc);
|
||||
|
||||
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
|
||||
if (origBk != rgbBk) SetBkColor(hdc, origBk);
|
||||
if (origText != rgbText) SetTextColor(hdc, origText);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
INT_PTR SetupListboxLabel::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
BOOL SetupListboxLabel::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::MouseLeave(SetupListbox *instance, const RECT *prcItem)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
BOOL SetupListboxLabel::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
void SetupListboxLabel::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
|
||||
{
|
||||
}
|
||||
|
||||
BOOL SetupListboxLabel::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
WCHAR szName[128] = {0};
|
||||
if (FAILED(GetName(szName, ARRAYSIZE(szName))))
|
||||
return FALSE;
|
||||
|
||||
if (NULL == pszBuffer ||
|
||||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"lbl_empty_%s", szName)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
57
Src/Plugins/Library/ml_online/Setup/setupListboxLabel.h
Normal file
57
Src/Plugins/Library/ml_online/Setup/setupListboxLabel.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "./setupListbox.h"
|
||||
|
||||
|
||||
class SetupListboxLabel: public SetupListboxItem
|
||||
{
|
||||
|
||||
protected:
|
||||
SetupListboxLabel(LPCWSTR pszName);
|
||||
~SetupListboxLabel();
|
||||
|
||||
public:
|
||||
static SetupListboxLabel *CreateInstance(LPCWSTR pszNamee);
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
HRESULT GetName(LPWSTR pszBuffer, INT cchBufferMax);
|
||||
HRESULT SetName(LPCWSTR pszName);
|
||||
BOOL IsNameNull();
|
||||
|
||||
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
|
||||
HBRUSH GetBrush(HDC hdc, UINT state);
|
||||
|
||||
|
||||
/* SetupListboxItem */
|
||||
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
|
||||
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
|
||||
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
|
||||
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
|
||||
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
|
||||
BOOL IsDisabled() { return TRUE; }
|
||||
void Command(SetupListbox *instance, INT commandId, INT eventId) {}
|
||||
HWND CreateDetailsView(HWND hParent) { return NULL; }
|
||||
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
LPWSTR name;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLISTBOX_LABEL_HEADER
|
395
Src/Plugins/Library/ml_online/Setup/setupLog.cpp
Normal file
395
Src/Plugins/Library/ml_online/Setup/setupLog.cpp
Normal file
|
@ -0,0 +1,395 @@
|
|||
#include "./setupLog.h"
|
||||
#include "../common.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include "../config.h"
|
||||
|
||||
#include "../../nu/trace.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omwebstorage.h>
|
||||
#include <ifc_omstorageasync.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define SETUPLOG_SEPARATOR ','
|
||||
#define SETUPLOG_SECTION "Setup"
|
||||
#define SETUPLOG_KEY_SUBSCRIBED "subscribed"
|
||||
#define SETUPLOG_KEY_UNSUBSCRIBED "unsubscribed"
|
||||
|
||||
struct LOGPARSERPARAM
|
||||
{
|
||||
LOGPARSERPARAM() : instance(NULL), operation(0) {}
|
||||
|
||||
SetupLog *instance;
|
||||
UINT operation;
|
||||
};
|
||||
|
||||
static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap)
|
||||
{
|
||||
SetupLog::ServiceMap::iterator it;
|
||||
|
||||
size_t c1 = 0, c2 = 0;
|
||||
for (it = serviceMap->begin(); it != serviceMap->end(); it++)
|
||||
{
|
||||
switch(it->second)
|
||||
{
|
||||
case SetupLog::opServiceAdded:
|
||||
c1++;
|
||||
break;
|
||||
case SetupLog::opServiceRemoved:
|
||||
c2++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (c1 > c2) ? c1 : c2;
|
||||
}
|
||||
|
||||
static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*pszBuffer = '\0';
|
||||
|
||||
if (NULL == serviceMap)
|
||||
return S_OK;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
size_t remaining = cchBufferMax;
|
||||
LPSTR cursor = pszBuffer;
|
||||
SetupLog::ServiceMap::iterator it;
|
||||
|
||||
const char format[] = { SETUPLOG_SEPARATOR, '%', 'u', '\0'};
|
||||
|
||||
for (it = serviceMap->begin(); it != serviceMap->end() && SUCCEEDED(hr); it++)
|
||||
{
|
||||
if (it->second == operation)
|
||||
{
|
||||
hr = StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
((cursor == pszBuffer) ? (format + 1) : format), it->first);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static LPCSTR SetupLog_GetOperationKey(UINT operation)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case SetupLog::opServiceAdded: return SETUPLOG_KEY_SUBSCRIBED;
|
||||
case SetupLog::opServiceRemoved: return SETUPLOG_KEY_UNSUBSCRIBED;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static LPCWSTR SetupLog_GetOperationAction(UINT operation)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case SetupLog::opServiceAdded: return L"add";
|
||||
case SetupLog::opServiceRemoved: return L"remove";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL SetupLog_WriteOperationLog(UINT operation, LPCSTR pszValue)
|
||||
{
|
||||
LPCSTR pszKey = SetupLog_GetOperationKey(operation);
|
||||
if (NULL == pszKey) return FALSE;
|
||||
return Config_WriteStr(SETUPLOG_SECTION, pszKey, pszValue);
|
||||
}
|
||||
|
||||
static HRESULT SetupLog_ReadOperationLog(UINT operation, LPSTR pszBuffer, UINT cchBufferMax, UINT *cchReaded)
|
||||
{
|
||||
LPCSTR pszKey = SetupLog_GetOperationKey(operation);
|
||||
if (NULL == pszKey) return E_INVALIDARG;
|
||||
|
||||
DWORD readed = Config_ReadStr(SETUPLOG_SECTION, pszKey, NULL, pszBuffer, cchBufferMax);
|
||||
|
||||
if (NULL != cchReaded)
|
||||
{
|
||||
*cchReaded = readed;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
SetupLog::SetupLog() : ref(1)
|
||||
{
|
||||
}
|
||||
|
||||
SetupLog::~SetupLog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SetupLog *SetupLog::Open()
|
||||
{
|
||||
SetupLog *instance = new SetupLog();
|
||||
if (NULL == instance) return NULL;
|
||||
|
||||
INT cchBuffer = 32000;
|
||||
LPSTR buffer = Plugin_MallocAnsiString(cchBuffer);
|
||||
if (NULL == buffer)
|
||||
{
|
||||
instance->Release();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT cchReaded = 0;
|
||||
const UINT szOperations[] = { opServiceAdded,
|
||||
opServiceRemoved, };
|
||||
|
||||
UINT serviceId;
|
||||
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
|
||||
{
|
||||
if (SUCCEEDED(SetupLog_ReadOperationLog(szOperations[i], buffer, cchBuffer, &cchReaded)) && cchReaded > 0)
|
||||
{
|
||||
LPSTR cursor = buffer;
|
||||
LPSTR block = cursor;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (SETUPLOG_SEPARATOR == *cursor || '\0' == *cursor)
|
||||
{
|
||||
while (' ' == *block && block < cursor) block++;
|
||||
|
||||
if (block < cursor &&
|
||||
FALSE != StrToIntExA(block, STIF_SUPPORT_HEX, (INT*)&serviceId) &&
|
||||
0 != serviceId)
|
||||
{
|
||||
instance->LogServiceById(serviceId, szOperations[i]);
|
||||
}
|
||||
|
||||
if ('\0' == *cursor)
|
||||
break;
|
||||
|
||||
cursor++;
|
||||
block = cursor;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Plugin_FreeAnsiString(buffer);
|
||||
return instance;
|
||||
}
|
||||
|
||||
ULONG SetupLog::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupLog::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
BOOL SetupLog::IsOperationSupported(UINT operation)
|
||||
{
|
||||
switch(operation)
|
||||
{
|
||||
case SetupLog::opServiceAdded:
|
||||
case SetupLog::opServiceRemoved:
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
HRESULT SetupLog::LogServiceById(UINT serviceUid, UINT operation)
|
||||
{
|
||||
if (0 == serviceUid || FALSE == IsOperationSupported(operation))
|
||||
return E_INVALIDARG;
|
||||
|
||||
serviceMap[serviceUid] = operation;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupLog::LogService(ifc_omservice *service, UINT operation)
|
||||
{
|
||||
if (NULL == service || !IsOperationSupported(operation))
|
||||
return E_INVALIDARG;
|
||||
|
||||
return LogServiceById(service->GetId(), operation);
|
||||
}
|
||||
|
||||
HRESULT SetupLog::Save()
|
||||
{
|
||||
LPSTR buffer = NULL;
|
||||
size_t cchBuffer = SetupLog_GetMaxServiceIdCount(&serviceMap) * 11;
|
||||
|
||||
if (0 != cchBuffer)
|
||||
{
|
||||
cchBuffer += 1;
|
||||
buffer = Plugin_MallocAnsiString(cchBuffer);
|
||||
if (NULL == buffer)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
const UINT szOperations[] = { opServiceAdded,
|
||||
opServiceRemoved, };
|
||||
|
||||
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
|
||||
{
|
||||
LPCSTR value = (NULL != buffer &&
|
||||
SUCCEEDED(SetupLog_FormatServiceId(&serviceMap, szOperations[i], buffer, cchBuffer)) &&
|
||||
'\0' != *buffer) ? buffer : NULL;
|
||||
SetupLog_WriteOperationLog(szOperations[i], value);
|
||||
}
|
||||
|
||||
if (NULL != buffer)
|
||||
Plugin_FreeAnsiString(buffer);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupLog::Erase()
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_SUBSCRIBED, NULL))
|
||||
hr = E_FAIL;
|
||||
if (FALSE == Config_WriteStr(SETUPLOG_SECTION, SETUPLOG_KEY_UNSUBSCRIBED, NULL))
|
||||
hr = E_FAIL;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
struct LOGSENDJOBPARAM
|
||||
{
|
||||
LOGSENDJOBPARAM() : totalJobs(0), storage(NULL), completeEvent(NULL) {}
|
||||
|
||||
ULONG totalJobs;
|
||||
CRITICAL_SECTION lock;
|
||||
ifc_omstorage *storage;
|
||||
HANDLE completeEvent;
|
||||
};
|
||||
|
||||
static void CALLBACK SetupLog_SendCompleted(ifc_omstorageasync *async)
|
||||
{
|
||||
if (NULL != async)
|
||||
{
|
||||
LOGSENDJOBPARAM *param = NULL;
|
||||
if (SUCCEEDED(async->GetData((void**)¶m)) && NULL != param)
|
||||
{
|
||||
EnterCriticalSection(¶m->lock);
|
||||
|
||||
if (NULL != param->storage)
|
||||
{
|
||||
param->storage->EndLoad(async, NULL);
|
||||
param->storage->Release();
|
||||
}
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)¶m->totalJobs);
|
||||
if (0 == r)
|
||||
{
|
||||
if (NULL != param->completeEvent)
|
||||
SetEvent(param->completeEvent);
|
||||
|
||||
LeaveCriticalSection(¶m->lock);
|
||||
DeleteCriticalSection(¶m->lock);
|
||||
free(param);
|
||||
param = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(¶m->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT SetupLog::Send(HANDLE completeEvent)
|
||||
{
|
||||
size_t cchAlloc = serviceMap.size();
|
||||
if (0 == cchAlloc)
|
||||
{
|
||||
if (NULL != completeEvent) SetEvent(completeEvent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
UINT *buffer = (UINT*)calloc(cchAlloc, sizeof(UINT));
|
||||
LOGSENDJOBPARAM *param = (LOGSENDJOBPARAM*)calloc(1, sizeof(LOGSENDJOBPARAM));
|
||||
|
||||
if (NULL == buffer || NULL == param)
|
||||
{
|
||||
if (NULL != buffer) { free(buffer); buffer = NULL; }
|
||||
if (NULL != param) { free(param); param = NULL; }
|
||||
if (NULL != completeEvent) { SetEvent(completeEvent); completeEvent = NULL; }
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
ifc_omstorage *storage = NULL;
|
||||
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
|
||||
if (SUCCEEDED(hr) && storage != NULL)
|
||||
{
|
||||
const UINT szOperations[] = { opServiceAdded,
|
||||
opServiceRemoved, };
|
||||
param->totalJobs = 0;
|
||||
param->completeEvent = completeEvent;
|
||||
param->storage = storage;
|
||||
|
||||
InitializeCriticalSection(¶m->lock);
|
||||
EnterCriticalSection(¶m->lock);
|
||||
|
||||
for (INT i = 0; i < ARRAYSIZE(szOperations); i++)
|
||||
{
|
||||
size_t count = 0;
|
||||
hr = S_OK;
|
||||
for (SetupLog::ServiceMap::iterator it = serviceMap.begin(); it != serviceMap.end() && SUCCEEDED(hr); it++)
|
||||
{
|
||||
if (it->second == szOperations[i])
|
||||
{
|
||||
buffer[count] = it->first;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (0 != count)
|
||||
{
|
||||
LPWSTR url = NULL;
|
||||
LPCWSTR action = SetupLog_GetOperationAction(szOperations[i]);
|
||||
if (NULL != action &&
|
||||
SUCCEEDED(Plugin_BuildActionUrl(&url, action, buffer, count)))
|
||||
{
|
||||
ifc_omstorageasync *async = NULL;;
|
||||
if (SUCCEEDED(storage->BeginLoad(url, NULL, SetupLog_SendCompleted, param, &async)))
|
||||
{
|
||||
InterlockedIncrement((LONG*)¶m->totalJobs);
|
||||
storage->AddRef();
|
||||
async->Release();
|
||||
}
|
||||
Plugin_FreeString(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == param->totalJobs)
|
||||
{
|
||||
LeaveCriticalSection(¶m->lock);
|
||||
DeleteCriticalSection(¶m->lock);
|
||||
hr = E_FAIL;
|
||||
if (param) { free(param); param = NULL; }
|
||||
}
|
||||
else
|
||||
{
|
||||
LeaveCriticalSection(¶m->lock);
|
||||
}
|
||||
|
||||
storage->Release();
|
||||
}
|
||||
|
||||
if (buffer) { free(buffer); buffer = NULL; }
|
||||
return hr;
|
||||
}
|
54
Src/Plugins/Library/ml_online/Setup/setupLog.h
Normal file
54
Src/Plugins/Library/ml_online/Setup/setupLog.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <map>
|
||||
|
||||
class ifc_omservice;
|
||||
|
||||
class SetupLog
|
||||
{
|
||||
public:
|
||||
typedef enum
|
||||
{
|
||||
opUnknown = 0,
|
||||
opServiceAdded = 1,
|
||||
opServiceRemoved = 2,
|
||||
};
|
||||
|
||||
protected:
|
||||
SetupLog();
|
||||
~SetupLog();
|
||||
|
||||
public:
|
||||
static SetupLog *Open();
|
||||
static HRESULT Erase();
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
HRESULT LogServiceById(UINT serviceUid, UINT operation);
|
||||
HRESULT LogService(ifc_omservice *service, UINT operation);
|
||||
HRESULT Save();
|
||||
HRESULT Send(HANDLE completeEvent);
|
||||
|
||||
BOOL IsOperationSupported(UINT operation);
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
typedef std::map<UINT, UINT> ServiceMap;
|
||||
friend static size_t SetupLog_GetMaxServiceIdCount(SetupLog::ServiceMap *serviceMap);
|
||||
friend static HRESULT SetupLog_FormatServiceId(SetupLog::ServiceMap *serviceMap, INT operation, LPSTR pszBuffer, size_t cchBufferMax);
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
ServiceMap serviceMap;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPLOG_HEADER
|
648
Src/Plugins/Library/ml_online/Setup/setupPage.cpp
Normal file
648
Src/Plugins/Library/ml_online/Setup/setupPage.cpp
Normal file
|
@ -0,0 +1,648 @@
|
|||
#include "./setupPage.h"
|
||||
#include "./setupListbox.h"
|
||||
#include "./setupGroupList.h"
|
||||
#include "./setupGroupFilter.h"
|
||||
#include "./setupListboxLabel.h"
|
||||
#include "../common.h"
|
||||
#include "../config.h"
|
||||
#include "../resource.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
#include "./setupDetails.h"
|
||||
#include "./setupLog.h"
|
||||
|
||||
#include "../../winamp/setup/svc_setup.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omfilestorage.h>
|
||||
#include <ifc_omwebstorage.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <vector>
|
||||
|
||||
#define FEATURED_SERVICES_URL L"http://services.winamp.com/svc/default"
|
||||
|
||||
#define IDC_DETAILS 10000
|
||||
|
||||
typedef std::vector<ifc_omservice*> ServiceList;
|
||||
typedef std::vector<UINT> ServiceIdList;
|
||||
|
||||
HWND SetupPage_CreateWindow(HWND hParent, SetupPage *page);
|
||||
static INT_PTR SetupPage_ModalLoop(HWND hwnd, HACCEL hAccel, HANDLE hCancel);
|
||||
|
||||
struct AppendServiceToStringData
|
||||
{
|
||||
AppendServiceToStringData() : formatFirst(NULL), formatNext(NULL), cursor(NULL),
|
||||
remaining(0), inserted(0), result(S_OK) {}
|
||||
|
||||
LPCWSTR formatFirst;
|
||||
LPCWSTR formatNext;
|
||||
LPWSTR cursor;
|
||||
size_t remaining;
|
||||
size_t inserted;
|
||||
HRESULT result;
|
||||
};
|
||||
|
||||
static BOOL CALLBACK SetupPage_AppendServiceToStringCallback(UINT serviceId, void *data)
|
||||
{
|
||||
AppendServiceToStringData *param = (AppendServiceToStringData*)data;
|
||||
if (NULL == param) return FALSE;
|
||||
|
||||
param->result = StringCchPrintfEx(param->cursor, param->remaining, ¶m->cursor, ¶m->remaining,
|
||||
STRSAFE_NULL_ON_FAILURE,
|
||||
((0 == param->inserted) ? param->formatFirst : param->formatNext), serviceId);
|
||||
|
||||
if (FAILED(param->result))
|
||||
return FALSE;
|
||||
|
||||
param->inserted++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL CALLBACK SetupPage_AppendServiceIdCallback(UINT serviceId, void *data)
|
||||
{
|
||||
ServiceIdList *list = (ServiceIdList*)data;
|
||||
if (NULL == list) return FALSE;
|
||||
list->push_back(serviceId);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static HRESULT SetupPage_GetFeaturedServicesUrl(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
LPWSTR cursor = pszBuffer;
|
||||
size_t remaining = cchBufferMax;
|
||||
|
||||
HRESULT hr = StringCchCopyEx(cursor, remaining, FEATURED_SERVICES_URL, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
AppendServiceToStringData param;
|
||||
param.cursor = cursor;
|
||||
param.remaining = remaining;
|
||||
param.formatFirst = L"?svc_ids=%u";
|
||||
param.formatNext = L",%u";
|
||||
param.inserted = 0;
|
||||
param.result = S_OK;
|
||||
|
||||
hr = Config_ReadServiceIdList("Setup", "featuredExtra", ',', SetupPage_AppendServiceToStringCallback, ¶m);
|
||||
if (SUCCEEDED(hr))
|
||||
hr = param.result;
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
SetupPage* SetupPage::CreateInstance()
|
||||
{
|
||||
SetupPage *instance = new SetupPage();
|
||||
return instance;
|
||||
}
|
||||
|
||||
SetupPage::SetupPage()
|
||||
: ref(1), hwnd(NULL), name(NULL), title(NULL),
|
||||
groupList(NULL), completeEvent(NULL),
|
||||
servicesInitialized(FALSE)
|
||||
{
|
||||
WasabiApi_AddRef();
|
||||
SetupDetails_Initialize();
|
||||
}
|
||||
|
||||
SetupPage::~SetupPage()
|
||||
{
|
||||
if (NULL != name)
|
||||
{
|
||||
Plugin_FreeString(name);
|
||||
name = NULL;
|
||||
}
|
||||
|
||||
if (NULL != title)
|
||||
{
|
||||
Plugin_FreeString(title);
|
||||
title = NULL;
|
||||
}
|
||||
|
||||
if (NULL != groupList)
|
||||
{
|
||||
groupList->Release();
|
||||
groupList = NULL;
|
||||
}
|
||||
|
||||
if (NULL != completeEvent)
|
||||
{
|
||||
CloseHandle(completeEvent);
|
||||
completeEvent = NULL;
|
||||
}
|
||||
|
||||
SetupDetails_Uninitialize();
|
||||
|
||||
if (FALSE != servicesInitialized)
|
||||
{
|
||||
if (NULL != OMBROWSERMNGR)
|
||||
OMBROWSERMNGR->Finish();
|
||||
}
|
||||
|
||||
WasabiApi_Release();
|
||||
}
|
||||
|
||||
size_t SetupPage::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t SetupPage::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int SetupPage::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object) return E_POINTER;
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::GetName(bool bShort, const wchar_t **pszName)
|
||||
{
|
||||
InitializeServices();
|
||||
|
||||
if (false == bShort)
|
||||
{
|
||||
if (NULL == title)
|
||||
{
|
||||
WCHAR szBuffer[128] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SETUPPAGE_TITLE, szBuffer, ARRAYSIZE(szBuffer));
|
||||
title = Plugin_CopyString(szBuffer);
|
||||
}
|
||||
*pszName = title;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NULL == name)
|
||||
{
|
||||
WCHAR szBuffer[128] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_ONLINE_SERVICES, szBuffer, ARRAYSIZE(szBuffer));
|
||||
name = Plugin_CopyString(szBuffer);
|
||||
}
|
||||
*pszName = name;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::Save(HWND hwndText)
|
||||
{
|
||||
if (NULL == groupList)
|
||||
return S_OK;
|
||||
|
||||
SetupLog *log = SetupLog::Open();
|
||||
HRESULT hr = groupList->Save(log);
|
||||
|
||||
if (NULL != log)
|
||||
{
|
||||
log->Save();
|
||||
log->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::Revert(void)
|
||||
{
|
||||
HRESULT hr(S_OK);
|
||||
|
||||
if (NULL != groupList)
|
||||
{
|
||||
groupList->Release();
|
||||
groupList = NULL;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::IsDirty(void)
|
||||
{
|
||||
return (NULL != groupList && groupList->IsModified()) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::Validate(void)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::InitializeServices()
|
||||
{
|
||||
if (FALSE != servicesInitialized)
|
||||
return S_FALSE;
|
||||
|
||||
HWND hWinamp = NULL;
|
||||
svc_setup *setupSvc = QueryWasabiInterface(svc_setup, UID_SVC_SETUP);
|
||||
if (NULL == setupSvc) return E_UNEXPECTED;
|
||||
HRESULT hr = setupSvc->GetWinampWnd(&hWinamp);
|
||||
ReleaseWasabiInterface(UID_SVC_SETUP, setupSvc);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = WasabiApi_LoadDefaults();
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (NULL != OMBROWSERMNGR &&
|
||||
NULL != OMSERVICEMNGR &&
|
||||
NULL != OMUTILITY)
|
||||
{
|
||||
hr = OMBROWSERMNGR->Initialize(NULL, hWinamp);
|
||||
}
|
||||
else
|
||||
hr = E_UNEXPECTED;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
servicesInitialized = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::CreateView(HWND hParent, HWND *phwnd)
|
||||
{
|
||||
if (NULL == phwnd)
|
||||
return E_INVALIDARG;
|
||||
|
||||
if (FAILED(InitializeServices()))
|
||||
{
|
||||
*phwnd = NULL;
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*phwnd = SetupPage_CreateWindow(hParent, this);
|
||||
return (NULL == phwnd) ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
|
||||
BOOL SetupPage::UpdateListAsync(INT groupId)
|
||||
{
|
||||
if (NULL == hwnd)
|
||||
return FALSE;
|
||||
|
||||
return PostMessage(hwnd, SPM_UPDATELIST, (WPARAM)groupId, NULL);
|
||||
}
|
||||
|
||||
BOOL SetupPage::AttachWindow(HWND hAttach)
|
||||
{
|
||||
hwnd = hAttach;
|
||||
|
||||
if (NULL == completeEvent)
|
||||
completeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
|
||||
if (NULL == groupList)
|
||||
{
|
||||
groupList = SetupGroupList::CreateInstance();
|
||||
if (NULL != groupList)
|
||||
{
|
||||
WCHAR szBuffer[4096] = {0};
|
||||
SetupPage_GetFeaturedServicesUrl(szBuffer, ARRAYSIZE(szBuffer));
|
||||
|
||||
SetupGroup *group = SetupGroup::CreateInstance(ID_FEATUREDGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED),
|
||||
szBuffer, &SUID_OmStorageUrl, &FUID_SetupFeaturedGroupFilter,
|
||||
SetupGroup::styleSortAlphabetically | SetupGroup::styleDefaultSubscribed | SetupGroup::styleSaveAll);
|
||||
if (NULL != group)
|
||||
{
|
||||
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATUREDLONG));
|
||||
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED_DESC));
|
||||
groupList->AddGroup(group);
|
||||
group->RequestReload();
|
||||
group->Release();
|
||||
}
|
||||
|
||||
group = SetupGroup::CreateInstance(ID_KNOWNGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN),
|
||||
L"*.ini", &SUID_OmStorageIni, &FUID_SetupKnownGroupFilter,
|
||||
SetupGroup::styleSortAlphabetically);
|
||||
if (NULL != group)
|
||||
{
|
||||
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWNLONG));
|
||||
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN_DESC));
|
||||
group->RequestReload();
|
||||
groupList->AddGroup(group);
|
||||
group->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != groupList)
|
||||
groupList->SetPageWnd(hwnd);
|
||||
|
||||
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
|
||||
if (NULL != hList)
|
||||
{
|
||||
SetupListbox *listbox;
|
||||
if (SUCCEEDED(SetupListbox::CreateInstance(hList, groupList, &listbox)))
|
||||
{
|
||||
}
|
||||
ListboxSelectionChanged();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupPage::DetachWindow()
|
||||
{
|
||||
hwnd = NULL;
|
||||
if (NULL != groupList)
|
||||
{
|
||||
groupList->SetPageWnd(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HRESULT SetupPage_AppendUnselectedServices(LPCSTR pszSection, LPCSTR pszKey, SetupGroup *group)
|
||||
{
|
||||
size_t index = group->GetRecordCount();
|
||||
size_t filterIndex, filterSize;
|
||||
|
||||
ServiceIdList list;
|
||||
Config_ReadServiceIdList(pszSection, pszKey, ',', SetupPage_AppendServiceIdCallback, &list);
|
||||
filterSize = list.size();
|
||||
|
||||
while(index--)
|
||||
{
|
||||
SetupRecord *record = group->GetRecord(index);
|
||||
if (NULL == record || FALSE != record->IsSelected()) continue;
|
||||
|
||||
ifc_omservice *service = record->GetService();
|
||||
if (NULL == service) continue;
|
||||
|
||||
UINT serviceId = service->GetId();
|
||||
for(filterIndex = 0; filterIndex < filterSize; filterIndex++)
|
||||
{
|
||||
if (list[filterIndex] == serviceId)
|
||||
break;
|
||||
}
|
||||
|
||||
if (filterIndex == filterSize)
|
||||
list.push_back(serviceId);
|
||||
}
|
||||
|
||||
if (0 != list.size())
|
||||
{
|
||||
size_t bufferAlloc = (list.size() * 11) * sizeof(CHAR);
|
||||
LPSTR buffer = Plugin_MallocAnsiString(bufferAlloc);
|
||||
if (NULL != buffer)
|
||||
{
|
||||
filterSize = list.size();
|
||||
LPSTR cursor = buffer;
|
||||
size_t remaining = bufferAlloc;
|
||||
for(index = 0; index < filterSize; index++)
|
||||
{
|
||||
if (FAILED(StringCchPrintfExA(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
((0 == index) ? "%u" : ",%u"), list[index])))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Config_WriteStr(pszSection, pszKey, buffer);
|
||||
Plugin_FreeAnsiString(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
Config_WriteStr(pszSection, pszKey, NULL);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::Execute(HWND hwndText)
|
||||
{
|
||||
SetupGroup *group = NULL;
|
||||
SetupLog *log = SetupLog::Open();
|
||||
WCHAR szBuffer[128] = {0};
|
||||
|
||||
if (FAILED(InitializeServices()))
|
||||
return E_FAIL;
|
||||
|
||||
if (NULL == groupList)
|
||||
{
|
||||
groupList = SetupGroupList::CreateInstance();
|
||||
if (NULL == groupList) return E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (S_OK != groupList->FindGroupById(ID_FEATUREDGROUP, &group) && group != NULL)
|
||||
{
|
||||
WCHAR szBuffer[4096] = {0};
|
||||
SetupPage_GetFeaturedServicesUrl(szBuffer, ARRAYSIZE(szBuffer));
|
||||
|
||||
group = SetupGroup::CreateInstance(ID_FEATUREDGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED),
|
||||
szBuffer, &SUID_OmStorageUrl, &FUID_SetupFeaturedGroupFilter,
|
||||
SetupGroup::styleDefaultSubscribed | SetupGroup::styleSaveAll);
|
||||
|
||||
if (NULL != group)
|
||||
{
|
||||
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATUREDLONG));
|
||||
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_FEATURED_DESC));
|
||||
groupList->AddGroup(group);
|
||||
group->RequestReload();
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == completeEvent)
|
||||
completeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
if (NULL != group)
|
||||
{
|
||||
if (SUCCEEDED(group->SignalLoadCompleted(completeEvent)))
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_DOWNLOADSERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
|
||||
SetWindowText(hwndText, szBuffer);
|
||||
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
|
||||
}
|
||||
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SAVESERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
|
||||
SetWindowText(hwndText, szBuffer);
|
||||
group->Save(log);
|
||||
SetupPage_AppendUnselectedServices("Setup", "featuredHistory", group);
|
||||
group->Release();
|
||||
group = NULL;
|
||||
}
|
||||
|
||||
// ensure that promotions are subscribed
|
||||
if (S_OK != groupList->FindGroupById(ID_KNOWNGROUP, &group) && group != NULL)
|
||||
{
|
||||
group = SetupGroup::CreateInstance(ID_KNOWNGROUP, MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN),
|
||||
L"*.ini", &SUID_OmStorageIni, &FUID_SetupKnownGroupFilter,
|
||||
SetupGroup::styleSortAlphabetically);
|
||||
if (NULL != group)
|
||||
{
|
||||
group->SetLongName(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWNLONG));
|
||||
group->SetDescription(MAKEINTRESOURCE(IDS_SERVICEGROUP_KNOWN_DESC));
|
||||
group->RequestReload();
|
||||
groupList->AddGroup(group);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != group)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SAVESERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
|
||||
SetWindowText(hwndText, szBuffer);
|
||||
|
||||
ResetEvent(completeEvent);
|
||||
if (SUCCEEDED(group->SignalLoadCompleted(completeEvent)))
|
||||
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
|
||||
|
||||
group->Save(log);
|
||||
group->Release();
|
||||
group = NULL;
|
||||
}
|
||||
|
||||
if (NULL != log)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_REGISTERINGSERVICE_JOB, szBuffer, ARRAYSIZE(szBuffer));
|
||||
SetWindowText(hwndText, szBuffer);
|
||||
ResetEvent(completeEvent);
|
||||
log->Send(completeEvent);
|
||||
SetupPage_ModalLoop(hwndText, NULL, completeEvent);
|
||||
log->Release();
|
||||
}
|
||||
|
||||
SetupLog::Erase();
|
||||
Config_WriteStr("Setup", "featuredExtra", NULL); // delete promo offer
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::Cancel(HWND hwndText)
|
||||
{
|
||||
if (NULL != completeEvent)
|
||||
SetEvent(completeEvent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetupPage::IsCancelSupported(void)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
void SetupPage::ListboxSelectionChanged()
|
||||
{
|
||||
if (NULL == hwnd) return;
|
||||
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
|
||||
if (NULL == hList) return;
|
||||
|
||||
SetupListboxItem *item = NULL;
|
||||
INT iSelection = (INT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
|
||||
if (LB_ERR == iSelection ||
|
||||
FAILED(groupList->FindListboxItem(iSelection, &item)))
|
||||
{
|
||||
item = NULL;
|
||||
}
|
||||
|
||||
HWND hDiscard = GetDlgItem(hwnd, IDC_DETAILS);
|
||||
if (NULL != hDiscard)
|
||||
{
|
||||
WCHAR szPanel[64] = {0}, szItem[64] = {0};
|
||||
if (FALSE != SetupDetails_GetUniqueName(hDiscard, szPanel, ARRAYSIZE(szPanel)) &&
|
||||
FALSE != item->GetUniqueName(szItem, ARRAYSIZE(szItem)) &&
|
||||
CSTR_EQUAL == CompareString(CSTR_INVARIANT, 0, szPanel, - 1, szItem, -1))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HWND hDetails = (NULL != item) ? item->CreateDetailsView(hwnd) : NULL;
|
||||
if (NULL != hDiscard)
|
||||
{
|
||||
SetWindowLongPtr(hDiscard, GWL_STYLE, GetWindowLongPtr(hDiscard, GWL_STYLE) & ~WS_VISIBLE);
|
||||
}
|
||||
|
||||
if (NULL != hDetails)
|
||||
{
|
||||
HWND hPlaceholder = GetDlgItem(hwnd, IDC_PLACEHOLDER);
|
||||
if (NULL != hPlaceholder)
|
||||
{
|
||||
RECT windowRect;
|
||||
if (GetWindowRect(hPlaceholder, &windowRect))
|
||||
{
|
||||
MapWindowPoints(HWND_DESKTOP,hwnd, (POINT*)&windowRect,2);
|
||||
SetWindowPos(hDetails, NULL, windowRect.left, windowRect.top,
|
||||
windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
|
||||
SWP_NOACTIVATE | SWP_NOZORDER);
|
||||
}
|
||||
SetWindowLongPtr(hDetails, GWLP_ID, IDC_DETAILS);
|
||||
ShowWindow(hDetails, SW_SHOWNA);
|
||||
RedrawWindow(hDetails, NULL, NULL, RDW_ERASENOW |RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != hDiscard)
|
||||
{
|
||||
DestroyWindow(hDiscard);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR SetupPage_ModalLoop(HWND hwnd, HACCEL hAccel, HANDLE hCancel)
|
||||
{
|
||||
MSG msg = {0};
|
||||
HWND hParent = NULL;
|
||||
while (NULL != (hParent = GetAncestor(hwnd, GA_PARENT)))
|
||||
{
|
||||
hwnd = hParent;
|
||||
}
|
||||
|
||||
if (NULL == hwnd)
|
||||
return 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
DWORD status = MsgWaitForMultipleObjectsEx(1, &hCancel, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
|
||||
if (WAIT_OBJECT_0 == status)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if ((WAIT_OBJECT_0 + 1)== status)
|
||||
{
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||
{
|
||||
//if (!CallMsgFilter(&msg, MSGF_DIALOGBOX))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
{
|
||||
PostQuitMessage((INT)msg.wParam);
|
||||
return msg.wParam;
|
||||
}
|
||||
|
||||
if (!TranslateAcceleratorW(hwnd, hAccel, &msg) &&
|
||||
!IsDialogMessageW(hwnd, &msg))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CBCLASS SetupPage
|
||||
START_MULTIPATCH;
|
||||
START_PATCH(MPIID_SETUPPAGE)
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, ADDREF, AddRef);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, RELEASE, Release);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, QUERYINTERFACE, QueryInterface);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_GET_NAME, GetName);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_CREATEVIEW, CreateView);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_SAVE, Save);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_REVERT, Revert);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_ISDIRTY, IsDirty);
|
||||
M_CB(MPIID_SETUPPAGE, ifc_setuppage, API_SETUPPAGE_VALIDATE, Validate);
|
||||
|
||||
NEXT_PATCH(MPIID_SETUPJOB)
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, ADDREF, AddRef);
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, RELEASE, Release);
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, QUERYINTERFACE, QueryInterface);
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_EXECUTE, Execute);
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_CANCEL, Cancel);
|
||||
M_CB(MPIID_SETUPJOB, ifc_setupjob, API_SETUPJOB_ISCANCELSUPPORTED, IsCancelSupported);
|
||||
|
||||
END_PATCH
|
||||
END_MULTIPATCH;
|
||||
#undef CBCLASS
|
85
Src/Plugins/Library/ml_online/Setup/setupPage.h
Normal file
85
Src/Plugins/Library/ml_online/Setup/setupPage.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <bfc/multipatch.h>
|
||||
|
||||
#include "../../winamp/setup/ifc_setuppage.h"
|
||||
#include "../../winamp/setup/ifc_setupjob.h"
|
||||
|
||||
#include "./setupGroupList.h"
|
||||
|
||||
class SetupListboxLabel;
|
||||
|
||||
#define ID_KNOWNGROUP 0
|
||||
#define ID_FEATUREDGROUP 1
|
||||
|
||||
#define MPIID_SETUPPAGE 10
|
||||
#define MPIID_SETUPJOB 20
|
||||
|
||||
#define SPM_FIRST (WM_APP + 2)
|
||||
#define SPM_UPDATELIST (SPM_FIRST + 0)
|
||||
|
||||
class SetupPage : public MultiPatch<MPIID_SETUPPAGE, ifc_setuppage>,
|
||||
public MultiPatch<MPIID_SETUPJOB, ifc_setupjob>
|
||||
{
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
flagInitWasabi = 0x00000001,
|
||||
};
|
||||
|
||||
protected:
|
||||
SetupPage();
|
||||
virtual ~SetupPage();
|
||||
|
||||
public:
|
||||
static SetupPage* CreateInstance();
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_setuppage */
|
||||
HRESULT GetName(bool bShort, const wchar_t **pszName);
|
||||
HRESULT Save(HWND hText);
|
||||
HRESULT CreateView(HWND hParent, HWND *phwnd);
|
||||
HRESULT Revert(void);
|
||||
HRESULT IsDirty(void);
|
||||
HRESULT Validate(void);
|
||||
|
||||
/* ifc_setupjob */
|
||||
HRESULT Execute(HWND hwndText);
|
||||
HRESULT Cancel(HWND hwndText);
|
||||
HRESULT IsCancelSupported(void);
|
||||
|
||||
public:
|
||||
BOOL AttachWindow(HWND hAttach);
|
||||
void DetachWindow();
|
||||
|
||||
void ListboxSelectionChanged();
|
||||
BOOL UpdateListAsync(INT groupId);
|
||||
|
||||
protected:
|
||||
HRESULT InitializeServices();
|
||||
|
||||
private:
|
||||
size_t ref;
|
||||
HWND hwnd;
|
||||
LPWSTR name;
|
||||
LPWSTR title;
|
||||
SetupGroupList *groupList;
|
||||
HANDLE completeEvent;
|
||||
BOOL servicesInitialized;
|
||||
|
||||
protected:
|
||||
RECVS_MULTIPATCH;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPPAGE_HEADER
|
145
Src/Plugins/Library/ml_online/Setup/setupPageWnd.cpp
Normal file
145
Src/Plugins/Library/ml_online/Setup/setupPageWnd.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
#include "./setupPage.h"
|
||||
#include "./setupListbox.h"
|
||||
#include "../common.h"
|
||||
#include "../resource.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
static ATOM SETUPPAGE_PROP = 0;
|
||||
|
||||
#define GetPage(__hwnd) ((SetupPage*)GetPropW((__hwnd), MAKEINTATOM(SETUPPAGE_PROP)))
|
||||
|
||||
static INT_PTR WINAPI SetupPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
|
||||
HWND SetupPage_CreateWindow(HWND hParent, SetupPage *page)
|
||||
{
|
||||
return WASABI_API_CREATEDIALOGPARAMW(IDD_SETUPPAGE, hParent, SetupPage_DialogProc, (LPARAM)page);
|
||||
}
|
||||
|
||||
static INT_PTR SetupPage_OnInitDialog(HWND hwnd, HWND hFocus, LPARAM lParam)
|
||||
{
|
||||
if (0 == SETUPPAGE_PROP)
|
||||
{
|
||||
SETUPPAGE_PROP = GlobalAddAtom(L"omSetupPageProp");
|
||||
if (0 == SETUPPAGE_PROP) return FALSE;
|
||||
}
|
||||
|
||||
SetupPage *page = (SetupPage*)lParam;
|
||||
if (NULL != page && page->AttachWindow(hwnd))
|
||||
{
|
||||
SetProp(hwnd, MAKEINTATOM(SETUPPAGE_PROP), page);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void SetupPage_OnDestroy(HWND hwnd)
|
||||
{
|
||||
SetupPage *page = GetPage(hwnd);
|
||||
if (NULL != page)
|
||||
{
|
||||
page->DetachWindow();
|
||||
}
|
||||
RemoveProp(hwnd, MAKEINTATOM(SETUPPAGE_PROP));
|
||||
}
|
||||
|
||||
static void SetupPage_OnCommand(HWND hwnd, INT controlId, INT eventId, HWND hControl)
|
||||
{
|
||||
SetupPage *page;
|
||||
switch(controlId)
|
||||
{
|
||||
case IDC_SERVICELIST:
|
||||
switch(eventId)
|
||||
{
|
||||
case LBN_SELCHANGE:
|
||||
page = GetPage(hwnd);
|
||||
if (NULL != page)
|
||||
page->ListboxSelectionChanged();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL SetupPage_OnMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *pmis)
|
||||
{
|
||||
SetupListbox *instance;
|
||||
switch(pmis->CtlID)
|
||||
{
|
||||
case IDC_SERVICELIST:
|
||||
instance = SetupListbox::GetInstance(GetDlgItem(hwnd, pmis->CtlID));
|
||||
if (NULL != instance)
|
||||
{
|
||||
return instance->MeasureItem(pmis->itemID, &pmis->itemWidth, &pmis->itemHeight);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL SetupPage_OnDrawItem(HWND hwnd, DRAWITEMSTRUCT *pdis)
|
||||
{
|
||||
SetupListbox *instance;
|
||||
switch(pdis->CtlID)
|
||||
{
|
||||
case IDC_SERVICELIST:
|
||||
instance = SetupListbox::GetInstance(pdis->hwndItem);
|
||||
if (NULL != instance)
|
||||
{
|
||||
return instance->DrawItem(pdis->hDC, &pdis->rcItem, pdis->itemID, pdis->itemState, pdis->itemAction);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR SetupPage_OnCharToItem(HWND hwnd, INT vKey, INT caretPos, HWND hList)
|
||||
{
|
||||
|
||||
if (IDC_SERVICELIST == GetDlgCtrlID(hList))
|
||||
{
|
||||
SetupListbox *instance = SetupListbox::GetInstance(hList);
|
||||
if (NULL != instance)
|
||||
return instance->CharToItem(vKey, caretPos);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static INT_PTR SetupPage_OnKeyToItem(HWND hwnd, INT vKey, INT caretPos, HWND hList)
|
||||
{
|
||||
if (IDC_SERVICELIST == GetDlgCtrlID(hList))
|
||||
{
|
||||
SetupListbox *instance = SetupListbox::GetInstance(hList);
|
||||
if (NULL != instance)
|
||||
return instance->KeyToItem(vKey, caretPos);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
static void SetupPage_OnUpdateList(HWND hwnd, INT groupId)
|
||||
{
|
||||
HWND hList = GetDlgItem(hwnd, IDC_SERVICELIST);
|
||||
if (NULL != hList)
|
||||
{
|
||||
SetupListbox *listbox = SetupListbox::GetInstance(hList);
|
||||
if (NULL != listbox)
|
||||
{
|
||||
listbox->UpdateCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
static INT_PTR WINAPI SetupPage_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return SetupPage_OnInitDialog(hwnd, (HWND)wParam, lParam);
|
||||
case WM_DESTROY: SetupPage_OnDestroy(hwnd); break;
|
||||
case WM_COMMAND: SetupPage_OnCommand(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam); break;
|
||||
case WM_MEASUREITEM: return SetupPage_OnMeasureItem(hwnd, (MEASUREITEMSTRUCT*)lParam);
|
||||
case WM_DRAWITEM: return SetupPage_OnDrawItem(hwnd, (DRAWITEMSTRUCT*)lParam);
|
||||
case WM_CHARTOITEM: return SetupPage_OnCharToItem(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
|
||||
case WM_VKEYTOITEM: return SetupPage_OnKeyToItem(hwnd, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
|
||||
case SPM_UPDATELIST: SetupPage_OnUpdateList(hwnd, (INT)wParam); return TRUE;
|
||||
}
|
||||
return 0;
|
||||
}
|
567
Src/Plugins/Library/ml_online/Setup/setupRecord.cpp
Normal file
567
Src/Plugins/Library/ml_online/Setup/setupRecord.cpp
Normal file
|
@ -0,0 +1,567 @@
|
|||
#include "./main.h"
|
||||
#include "../api__ml_online.h"
|
||||
#include "./setupRecord.h"
|
||||
#include "./setupDetails.h"
|
||||
#include "./setupLog.h"
|
||||
#include "../resource.h"
|
||||
|
||||
#include "./serviceHelper.h"
|
||||
#include "./serviceHost.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omwebstorage.h>
|
||||
#include <ifc_omserviceenum.h>
|
||||
#include <ifc_omservicecopier.h>
|
||||
|
||||
#include <wininet.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define RECORD_MARGINCX 6
|
||||
#define RECORD_MARGINCY 2
|
||||
#define CHECKBOX_MARGIN_RIGHT 2
|
||||
|
||||
#define TEXT_OFFSET_LEFT 3
|
||||
#define TEXT_OFFSET_BOTTOM RECORD_MARGINCY
|
||||
#define TEXT_ALIGN (TA_LEFT | TA_BOTTOM)
|
||||
|
||||
SetupRecord::SetupRecord(ifc_omservice *serviceToUse)
|
||||
: ref(1), service(serviceToUse), flags(0), async(NULL)
|
||||
{
|
||||
if (NULL != service)
|
||||
{
|
||||
if (S_OK == ServiceHelper_IsSubscribed(service))
|
||||
flags |= recordSelected;
|
||||
service->AddRef();
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&lock);
|
||||
}
|
||||
|
||||
SetupRecord::~SetupRecord()
|
||||
{
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
if (NULL != async)
|
||||
{
|
||||
ifc_omstorage *storage = NULL;
|
||||
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
|
||||
if (SUCCEEDED(hr) && storage != NULL)
|
||||
{
|
||||
storage->RequestAbort(async, TRUE);
|
||||
}
|
||||
|
||||
async->Release();
|
||||
async = NULL;
|
||||
}
|
||||
|
||||
if (NULL != service)
|
||||
service->Release();
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
DeleteCriticalSection(&lock);
|
||||
}
|
||||
|
||||
SetupRecord *SetupRecord::CreateInstance(ifc_omservice *serviceToUse)
|
||||
{
|
||||
if (NULL == serviceToUse) return NULL;
|
||||
return new SetupRecord(serviceToUse);
|
||||
}
|
||||
|
||||
ULONG SetupRecord::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
ULONG SetupRecord::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
HRESULT SetupRecord::GetServiceName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == service) return E_UNEXPECTED;
|
||||
return service->GetName(pszBuffer, cchBufferMax);
|
||||
}
|
||||
|
||||
HRESULT SetupRecord::GetDisplayName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
HRESULT hr = GetServiceName(pszBuffer, cchBufferMax);
|
||||
if (SUCCEEDED(hr) && L'\0' == *pszBuffer)
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_DEFAULT_SERVICENAME, pszBuffer, cchBufferMax);
|
||||
DownloadDetails();
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupRecord::DownloadDetails()
|
||||
{
|
||||
HRESULT hr;
|
||||
EnterCriticalSection(&lock);
|
||||
if (NULL == async && 0 == (recordDownloaded & flags))
|
||||
{
|
||||
WCHAR szUrl[INTERNET_MAX_URL_LENGTH] = {0};
|
||||
hr = ServiceHelper_GetDetailsUrl(szUrl, ARRAYSIZE(szUrl), service, FALSE);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ifc_omstorage *storage = NULL;
|
||||
hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
|
||||
if (SUCCEEDED(hr) && storage != NULL)
|
||||
{
|
||||
ServiceHost *serviceHost = NULL;
|
||||
if (FAILED(ServiceHost::GetCachedInstance(&serviceHost)))
|
||||
serviceHost = NULL;
|
||||
|
||||
hr = storage->BeginLoad(szUrl, serviceHost, SetupRecord_ServiceDownloadedCallback, this, &async);
|
||||
storage->Release();
|
||||
|
||||
if (NULL != serviceHost)
|
||||
serviceHost->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = S_FALSE;
|
||||
}
|
||||
LeaveCriticalSection(&lock);
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SetupRecord::Save(SetupLog *log)
|
||||
{
|
||||
if (NULL == service) return E_POINTER;
|
||||
|
||||
HRESULT hr = ServiceHelper_Subscribe(service, IsSelected(), SHF_SAVE);
|
||||
if (S_OK == hr)
|
||||
{
|
||||
if (NULL != log)
|
||||
{
|
||||
INT operation = (IsSelected()) ? SetupLog::opServiceAdded : SetupLog::opServiceRemoved;
|
||||
log->LogService(service, operation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::IsModified()
|
||||
{
|
||||
if (NULL == service)
|
||||
return FALSE;
|
||||
|
||||
if (S_OK == ServiceHelper_IsSubscribed(service) != (FALSE != IsSelected()))
|
||||
return TRUE;
|
||||
if (S_OK == ServiceHelper_IsModified(service))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::IsSelected()
|
||||
{
|
||||
return (0 != (recordSelected & flags));
|
||||
}
|
||||
|
||||
void SetupRecord::SetSelected(BOOL fSelected)
|
||||
{
|
||||
if ((FALSE == fSelected) == !IsSelected())
|
||||
return;
|
||||
|
||||
if (FALSE == fSelected)
|
||||
flags &= ~recordSelected;
|
||||
else
|
||||
flags |= recordSelected;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::AdjustCheckboxRect(SetupListbox *instance, RECT *prcItem)
|
||||
{
|
||||
SIZE checkSize;
|
||||
if (!instance->GetCheckboxMetrics(NULL, IsSelected(), 0, &checkSize))
|
||||
return FALSE;
|
||||
|
||||
prcItem->left += RECORD_MARGINCX;
|
||||
prcItem->right = prcItem->left + checkSize.cx;
|
||||
|
||||
if (checkSize.cy > (prcItem->bottom - prcItem->top))
|
||||
checkSize.cy = (prcItem->bottom - prcItem->top);
|
||||
prcItem->top += ((prcItem->bottom - prcItem->top) - checkSize.cy) / 2;
|
||||
prcItem->bottom = prcItem->top + checkSize.cy;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy)
|
||||
{
|
||||
HDC hdc = GetDCEx(instance->GetHwnd(), NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL == hdc) return FALSE;
|
||||
|
||||
HFONT originalFont = (HFONT)SelectObject(hdc, instance->GetFont());
|
||||
|
||||
SIZE checkSize;
|
||||
instance->GetCheckboxMetrics(hdc, IsSelected(), 0, &checkSize);
|
||||
|
||||
if (NULL != cy)
|
||||
{
|
||||
*cy = 0;
|
||||
TEXTMETRIC tm = {0};
|
||||
if (GetTextMetrics(hdc, &tm))
|
||||
{
|
||||
*cy = tm.tmHeight + tm.tmExternalLeading;
|
||||
if (checkSize.cy > (INT)*cy) *cy = checkSize.cy;
|
||||
*cy += RECORD_MARGINCY*2;
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL != cx)
|
||||
{
|
||||
*cx = checkSize.cx;
|
||||
WCHAR szBuffer[128] = {0};
|
||||
if (SUCCEEDED(GetDisplayName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
INT cchBuffer = lstrlenW(szBuffer);
|
||||
SIZE textSize;
|
||||
if (0 != cchBuffer && GetTextExtentPoint32(hdc, szBuffer, cchBuffer, &textSize))
|
||||
{
|
||||
*cx += textSize.cx;
|
||||
if (0 != checkSize.cx)
|
||||
*cx += CHECKBOX_MARGIN_RIGHT + RECORD_MARGINCX;
|
||||
}
|
||||
}
|
||||
if (0 != *cx) *cx += RECORD_MARGINCX*2;
|
||||
}
|
||||
|
||||
SelectObject(hdc, originalFont);
|
||||
ReleaseDC(instance->GetHwnd(), hdc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupRecord::GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut)
|
||||
{
|
||||
COLORREF rgbBk, rgbText;
|
||||
|
||||
if (0 != (ODS_DISABLED & state))
|
||||
{
|
||||
rgbBk = GetBkColor(hdc);
|
||||
rgbText = GetSysColor(COLOR_GRAYTEXT);
|
||||
}
|
||||
else if (0 != (ODS_SELECTED & state))
|
||||
{
|
||||
if (0 == (ODS_INACTIVE & state))
|
||||
{
|
||||
rgbBk = GetSysColor(COLOR_HIGHLIGHT);
|
||||
rgbText = GetSysColor(COLOR_HIGHLIGHTTEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
rgbBk = GetSysColor(COLOR_3DFACE);
|
||||
rgbText = GetTextColor(hdc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rgbBk = GetBkColor(hdc);
|
||||
rgbText = GetTextColor(hdc);
|
||||
}
|
||||
|
||||
if (NULL != rgbBkOut) *rgbBkOut = rgbBk;
|
||||
if (NULL != rgbTextOut) *rgbTextOut = rgbText;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state)
|
||||
{
|
||||
LONG paintLeft = prc->left + RECORD_MARGINCX;
|
||||
RECT partRect;
|
||||
|
||||
UINT checkState = state & ~ODS_SELECTED;
|
||||
if (0 == (checkboxPressed & flags))
|
||||
{
|
||||
if (0 != (checkboxHighlighted & flags))
|
||||
checkState |= ODS_HOTLIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkState |= ((0 != (checkboxHighlighted & flags)) ? ODS_SELECTED : ODS_HOTLIGHT);
|
||||
}
|
||||
|
||||
HRGN backRgn, rgn;
|
||||
backRgn = CreateRectRgnIndirect(prc);
|
||||
rgn = CreateRectRgn(0,0,0,0);
|
||||
|
||||
SetRectEmpty(&partRect);
|
||||
instance->GetCheckboxMetrics(hdc, IsSelected(), checkState, (((SIZE*)&partRect) + 1));
|
||||
|
||||
INT space = (prc->bottom - prc->top) - (partRect.bottom- partRect.top);
|
||||
INT offsetY = space / 2 + space%2;
|
||||
if (offsetY < 0) offsetY = 0;
|
||||
|
||||
OffsetRect(&partRect, paintLeft, prc->top + offsetY);
|
||||
if (instance->DrawCheckbox(hdc, IsSelected(), checkState, &partRect, prc))
|
||||
{
|
||||
paintLeft = partRect.right + CHECKBOX_MARGIN_RIGHT;
|
||||
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
|
||||
}
|
||||
|
||||
COLORREF rgbBk, rgbText;
|
||||
GetColors(hdc, state, &rgbBk, &rgbText);
|
||||
|
||||
COLORREF origBk = SetBkColor(hdc, rgbBk);
|
||||
COLORREF origText = SetTextColor(hdc, rgbText);
|
||||
UINT textAlign = SetTextAlign(hdc, TEXT_ALIGN);
|
||||
|
||||
WCHAR szBuffer[128] = {0};
|
||||
INT cchBuffer = 0;
|
||||
if (SUCCEEDED(GetDisplayName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
cchBuffer = lstrlenW(szBuffer);
|
||||
|
||||
SetRect(&partRect, paintLeft, prc->top, prc->right, prc->bottom);
|
||||
if (ExtTextOut(hdc, partRect.left + TEXT_OFFSET_LEFT, partRect.bottom - TEXT_OFFSET_BOTTOM,
|
||||
ETO_OPAQUE | ETO_CLIPPED, &partRect, szBuffer, cchBuffer, NULL))
|
||||
{
|
||||
if (SetRectRgn(rgn, partRect.left, partRect.top, partRect.right, partRect.bottom))
|
||||
CombineRgn(backRgn, backRgn, rgn, RGN_DIFF);
|
||||
}
|
||||
|
||||
if (ODS_FOCUS == ((ODS_FOCUS | 0x0200/*ODS_NOFOCUSRECT*/) & state))
|
||||
DrawFocusRect(hdc, &partRect);
|
||||
|
||||
if (NULL != backRgn)
|
||||
{
|
||||
PaintRgn(hdc, backRgn);
|
||||
DeleteObject(backRgn);
|
||||
}
|
||||
if (NULL != rgn)
|
||||
DeleteObject(rgn);
|
||||
|
||||
if (TEXT_ALIGN != textAlign) SetTextAlign(hdc, textAlign);
|
||||
if (origBk != rgbBk) SetBkColor(hdc, origBk);
|
||||
if (origText != rgbText) SetTextColor(hdc, origText);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
INT_PTR SetupRecord::KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey)
|
||||
{
|
||||
switch(vKey)
|
||||
{
|
||||
case VK_SPACE:
|
||||
InvertCheckbox(instance, prcItem);
|
||||
return -2;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
RECT checkboxRect;
|
||||
BOOL fInvalidate = FALSE;
|
||||
CopyRect(&checkboxRect, prcItem);
|
||||
AdjustCheckboxRect(instance, &checkboxRect);
|
||||
|
||||
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
|
||||
checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
|
||||
{
|
||||
if (0 == (checkboxHighlighted & flags))
|
||||
{
|
||||
flags |= checkboxHighlighted;
|
||||
fInvalidate = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != (checkboxHighlighted & flags))
|
||||
{
|
||||
flags &= ~checkboxHighlighted;
|
||||
fInvalidate = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (FALSE != fInvalidate)
|
||||
instance->InvalidateRect(&checkboxRect, FALSE);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::MouseLeave(SetupListbox *instance, const RECT *prcItem)
|
||||
{
|
||||
if (0 != (checkboxHighlighted & flags))
|
||||
{
|
||||
flags &= ~checkboxHighlighted;
|
||||
RECT checkboxRect;
|
||||
CopyRect(&checkboxRect, prcItem);
|
||||
AdjustCheckboxRect(instance, &checkboxRect);
|
||||
instance->InvalidateRect(&checkboxRect, FALSE);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
RECT checkboxRect;
|
||||
BOOL handled = FALSE;
|
||||
CopyRect(&checkboxRect, prcItem);
|
||||
AdjustCheckboxRect(instance, &checkboxRect);
|
||||
|
||||
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
|
||||
prcItem->left <= pt.x && pt.x < (checkboxRect.right + CHECKBOX_MARGIN_RIGHT))
|
||||
{
|
||||
handled = TRUE;
|
||||
if (checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
|
||||
{
|
||||
flags |= (checkboxHighlighted | checkboxPressed);
|
||||
instance->SetCapture(this);
|
||||
instance->InvalidateRect(&checkboxRect, FALSE);
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
RECT checkboxRect;
|
||||
BOOL handled = FALSE;
|
||||
CopyRect(&checkboxRect, prcItem);
|
||||
AdjustCheckboxRect(instance, &checkboxRect);
|
||||
|
||||
if (0 != (checkboxPressed & flags))
|
||||
{
|
||||
flags &= ~checkboxPressed;
|
||||
if (this == instance->GetCapture())
|
||||
instance->ReleaseCapture();
|
||||
|
||||
if (prcItem->top <= pt.y && pt.y < prcItem->bottom &&
|
||||
checkboxRect.left <= pt.x && pt.x < checkboxRect.right)
|
||||
{
|
||||
SetSelected(!IsSelected());
|
||||
handled = TRUE;
|
||||
}
|
||||
instance->InvalidateRect(&checkboxRect, FALSE);
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
InvertCheckbox(instance, prcItem);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL SetupRecord::RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SetupRecord::CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured)
|
||||
{
|
||||
}
|
||||
|
||||
void SetupRecord::InvertCheckbox(SetupListbox *instance, const RECT *prcItem)
|
||||
{
|
||||
SetSelected(!IsSelected());
|
||||
|
||||
if (NULL != instance && NULL != prcItem)
|
||||
{
|
||||
RECT checkboxRect;
|
||||
CopyRect(&checkboxRect, prcItem);
|
||||
AdjustCheckboxRect(instance, &checkboxRect);
|
||||
instance->InvalidateRect(&checkboxRect, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
HWND SetupRecord::CreateDetailsView(HWND hParent)
|
||||
{
|
||||
DownloadDetails();
|
||||
|
||||
WCHAR szName[64] = {0};
|
||||
if (FALSE == GetUniqueName(szName, ARRAYSIZE(szName)))
|
||||
szName[0] = L'\0';
|
||||
|
||||
return SetupDetails_CreateServiceView(hParent, szName, service);
|
||||
}
|
||||
|
||||
BOOL SetupRecord::GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer ||
|
||||
FAILED(StringCchPrintf(pszBuffer, cchBufferMax, L"record_svc_%u", service->GetId())))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void SetupRecord::OnDownloadCompleted()
|
||||
{
|
||||
ifc_omstorage *storage = NULL;
|
||||
HRESULT hr = OMSERVICEMNGR->QueryStorage(&SUID_OmStorageUrl, &storage);
|
||||
if (SUCCEEDED(hr) && service != NULL)
|
||||
{
|
||||
ifc_omserviceenum *serviceEnum = NULL;
|
||||
hr = storage->EndLoad(async, &serviceEnum);
|
||||
if (SUCCEEDED(hr) && serviceEnum != NULL)
|
||||
{
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
ifc_omservice *result = NULL;
|
||||
while(S_OK == serviceEnum->Next(1, &result, NULL))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
if (result->GetId() == service->GetId())
|
||||
{
|
||||
ifc_omservicecopier *copier;
|
||||
if (SUCCEEDED(result->QueryInterface(IFC_OmServiceCopier, (void**)&copier)))
|
||||
{
|
||||
copier->CopyTo(service, NULL);
|
||||
copier->Release();
|
||||
}
|
||||
result->Release();
|
||||
flags |= recordDownloaded;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
result->Release();
|
||||
}
|
||||
}
|
||||
result = NULL;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
|
||||
serviceEnum->Release();
|
||||
}
|
||||
|
||||
storage->Release();
|
||||
}
|
||||
|
||||
EnterCriticalSection(&lock);
|
||||
|
||||
async->Release();
|
||||
async = NULL;
|
||||
|
||||
LeaveCriticalSection(&lock);
|
||||
}
|
||||
|
||||
void CALLBACK SetupRecord_ServiceDownloadedCallback(ifc_omstorageasync *result)
|
||||
{
|
||||
if (NULL == result) return;
|
||||
SetupRecord *record = NULL;
|
||||
if (SUCCEEDED(result->GetData((void**)&record)) && NULL != record)
|
||||
{
|
||||
record->OnDownloadCompleted();
|
||||
}
|
||||
}
|
84
Src/Plugins/Library/ml_online/Setup/setupRecord.h
Normal file
84
Src/Plugins/Library/ml_online/Setup/setupRecord.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include "./setupListbox.h"
|
||||
|
||||
class ifc_omservice;
|
||||
class ifc_omstorageasync;
|
||||
class SetupLog;
|
||||
|
||||
class SetupRecord : public SetupListboxItem
|
||||
|
||||
{
|
||||
protected:
|
||||
typedef enum
|
||||
{
|
||||
recordSelected = 0x0001,
|
||||
recordDownloaded = 0x0002,
|
||||
checkboxHighlighted = 0x0100,
|
||||
checkboxPressed = 0x0200,
|
||||
} RecordFlags;
|
||||
|
||||
protected:
|
||||
SetupRecord(ifc_omservice *serviceToUse);
|
||||
~SetupRecord();
|
||||
|
||||
public:
|
||||
static SetupRecord *CreateInstance(ifc_omservice *serviceToUse);
|
||||
|
||||
public:
|
||||
ULONG AddRef();
|
||||
ULONG Release();
|
||||
|
||||
ifc_omservice *GetService() { return service; }
|
||||
|
||||
BOOL IsModified();
|
||||
BOOL IsSelected();
|
||||
void SetSelected(BOOL fSelected);
|
||||
|
||||
HRESULT GetServiceName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
HRESULT GetDisplayName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
HRESULT Save(SetupLog *log);
|
||||
HRESULT DownloadDetails();
|
||||
|
||||
/* SetupListboxItem */
|
||||
BOOL MeasureItem(SetupListbox *instance, UINT *cx, UINT *cy);
|
||||
BOOL DrawItem(SetupListbox *instance, HDC hdc, const RECT *prc, UINT state);
|
||||
INT_PTR KeyToItem(SetupListbox *instance, const RECT *prcItem, INT vKey);
|
||||
BOOL MouseMove(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL MouseLeave(SetupListbox *instance, const RECT *prcItem);
|
||||
BOOL LButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL LButtonDblClk(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonDown(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
BOOL RButtonUp(SetupListbox *instance, const RECT *prcItem, UINT mouseFlags, POINT pt);
|
||||
void CaptureChanged(SetupListbox *instance, const RECT *prcItem, SetupListboxItem *captured);
|
||||
BOOL IsDisabled() { return FALSE; }
|
||||
void Command(SetupListbox *instance, INT commandId, INT eventId) {}
|
||||
HWND CreateDetailsView(HWND hParent);
|
||||
BOOL GetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
|
||||
|
||||
protected:
|
||||
BOOL AdjustCheckboxRect(SetupListbox *instance, RECT *prcItem);
|
||||
void GetColors(HDC hdc, UINT state, COLORREF *rgbBkOut, COLORREF *rgbTextOut);
|
||||
void InvertCheckbox(SetupListbox *instance, const RECT *prcItem);
|
||||
void OnDownloadCompleted();
|
||||
|
||||
private:
|
||||
friend static void CALLBACK SetupRecord_ServiceDownloadedCallback(ifc_omstorageasync *result);
|
||||
|
||||
protected:
|
||||
ULONG ref;
|
||||
ifc_omservice *service;
|
||||
ifc_omstorageasync *async;
|
||||
CRITICAL_SECTION lock;
|
||||
UINT flags;
|
||||
};
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUPRECORD_HEADER
|
797
Src/Plugins/Library/ml_online/Setup/setupServicePanel.cpp
Normal file
797
Src/Plugins/Library/ml_online/Setup/setupServicePanel.cpp
Normal file
|
@ -0,0 +1,797 @@
|
|||
#include "../common.h"
|
||||
#include "./setupServicePanel.h"
|
||||
#include "./setupDetails.h"
|
||||
#include "./setupPage.h"
|
||||
#include "../resource.h"
|
||||
#include "../api__ml_online.h"
|
||||
|
||||
#include <ifc_omservice.h>
|
||||
#include <ifc_omservicedetails.h>
|
||||
#include <ifc_omcachemanager.h>
|
||||
#include <ifc_omcachegroup.h>
|
||||
#include <ifc_omcacherecord.h>
|
||||
#include <ifc_imageloader.h>
|
||||
#include <ifc_omgraphics.h>
|
||||
#include <ifc_omserviceeventmngr.h>
|
||||
#include <ifc_omserviceeditor.h>
|
||||
|
||||
#include <shlwapi.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define GetPanel(__hwnd) ((ServicePanel*)GetPropW((__hwnd), MAKEINTATOM(DETAILS_PROP)))
|
||||
|
||||
#define GET_IDETAILS(__service, __details)\
|
||||
(NULL != (service) && SUCCEEDED((service)->QueryInterface(IFC_OmServiceDetails, (void**)&(__details))))
|
||||
|
||||
|
||||
ServicePanel::ServicePanel(LPCWSTR pszName, ifc_omservice *service)
|
||||
: ref(1), name(NULL), service(NULL), hwnd(NULL), fontTitle(NULL), fontMeta(NULL), thumbnailCache(NULL)
|
||||
{
|
||||
name = Plugin_CopyString(pszName);
|
||||
this->service = service;
|
||||
if (NULL != service)
|
||||
service->AddRef();
|
||||
}
|
||||
|
||||
ServicePanel::~ServicePanel()
|
||||
{
|
||||
Plugin_FreeString(name);
|
||||
|
||||
if (NULL != service)
|
||||
service->Release();
|
||||
|
||||
if (NULL != fontTitle)
|
||||
DeleteObject(fontTitle);
|
||||
|
||||
if (NULL != fontMeta)
|
||||
DeleteObject(fontMeta);
|
||||
|
||||
if (NULL != thumbnailCache)
|
||||
thumbnailCache->Release();
|
||||
}
|
||||
|
||||
HWND ServicePanel::CreateInstance(HWND hParent, LPCWSTR pszName, ifc_omservice *service, ServicePanel **instance)
|
||||
{
|
||||
ServicePanel *panel = new ServicePanel(pszName, service);
|
||||
if (NULL == panel)
|
||||
{
|
||||
if (NULL != instance) *instance = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HWND hwnd = WASABI_API_CREATEDIALOGPARAMW(IDD_SETUP_SERVICEDETAILS, hParent, ServicePanel_DialogProc, (LPARAM)panel);
|
||||
|
||||
if (NULL != instance)
|
||||
{
|
||||
if (NULL != hwnd)
|
||||
{
|
||||
*instance = panel;
|
||||
panel->AddRef();
|
||||
}
|
||||
else
|
||||
*instance = NULL;
|
||||
}
|
||||
|
||||
panel->Release();
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
size_t ServicePanel::AddRef()
|
||||
{
|
||||
return InterlockedIncrement((LONG*)&ref);
|
||||
}
|
||||
|
||||
size_t ServicePanel::Release()
|
||||
{
|
||||
if (0 == ref)
|
||||
return ref;
|
||||
|
||||
LONG r = InterlockedDecrement((LONG*)&ref);
|
||||
if (0 == r)
|
||||
delete(this);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ServicePanel::QueryInterface(GUID interface_guid, void **object)
|
||||
{
|
||||
if (NULL == object) return E_POINTER;
|
||||
|
||||
if (IsEqualIID(interface_guid, IFC_OmServiceEvent))
|
||||
*object = static_cast<ifc_omserviceevent*>(this);
|
||||
else
|
||||
{
|
||||
*object = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
if (NULL == *object)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void CALLBACK ThreadCallback_ServiceChange(Dispatchable *instance, ULONG_PTR param1, ULONG_PTR param2)
|
||||
{
|
||||
ifc_omserviceevent *panel = (ifc_omserviceevent*)instance;
|
||||
ifc_omservice *service = (ifc_omservice*)param1;
|
||||
if (NULL != service)
|
||||
{
|
||||
if (NULL != panel)
|
||||
panel->ServiceChange(service, (UINT)param2);
|
||||
service->Release();
|
||||
}
|
||||
}
|
||||
void ServicePanel::ServiceChange(ifc_omservice *service, unsigned int modifiedFlags)
|
||||
{
|
||||
|
||||
DWORD currentTID = GetCurrentThreadId();
|
||||
DWORD windowTID = GetWindowThreadProcessId(hwnd, NULL);
|
||||
if (NULL != windowTID && currentTID != windowTID)
|
||||
{
|
||||
if(NULL != OMUTILITY)
|
||||
{
|
||||
service->AddRef();
|
||||
if (FAILED(OMUTILITY->PostMainThreadCallback2(ThreadCallback_ServiceChange, (ifc_omserviceevent*)this, (ULONG_PTR)service, (ULONG_PTR)modifiedFlags)))
|
||||
service->Release();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ( 0 != (ifc_omserviceeditor::modifiedName & modifiedFlags))
|
||||
{
|
||||
UpdateName();
|
||||
HWND hPage = GetParent(hwnd);
|
||||
if (NULL != hPage)
|
||||
PostMessage(hPage, SPM_UPDATELIST, (WPARAM)service->GetId(), NULL);
|
||||
}
|
||||
|
||||
if ( 0 != (ifc_omserviceeditor::modifiedDescription & modifiedFlags))
|
||||
UpdateDescription();
|
||||
|
||||
if ( 0 != (ifc_omserviceeditor::modifiedThumbnail& modifiedFlags))
|
||||
UpdateThumbnail();
|
||||
|
||||
if ( 0 != ((ifc_omserviceeditor::modifiedAuthorFirst |
|
||||
ifc_omserviceeditor::modifiedAuthorLast |
|
||||
ifc_omserviceeditor::modifiedUpdated |
|
||||
ifc_omserviceeditor::modifiedPublished) & modifiedFlags))
|
||||
{
|
||||
UpdateMeta();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HRESULT ServicePanel::LoadLocalThumbnail(LPCWSTR pszPath)
|
||||
{
|
||||
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
|
||||
if (NULL == hThumbnail) return E_UNEXPECTED;
|
||||
|
||||
SendMessage(hThumbnail, WM_SETREDRAW, FALSE, 0L);
|
||||
|
||||
HBITMAP hBitmap = NULL;
|
||||
|
||||
BITMAPINFOHEADER header;
|
||||
void *pixelData;
|
||||
|
||||
ifc_omimageloader *imageLoader;
|
||||
if (SUCCEEDED(OMUTILITY->QueryImageLoader(NULL, pszPath, FALSE, &imageLoader)))
|
||||
{
|
||||
imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData);
|
||||
imageLoader->Release();
|
||||
}
|
||||
|
||||
if (NULL == hBitmap &&
|
||||
SUCCEEDED(OMUTILITY->QueryImageLoader(WASABI_API_ORIG_HINST, MAKEINTRESOURCE(IDR_SERVICE64X64_IMAGE), FALSE, &imageLoader)))
|
||||
{
|
||||
imageLoader->LoadBitmapEx(&hBitmap, &header, &pixelData);
|
||||
imageLoader->Release();
|
||||
}
|
||||
|
||||
HBITMAP hTest = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
|
||||
if (NULL != hTest)
|
||||
DeleteObject(hTest);
|
||||
|
||||
if (NULL != hBitmap)
|
||||
{
|
||||
hTest = (HBITMAP)SendMessage(hThumbnail, STM_GETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if (hTest != hBitmap)
|
||||
{ // this is XP and up image copy was created and alpha channel will be handled properly
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
else
|
||||
{ // fix alpha channel
|
||||
if (32 == header.biBitCount)
|
||||
{
|
||||
HDC hdcFixed = CreateCompatibleDC(NULL);
|
||||
if (NULL != hdcFixed)
|
||||
{
|
||||
BITMAPINFOHEADER headerFixed;
|
||||
CopyMemory(&headerFixed, &header, sizeof(BITMAPINFOHEADER));
|
||||
BYTE *pixelsFixed;
|
||||
INT cx = header.biWidth;
|
||||
INT cy = abs(header.biHeight);
|
||||
HBITMAP bitmapFixed = CreateDIBSection(NULL, (LPBITMAPINFO)&headerFixed, DIB_RGB_COLORS, (void**)&pixelsFixed, NULL, 0);
|
||||
|
||||
if (NULL != bitmapFixed)
|
||||
{
|
||||
HBITMAP bitmapOrig = (HBITMAP)SelectObject(hdcFixed, bitmapFixed);
|
||||
HBRUSH hb = (HBRUSH)SendMessage(hwnd, WM_CTLCOLORDLG, (WPARAM)hdcFixed, (LPARAM)hwnd);
|
||||
if (NULL == hb)
|
||||
hb = GetSysColorBrush(COLOR_3DFACE);
|
||||
RECT rect;
|
||||
SetRect(&rect, 0, 0, cx, cy);
|
||||
FillRect(hdcFixed, &rect, hb);
|
||||
|
||||
ifc_omgraphics *graphics;
|
||||
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
|
||||
{
|
||||
HDC hdcSrc = CreateCompatibleDC(NULL);
|
||||
if (NULL != hdcSrc)
|
||||
{
|
||||
HBITMAP bitmapSrcOrig = (HBITMAP)SelectObject(hdcSrc, hBitmap);
|
||||
BLENDFUNCTION bf;
|
||||
bf.BlendOp = AC_SRC_OVER;
|
||||
bf.BlendFlags = 0;
|
||||
bf.SourceConstantAlpha = 0xFF;
|
||||
bf.AlphaFormat = AC_SRC_ALPHA;
|
||||
|
||||
RECT blendRect;
|
||||
SetRect(&blendRect, 0, 0, cx, cy);
|
||||
|
||||
graphics->Premultiply((BYTE*)pixelData, cx, cy);
|
||||
graphics->AlphaBlend(hdcFixed, &blendRect, hdcSrc, &blendRect, bf);
|
||||
|
||||
SelectObject(hdcSrc, bitmapSrcOrig);
|
||||
DeleteDC(hdcSrc);
|
||||
}
|
||||
graphics->Release();
|
||||
}
|
||||
|
||||
SelectObject(hdcFixed, bitmapOrig);
|
||||
SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)bitmapFixed);
|
||||
DeleteObject(hBitmap);
|
||||
|
||||
}
|
||||
DeleteDC(hdcFixed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RECT clientRect;
|
||||
if (GetClientRect(hThumbnail, &clientRect))
|
||||
{
|
||||
INT cx = clientRect.right - clientRect.left;
|
||||
INT cy = clientRect.bottom - clientRect.top;
|
||||
if (64 != cx || 64 != cy)
|
||||
{
|
||||
SetWindowPos(hThumbnail, NULL, 0, 0, 64, 64, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER);
|
||||
}
|
||||
}
|
||||
|
||||
SendMessage(hThumbnail, WM_SETREDRAW, TRUE, 0L);
|
||||
|
||||
if (0 != ShowWindow(hThumbnail, (NULL != hBitmap) ? SW_SHOWNA : SW_HIDE))
|
||||
InvalidateRect(hThumbnail, NULL, TRUE);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void CALLBACK ThreadCallback_PathChanged(Dispatchable *instance, ULONG_PTR param1, ULONG_PTR param2)
|
||||
{
|
||||
ifc_omcachecallback *panel = (ifc_omcachecallback*)instance;
|
||||
ifc_omcacherecord *record = (ifc_omcacherecord*)param1;
|
||||
if (NULL != record)
|
||||
{
|
||||
if (NULL != panel)
|
||||
panel->PathChanged(record);
|
||||
record->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void ServicePanel::PathChanged(ifc_omcacherecord *record)
|
||||
{
|
||||
if (NULL == hwnd || FALSE == IsWindow(hwnd))
|
||||
return;
|
||||
|
||||
DWORD currentTID = GetCurrentThreadId();
|
||||
DWORD windowTID = GetWindowThreadProcessId(hwnd, NULL);
|
||||
if (NULL != windowTID && currentTID != windowTID)
|
||||
{
|
||||
if(NULL != OMUTILITY)
|
||||
{
|
||||
record->AddRef();
|
||||
if (FAILED(OMUTILITY->PostMainThreadCallback2(ThreadCallback_PathChanged, (ifc_omcachecallback*)this, (ULONG_PTR)record, 0L)))
|
||||
record->Release();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
WCHAR szPath[2048] = {0};
|
||||
if (FAILED(record->GetPath(szPath, ARRAYSIZE(szPath))))
|
||||
szPath[0] = L'\0';
|
||||
|
||||
LoadLocalThumbnail(szPath);
|
||||
}
|
||||
|
||||
void ServicePanel::Attach(HWND hwnd)
|
||||
{
|
||||
this->hwnd = hwnd;
|
||||
if (NULL != hwnd &&
|
||||
FALSE != SetProp(hwnd, MAKEINTATOM(DETAILS_PROP), this))
|
||||
{
|
||||
AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
void ServicePanel::Detach()
|
||||
{
|
||||
RemoveProp(hwnd, MAKEINTATOM(DETAILS_PROP));
|
||||
|
||||
if (NULL != thumbnailCache)
|
||||
{
|
||||
thumbnailCache->UnregisterCallback(this);
|
||||
thumbnailCache->Release();
|
||||
thumbnailCache = NULL;
|
||||
}
|
||||
|
||||
if (NULL != service)
|
||||
{
|
||||
ifc_omserviceeventmngr *eventManager;
|
||||
if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
|
||||
{
|
||||
eventManager->UnregisterHandler(this);
|
||||
eventManager->Release();
|
||||
}
|
||||
}
|
||||
|
||||
Release();
|
||||
}
|
||||
|
||||
HFONT ServicePanel::PickTitleFont(LPCWSTR pszTitle, INT cchTitle, INT maxWidth)
|
||||
{
|
||||
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||||
|
||||
LOGFONT lf;
|
||||
if (0 == GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
return NULL;
|
||||
|
||||
HFONT titleFont = NULL;
|
||||
if (cchTitle > 0)
|
||||
{
|
||||
LOGFONT lf;
|
||||
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Arial Bold");
|
||||
lf.lfWidth = 0;
|
||||
lf.lfWeight = FW_DONTCARE;
|
||||
lf.lfQuality = 5/*ANTIALIASED_QUALITY*/;
|
||||
|
||||
HDC hdc = GetDCEx(hwnd, NULL, DCX_CACHE | DCX_NORESETATTRS);
|
||||
if (NULL != hdc)
|
||||
{
|
||||
HFONT origFont = (HFONT)GetCurrentObject(hdc, OBJ_FONT);
|
||||
SIZE textSize;
|
||||
|
||||
INT heightLimit = (lf.lfHeight < 0) ? 1 : -1;
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? -2 : +2;
|
||||
do
|
||||
{
|
||||
textSize.cx = 0;
|
||||
if (NULL != titleFont) DeleteObject(titleFont);
|
||||
titleFont = CreateFontIndirect(&lf);
|
||||
if (NULL != titleFont)
|
||||
{
|
||||
SelectObject(hdc, titleFont);
|
||||
GetTextExtentPoint32(hdc, pszTitle, cchTitle, &textSize);
|
||||
}
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
|
||||
|
||||
} while(textSize.cx > maxWidth && lf.lfHeight != heightLimit);
|
||||
|
||||
if (0 == textSize.cx)
|
||||
{
|
||||
DeleteObject(titleFont);
|
||||
titleFont = NULL;
|
||||
}
|
||||
|
||||
SelectObject(hdc, origFont);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (NULL == titleFont &&
|
||||
0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
titleFont = CreateFontIndirect(&lf);
|
||||
}
|
||||
return titleFont;
|
||||
}
|
||||
|
||||
LPCWSTR ServicePanel::FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax)
|
||||
{
|
||||
SYSTEMTIME st;
|
||||
ZeroMemory(&st, sizeof(SYSTEMTIME));
|
||||
LPCWSTR cursor;
|
||||
|
||||
cursor = pszDate;
|
||||
INT index = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
INT iVal;
|
||||
|
||||
if (FALSE == StrToIntEx(cursor, STIF_DEFAULT, &iVal) || iVal < 1)
|
||||
{
|
||||
index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (0 == index)
|
||||
{
|
||||
if (iVal < 2000 || iVal > 2100)
|
||||
break;
|
||||
st.wYear = iVal;
|
||||
index++;
|
||||
}
|
||||
else if (1 == index)
|
||||
{
|
||||
if (iVal < 1 || iVal > 12)
|
||||
break;
|
||||
st.wMonth = iVal;
|
||||
index++;
|
||||
}
|
||||
else if (2 == index)
|
||||
{
|
||||
if (iVal < 1 || iVal > 31)
|
||||
break;
|
||||
st.wDay = iVal;
|
||||
index++;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
while(L'\0' != *cursor && L'-' != *cursor) cursor++;
|
||||
if (L'-' == *cursor) cursor++;
|
||||
if (L'\0' == *cursor)
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (3 == index &&
|
||||
0 != GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszBuffer, cchBufferMax))
|
||||
{
|
||||
return pszBuffer;
|
||||
}
|
||||
|
||||
return pszDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
HRESULT ServicePanel::GetFullName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer)
|
||||
return E_POINTER;
|
||||
*pszBuffer = L'\0';
|
||||
|
||||
if (NULL == service) return E_UNEXPECTED;
|
||||
|
||||
ifc_omservicedetails *details;
|
||||
HRESULT hr = service->QueryInterface(IFC_OmServiceDetails, (void**)&details);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = details->GetAuthorFirst(pszBuffer, cchBufferMax);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT cchBuffer = lstrlen(pszBuffer);
|
||||
LPWSTR cursor = pszBuffer + cchBuffer;
|
||||
size_t remaining = cchBufferMax - cchBuffer;
|
||||
|
||||
if (cursor != pszBuffer)
|
||||
{
|
||||
hr = StringCchCopyEx(cursor, remaining, L" ", &cursor, &remaining, 0);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = details->GetAuthorLast(cursor, (UINT)remaining);
|
||||
if (FAILED(hr) || L'\0' == *cursor)
|
||||
{
|
||||
pszBuffer[cchBuffer] = L'\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
void ServicePanel::UpdateName()
|
||||
{
|
||||
HWND hTitle = GetDlgItem(hwnd, IDC_TITLE);
|
||||
if (NULL == hTitle) return;
|
||||
|
||||
WCHAR szBuffer[128] = {0};
|
||||
if (NULL == service ||
|
||||
FAILED(service->GetName(szBuffer, ARRAYSIZE(szBuffer))))
|
||||
{
|
||||
szBuffer[0] = L'\0';
|
||||
}
|
||||
|
||||
INT cchBuffer = lstrlen(szBuffer);
|
||||
RECT rc;
|
||||
GetClientRect(hTitle, &rc);
|
||||
HFONT font = PickTitleFont(szBuffer, cchBuffer, rc.right - rc.left);
|
||||
if (NULL != font)
|
||||
{
|
||||
if (NULL != fontTitle)
|
||||
DeleteObject(fontTitle);
|
||||
|
||||
fontTitle = font;
|
||||
SendMessage(hTitle, WM_SETFONT, (WPARAM)fontTitle, 0L);
|
||||
}
|
||||
|
||||
|
||||
SetWindowText(hTitle, szBuffer);
|
||||
InvalidateRect(hTitle, NULL, TRUE);
|
||||
}
|
||||
|
||||
|
||||
void ServicePanel::UpdateDescription()
|
||||
{
|
||||
HWND hDescription = GetDlgItem(hwnd, IDC_DESCRIPTION);
|
||||
if (NULL == hDescription) return;
|
||||
|
||||
WCHAR szBuffer[4096] = {0};
|
||||
ifc_omservicedetails *details = 0;
|
||||
if (GET_IDETAILS(service, details))
|
||||
{
|
||||
details->GetDescription(szBuffer, ARRAYSIZE(szBuffer));
|
||||
details->Release();
|
||||
}
|
||||
|
||||
SetupDetails_SetDescription(hDescription, szBuffer);
|
||||
}
|
||||
|
||||
void ServicePanel::UpdateMeta()
|
||||
{
|
||||
HWND hMeta = GetDlgItem(hwnd, IDC_SERVICEMETA);
|
||||
if (NULL == hMeta) return;
|
||||
|
||||
WCHAR szBuffer[512] = {0};
|
||||
ifc_omservicedetails *svcdetails = 0;
|
||||
if (GET_IDETAILS(service, svcdetails))
|
||||
{
|
||||
WCHAR szValue[256] = {0}, szPrefix[64] = {0};
|
||||
HRESULT hr = S_OK;
|
||||
LPWSTR cursor = szBuffer;
|
||||
size_t remaining = ARRAYSIZE(szBuffer);
|
||||
|
||||
if (SUCCEEDED(GetFullName(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
|
||||
{
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_BYAUTHOR, szPrefix, ARRAYSIZE(szPrefix));
|
||||
hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
L"%s%s", szPrefix, szValue);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(svcdetails->GetUpdated(szValue, ARRAYSIZE(szValue))) && L'\0' != szValue[0])
|
||||
{
|
||||
if (cursor != szBuffer)
|
||||
hr = StringCchCopyEx(cursor, remaining, L"\r\n", &cursor, &remaining, STRSAFE_NULL_ON_FAILURE);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
WCHAR szDate[128] = {0};
|
||||
WASABI_API_LNGSTRINGW_BUF(IDS_SERVICE_LASTUPDATED, szPrefix, ARRAYSIZE(szPrefix));
|
||||
StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_NULL_ON_FAILURE,
|
||||
L"%s%s", szPrefix, FormatDate(szValue, szDate, ARRAYSIZE(szDate)));
|
||||
}
|
||||
}
|
||||
|
||||
svcdetails->Release();
|
||||
}
|
||||
|
||||
if (NULL == fontMeta)
|
||||
{
|
||||
HFONT dialogFont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0L);
|
||||
LOGFONT lf;
|
||||
if (0 != GetObject(dialogFont, sizeof(LOGFONT), &lf))
|
||||
{
|
||||
StringCchCopy(lf.lfFaceName, ARRAYSIZE(lf.lfFaceName), L"Tahoma");
|
||||
lf.lfWidth = 0;
|
||||
lf.lfHeight += (lf.lfHeight < 0) ? 1 : -1;
|
||||
lf.lfQuality = ANTIALIASED_QUALITY;
|
||||
fontMeta = CreateFontIndirect(&lf);
|
||||
}
|
||||
|
||||
if (NULL != fontMeta)
|
||||
{
|
||||
SendMessage(hMeta, WM_SETFONT, (WPARAM)fontMeta, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowText(hMeta, szBuffer);
|
||||
if (0 != ShowWindow(hMeta, (L'\0' != szBuffer[0]) ? SW_SHOWNA : SW_HIDE))
|
||||
InvalidateRect(hMeta, NULL, TRUE);
|
||||
}
|
||||
|
||||
void ServicePanel::UpdateThumbnail()
|
||||
{
|
||||
if (NULL != thumbnailCache)
|
||||
{
|
||||
thumbnailCache->UnregisterCallback(this);
|
||||
thumbnailCache->Release();
|
||||
thumbnailCache = NULL;
|
||||
}
|
||||
LoadLocalThumbnail(NULL);
|
||||
|
||||
ifc_omservicedetails *details = 0;
|
||||
if (GET_IDETAILS(service, details))
|
||||
{
|
||||
WCHAR szPath[2048] = {0};
|
||||
if (SUCCEEDED(details->GetThumbnail(szPath, ARRAYSIZE(szPath))) && L'\0' != szPath[0])
|
||||
{
|
||||
ifc_omcachemanager *cacheManager;
|
||||
if (SUCCEEDED(OMUTILITY->GetCacheManager(&cacheManager)))
|
||||
{
|
||||
ifc_omcachegroup *cacheGroup;
|
||||
if (SUCCEEDED(cacheManager->Find(L"thumbnails", TRUE, &cacheGroup, NULL)))
|
||||
{
|
||||
|
||||
if (SUCCEEDED(cacheGroup->Find(szPath, TRUE, &thumbnailCache, FALSE)))
|
||||
{
|
||||
thumbnailCache->RegisterCallback(this);
|
||||
if (SUCCEEDED(thumbnailCache->GetPath(szPath, ARRAYSIZE(szPath))))
|
||||
LoadLocalThumbnail(szPath);
|
||||
}
|
||||
cacheGroup->Release();
|
||||
}
|
||||
cacheManager->Release();
|
||||
}
|
||||
}
|
||||
details->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
INT_PTR ServicePanel::OnInitDialog(HWND hFocus, LPARAM lParam)
|
||||
{
|
||||
UpdateName();
|
||||
UpdateDescription();
|
||||
UpdateThumbnail();
|
||||
UpdateMeta();
|
||||
|
||||
if (NULL != service)
|
||||
{
|
||||
ifc_omserviceeventmngr *eventManager;
|
||||
if (SUCCEEDED(service->QueryInterface(IFC_OmServiceEventMngr, (void**)&eventManager)))
|
||||
{
|
||||
eventManager->RegisterHandler(this);
|
||||
eventManager->Release();
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void ServicePanel::OnDestroy()
|
||||
{
|
||||
|
||||
HWND hThumbnail = GetDlgItem(hwnd, IDC_THUMBNAIL);
|
||||
if (NULL != hThumbnail)
|
||||
{
|
||||
HBITMAP hBitmap = (HBITMAP)SendMessage(hThumbnail, STM_SETIMAGE, IMAGE_BITMAP, 0L);
|
||||
if (NULL != hBitmap)
|
||||
DeleteObject(hBitmap);
|
||||
}
|
||||
|
||||
Detach();
|
||||
}
|
||||
|
||||
|
||||
INT_PTR ServicePanel::OnDialogColor(HDC hdc, HWND hControl)
|
||||
{
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
return (INT_PTR)SendMessage(hParent, WM_CTLCOLORDLG, (WPARAM)hdc, (LPARAM)hControl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
INT_PTR ServicePanel::OnStaticColor(HDC hdc, HWND hControl)
|
||||
{
|
||||
INT_PTR result = 0;
|
||||
HWND hParent = GetAncestor(hwnd, GA_PARENT);
|
||||
if (NULL != hParent && hParent != hwnd)
|
||||
result = (INT_PTR)SendMessage(hParent, WM_CTLCOLORSTATIC, (WPARAM)hdc, (LPARAM)hControl);
|
||||
|
||||
INT controlId = GetDlgCtrlID(hControl);
|
||||
switch(controlId)
|
||||
{
|
||||
case IDC_SERVICEMETA:
|
||||
{
|
||||
COLORREF rgbBk = GetBkColor(hdc);
|
||||
COLORREF rgbFg = GetTextColor(hdc);
|
||||
|
||||
ifc_omgraphics *graphics;
|
||||
if (SUCCEEDED(OMUTILITY->GetGraphics(&graphics)))
|
||||
{
|
||||
graphics->BlendColor(rgbFg, rgbBk, 180, &rgbFg);
|
||||
graphics->Release();
|
||||
}
|
||||
|
||||
SetTextColor(hdc, rgbFg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
INT_PTR ServicePanel::OnGetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax)
|
||||
{
|
||||
if (NULL == pszBuffer) return FALSE;
|
||||
return SUCCEEDED(StringCchCopy(pszBuffer, cchBufferMax, (NULL != name) ? name : L""));
|
||||
}
|
||||
|
||||
INT_PTR ServicePanel::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch(uMsg)
|
||||
{
|
||||
case WM_INITDIALOG: return OnInitDialog((HWND)wParam, lParam);
|
||||
case WM_DESTROY: OnDestroy(); break;
|
||||
case WM_CTLCOLORDLG: return OnDialogColor((HDC)wParam, (HWND)lParam);
|
||||
case WM_CTLCOLORSTATIC: return OnStaticColor((HDC)wParam, (HWND)lParam);
|
||||
|
||||
case NSDM_GETUNIQUENAME: MSGRESULT(hwnd, OnGetUniqueName((LPWSTR)lParam, (UINT)wParam));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
ServicePanel *panel = GetPanel(hwnd);
|
||||
if (NULL == panel)
|
||||
{
|
||||
if (WM_INITDIALOG == uMsg)
|
||||
{
|
||||
panel = (ServicePanel*)lParam;
|
||||
if (NULL != panel)
|
||||
panel->Attach(hwnd);
|
||||
}
|
||||
|
||||
if (NULL == panel) return 0;
|
||||
}
|
||||
|
||||
return panel->DialogProc(uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define CBCLASS ServicePanel
|
||||
START_MULTIPATCH;
|
||||
START_PATCH(MPIID_SERVICEEVENT)
|
||||
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, ADDREF, AddRef);
|
||||
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, RELEASE, Release);
|
||||
M_CB(MPIID_SERVICEEVENT, ifc_omserviceevent, QUERYINTERFACE, QueryInterface);
|
||||
M_VCB(MPIID_SERVICEEVENT, ifc_omserviceevent, API_SERVICECHANGE, ServiceChange);
|
||||
|
||||
|
||||
NEXT_PATCH(MPIID_CACHECALLBACK)
|
||||
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, ADDREF, AddRef);
|
||||
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, RELEASE, Release);
|
||||
M_CB(MPIID_CACHECALLBACK, ifc_omcachecallback, QUERYINTERFACE, QueryInterface);
|
||||
M_VCB(MPIID_CACHECALLBACK, ifc_omcachecallback, API_PATHCHANGED, PathChanged);
|
||||
|
||||
END_PATCH
|
||||
END_MULTIPATCH;
|
||||
#undef CBCLASS
|
79
Src/Plugins/Library/ml_online/Setup/setupServicePanel.h
Normal file
79
Src/Plugins/Library/ml_online/Setup/setupServicePanel.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER
|
||||
#define NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <wtypes.h>
|
||||
#include <bfc/multipatch.h>
|
||||
#include <ifc_omserviceevent.h>
|
||||
#include <ifc_omcachecallback.h>
|
||||
|
||||
class ifc_omservice;
|
||||
|
||||
#define MPIID_SERVICEEVENT 10
|
||||
#define MPIID_CACHECALLBACK 20
|
||||
|
||||
|
||||
class ServicePanel : public MultiPatch<MPIID_SERVICEEVENT, ifc_omserviceevent>,
|
||||
public MultiPatch<MPIID_CACHECALLBACK, ifc_omcachecallback>
|
||||
{
|
||||
protected:
|
||||
ServicePanel(LPCWSTR pszName, ifc_omservice *service);
|
||||
~ServicePanel();
|
||||
|
||||
public:
|
||||
static HWND CreateInstance(HWND hParent, LPCWSTR pszName, ifc_omservice *service, ServicePanel **instance);
|
||||
|
||||
public:
|
||||
/* Dispatchable */
|
||||
size_t AddRef();
|
||||
size_t Release();
|
||||
int QueryInterface(GUID interface_guid, void **object);
|
||||
|
||||
/* ifc_omserviceevent */
|
||||
void ServiceChange(ifc_omservice *service, unsigned int modifiedFlags);
|
||||
|
||||
/* ifc_omcachecallback */
|
||||
void PathChanged(ifc_omcacherecord *record);
|
||||
|
||||
protected:
|
||||
void Attach(HWND hwnd);
|
||||
void Detach();
|
||||
|
||||
void UpdateName();
|
||||
void UpdateDescription();
|
||||
void UpdateMeta();
|
||||
void UpdateThumbnail();
|
||||
|
||||
HFONT PickTitleFont(LPCWSTR pszTitle, INT cchTitle, INT maxWidth);
|
||||
LPCWSTR FormatDate(LPCWSTR pszDate, LPWSTR pszBuffer, INT cchBufferMax);
|
||||
HRESULT GetFullName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
|
||||
INT_PTR OnInitDialog(HWND hFocus, LPARAM lParam);
|
||||
void OnDestroy();
|
||||
INT_PTR OnDialogColor(HDC hdc, HWND hControl);
|
||||
INT_PTR OnStaticColor(HDC hdc, HWND hControl);
|
||||
INT_PTR DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
INT_PTR OnGetUniqueName(LPWSTR pszBuffer, UINT cchBufferMax);
|
||||
HRESULT LoadLocalThumbnail(LPCWSTR pszPath);
|
||||
|
||||
private:
|
||||
friend static INT_PTR WINAPI ServicePanel_DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
protected:
|
||||
size_t ref;
|
||||
HWND hwnd;
|
||||
LPWSTR name;
|
||||
ifc_omservice *service;
|
||||
ifc_omcacherecord *thumbnailCache;
|
||||
HFONT fontTitle;
|
||||
HFONT fontMeta;
|
||||
|
||||
private:
|
||||
RECVS_MULTIPATCH;
|
||||
};
|
||||
|
||||
|
||||
#endif //NULLOSFT_ONLINEMEDIA_PLUGIN_SETUP_SERVICE_PANEL_HEADER
|
Loading…
Add table
Add a link
Reference in a new issue