mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-18 15:35:54 +01:00
331 lines
8.2 KiB
C++
331 lines
8.2 KiB
C++
|
#include "main.h"
|
||
|
#include "./travelLogHelper.h"
|
||
|
#include "./graphics.h"
|
||
|
#include "./resource.h"
|
||
|
#include "./ifc_skinhelper.h"
|
||
|
#include "./ifc_imageloader.h"
|
||
|
#include "./menu.h"
|
||
|
#include "../Plugins/General/gen_ml/ml_ipc_0313.h"
|
||
|
|
||
|
#include <exdisp.h>
|
||
|
#include <tlogstg.h>
|
||
|
|
||
|
#define TRAVELLOGPOPUP_MAXCHARWIDTH 42
|
||
|
|
||
|
TravelLogHelper::TravelLogHelper(IWebBrowser2 *pWeb)
|
||
|
: ref(1), pWeb2(pWeb), bitmap(NULL), pixelData(NULL), firstFwd(FALSE), entriesCount(0), backEntry(-1)
|
||
|
{
|
||
|
if (NULL != pWeb2)
|
||
|
pWeb2->AddRef();
|
||
|
}
|
||
|
|
||
|
TravelLogHelper::~TravelLogHelper()
|
||
|
{
|
||
|
if (NULL != pWeb2)
|
||
|
pWeb2->Release();
|
||
|
|
||
|
if (NULL != bitmap)
|
||
|
DeleteObject(bitmap);
|
||
|
}
|
||
|
|
||
|
HRESULT TravelLogHelper::CreateInstance(IWebBrowser2 *pWeb2, TravelLogHelper **instance)
|
||
|
{
|
||
|
if (NULL == instance) return E_POINTER;
|
||
|
*instance = NULL;
|
||
|
|
||
|
if (NULL == pWeb2)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
*instance = new TravelLogHelper(pWeb2);
|
||
|
if (NULL == *instance) return E_OUTOFMEMORY;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
size_t TravelLogHelper::AddRef()
|
||
|
{
|
||
|
return InterlockedIncrement((LONG*)&ref);
|
||
|
}
|
||
|
|
||
|
size_t TravelLogHelper::Release()
|
||
|
{
|
||
|
if (0 == ref)
|
||
|
return ref;
|
||
|
|
||
|
LONG r = InterlockedDecrement((LONG*)&ref);
|
||
|
if (0 == r)
|
||
|
delete(this);
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
int TravelLogHelper::QueryInterface(GUID interface_guid, void **object)
|
||
|
{
|
||
|
if (NULL == object) return E_POINTER;
|
||
|
|
||
|
if (IsEqualIID(interface_guid, IFC_TravelLogHelper))
|
||
|
*object = static_cast<ifc_travelloghelper*>(this);
|
||
|
else if (IsEqualIID(interface_guid, IFC_MenuCustomizer))
|
||
|
*object = static_cast<ifc_menucustomizer*>(this);
|
||
|
else
|
||
|
{
|
||
|
*object = NULL;
|
||
|
return E_NOINTERFACE;
|
||
|
}
|
||
|
|
||
|
if (NULL == *object)
|
||
|
return E_UNEXPECTED;
|
||
|
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT TravelLogHelper::QueryStorage(ITravelLogStg **ppLog)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
if (NULL == ppLog)
|
||
|
return E_POINTER;
|
||
|
|
||
|
*ppLog = NULL;
|
||
|
|
||
|
if (NULL == pWeb2) return E_UNEXPECTED;
|
||
|
|
||
|
IServiceProvider *pProvider;
|
||
|
hr = pWeb2->QueryInterface(IID_IServiceProvider, (void**)&pProvider);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
hr = pProvider->QueryService(SID_STravelLogCursor, ppLog);
|
||
|
pProvider->Release();
|
||
|
}
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
BOOL TravelLogHelper::DrawIcon(HMENU menuInstance, HDC hdc, DRAWITEMSTRUCT *pdis)
|
||
|
{
|
||
|
if (0 == (ODS_SELECTED & pdis->itemState))
|
||
|
return FALSE;
|
||
|
|
||
|
LONG entry = pdis->itemID - 101;
|
||
|
if (entry < 0 || ((ULONG)entry) > entriesCount)
|
||
|
return FALSE;
|
||
|
|
||
|
BOOL fForward = (FALSE != firstFwd) ? TRUE : FALSE;
|
||
|
if (-1 != backEntry && entry >= backEntry)
|
||
|
fForward = !fForward;
|
||
|
|
||
|
if (NULL == bitmap)
|
||
|
{
|
||
|
ifc_omimageloader *imageLoader;
|
||
|
if (SUCCEEDED(Plugin_QueryImageLoader(Plugin_GetInstance(), MAKEINTRESOURCE(IDR_MENUARROW_IMAGE), FALSE, &imageLoader)))
|
||
|
{
|
||
|
if (SUCCEEDED(imageLoader->LoadBitmapEx(&bitmap, &header, &pixelData)))
|
||
|
{
|
||
|
if (header.biHeight < 0) header.biHeight = -header.biHeight;
|
||
|
|
||
|
Image_Colorize((BYTE*)pixelData, header.biWidth, header.biHeight,
|
||
|
header.biBitCount, GetBkColor(hdc), GetTextColor(hdc), TRUE);
|
||
|
}
|
||
|
imageLoader->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL resultOk = FALSE;
|
||
|
if (NULL != bitmap)
|
||
|
{
|
||
|
INT cx = header.biWidth/2;
|
||
|
INT cy = header.biHeight;
|
||
|
if (cy < 0) cy = -cy;
|
||
|
|
||
|
INT side = (pdis->rcItem.bottom - pdis->rcItem.top - 2);
|
||
|
if (cy < side) side = cy;
|
||
|
|
||
|
INT top = pdis->rcItem.top + ((pdis->rcItem.bottom - pdis->rcItem.top) - side)/2;
|
||
|
INT left = pdis->rcItem.left + (GetSystemMetrics(SM_CXMENUCHECK) - side)/2 + 3;
|
||
|
|
||
|
resultOk = StretchDIBits(hdc, left, top, side, side,
|
||
|
((FALSE != fForward) ? cx : 0), 0, cx, cy, pixelData, (BITMAPINFO*)&header, DIB_RGB_COLORS, SRCCOPY);
|
||
|
|
||
|
}
|
||
|
return resultOk;
|
||
|
}
|
||
|
|
||
|
INT TravelLogHelper::CustomDraw(HMENU menuInstance, INT action, HDC hdc, LPARAM param)
|
||
|
{
|
||
|
switch(action)
|
||
|
{
|
||
|
case MLMENU_ACTION_DRAWITEM:
|
||
|
return MLMENU_WANT_DRAWPART;
|
||
|
case MLMENU_ACTION_DRAWICON:
|
||
|
return DrawIcon(menuInstance, hdc, (DRAWITEMSTRUCT*)param);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT TravelLogHelper::ShowPopup(UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm)
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
ITravelLogStg *pLog;
|
||
|
hr = QueryStorage(&pLog);
|
||
|
if (FAILED(hr) || NULL == pLog) return hr;
|
||
|
|
||
|
DWORD entriesMax;
|
||
|
if (FAILED(pLog->GetCount(TLEF_RELATIVE_FORE | TLEF_RELATIVE_BACK, &entriesMax)))
|
||
|
entriesMax = 0;
|
||
|
|
||
|
ITravelLogEntry **entries = NULL;
|
||
|
|
||
|
INT selectedEntry = -1;
|
||
|
firstFwd = (0 == (TPM_BOTTOMALIGN & fuFlags));
|
||
|
entriesCount = 0;
|
||
|
backEntry = -1;
|
||
|
|
||
|
if (0 != entriesMax)
|
||
|
{
|
||
|
entries = (ITravelLogEntry**)calloc(entriesMax, sizeof(ITravelLogEntry*));
|
||
|
if (NULL != entries)
|
||
|
{
|
||
|
IEnumTravelLogEntry *pEnum = NULL;
|
||
|
TLENUMF tlenum = (0 != (TPM_BOTTOMALIGN & fuFlags)) ? TLEF_RELATIVE_BACK : TLEF_RELATIVE_FORE;
|
||
|
if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum)))
|
||
|
{
|
||
|
ULONG fetched;
|
||
|
pEnum->Reset();
|
||
|
pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched);
|
||
|
if (0 != fetched)
|
||
|
{
|
||
|
ITravelLogEntry *t, **l, **r;
|
||
|
for (l = &entries[entriesCount], r = &entries[entriesCount + fetched - 1]; l < r; l++, r--)
|
||
|
{
|
||
|
t = *l;
|
||
|
*l = *r;
|
||
|
*r = t;
|
||
|
}
|
||
|
entriesCount += fetched;
|
||
|
}
|
||
|
pEnum->Release();
|
||
|
}
|
||
|
|
||
|
tlenum = (0 != (TLEF_RELATIVE_FORE & tlenum)) ?
|
||
|
((tlenum & ~TLEF_RELATIVE_FORE) | TLEF_RELATIVE_BACK) :
|
||
|
tlenum = ((tlenum & ~TLEF_RELATIVE_BACK) | TLEF_RELATIVE_FORE);
|
||
|
|
||
|
if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum)))
|
||
|
{
|
||
|
|
||
|
ULONG fetched;
|
||
|
pEnum->Reset();
|
||
|
pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched);
|
||
|
if (0 != fetched)
|
||
|
{
|
||
|
backEntry = entriesCount;
|
||
|
entriesCount += fetched;
|
||
|
}
|
||
|
pEnum->Release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (entriesCount > 0)
|
||
|
{
|
||
|
HMENU hMenu = CreatePopupMenu();
|
||
|
if (NULL != hMenu)
|
||
|
{
|
||
|
MENUITEMINFOW mii = {0};
|
||
|
mii.cbSize = sizeof(MENUITEMINFOW);
|
||
|
mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE;
|
||
|
mii.fState = MFS_ENABLED | MFS_UNCHECKED;
|
||
|
|
||
|
for (ULONG i = 0; i < entriesCount; i++)
|
||
|
{
|
||
|
if (NULL != entries[i])
|
||
|
{
|
||
|
LPWSTR pszTitle;
|
||
|
if (SUCCEEDED(entries[i]->GetTitle(&pszTitle)) && NULL != pszTitle)
|
||
|
{
|
||
|
INT cchTitle = lstrlen(pszTitle);
|
||
|
|
||
|
if (cchTitle > TRAVELLOGPOPUP_MAXCHARWIDTH)
|
||
|
{
|
||
|
pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH] = L'\0';
|
||
|
for (INT k = 0; k < 3; k++)
|
||
|
pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH - 1 - k] = L'.';
|
||
|
|
||
|
}
|
||
|
mii.dwTypeData = pszTitle;
|
||
|
mii.wID = 101 + i;
|
||
|
InsertMenuItem(hMenu, i, TRUE, &mii);
|
||
|
CoTaskMemFree(pszTitle);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
{ // insert current page
|
||
|
WCHAR szBuffer[256] = {0};
|
||
|
|
||
|
Plugin_LoadString(IDS_CURRENT_PAGE, szBuffer, ARRAYSIZE(szBuffer));
|
||
|
|
||
|
mii.dwTypeData = szBuffer;
|
||
|
mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE | MIIM_FTYPE;
|
||
|
mii.fState = MFS_ENABLED | MFS_DEFAULT | MFS_CHECKED;
|
||
|
mii.fType = MFT_STRING | MFT_RADIOCHECK;
|
||
|
mii.wID = 100;
|
||
|
|
||
|
if (-1 == backEntry)
|
||
|
InsertMenuItem(hMenu, GetMenuItemCount(hMenu), TRUE, &mii);
|
||
|
else
|
||
|
InsertMenuItem(hMenu, 101 + backEntry, FALSE, &mii);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HANDLE hHook = Menu_InitializeHook(hwnd, this);
|
||
|
|
||
|
UINT commandId = TrackPopupMenuEx(hMenu, fuFlags | TPM_RETURNCMD, x, y, hwnd, lptpm);
|
||
|
|
||
|
if (NULL != hHook) Menu_RemoveHook(hHook);
|
||
|
|
||
|
if (commandId > 100 && commandId <= (100 + entriesCount))
|
||
|
selectedEntry = commandId - 101;
|
||
|
|
||
|
DestroyMenu(hMenu);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
if (-1 != selectedEntry && NULL != entries[selectedEntry])
|
||
|
{
|
||
|
pLog->TravelTo(entries[selectedEntry]);
|
||
|
}
|
||
|
|
||
|
if (NULL != entries)
|
||
|
{
|
||
|
for (ULONG i = 0; i < entriesCount; i++)
|
||
|
{
|
||
|
if (NULL != entries[i]) entries[i]->Release();
|
||
|
}
|
||
|
free(entries);
|
||
|
|
||
|
}
|
||
|
pLog->Release();
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
#define CBCLASS TravelLogHelper
|
||
|
START_MULTIPATCH;
|
||
|
START_PATCH(MPIID_TRAVELLOGHELPER)
|
||
|
M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, ADDREF, AddRef);
|
||
|
M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, RELEASE, Release);
|
||
|
M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, QUERYINTERFACE, QueryInterface);
|
||
|
M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_QUERYSTORAGE, QueryStorage);
|
||
|
M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_SHOWPOPUP, ShowPopup);
|
||
|
NEXT_PATCH(MPIID_MENUCUSTOMIZER)
|
||
|
M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, ADDREF, AddRef);
|
||
|
M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, RELEASE, Release);
|
||
|
M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, QUERYINTERFACE, QueryInterface);
|
||
|
M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, API_CUSTOMDRAW, CustomDraw);
|
||
|
END_PATCH
|
||
|
END_MULTIPATCH;
|
||
|
#undef CBCLASS
|