mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-12-29 00:26:06 +00:00
162 lines
3.7 KiB
C++
162 lines
3.7 KiB
C++
#include "main.h"
|
|
#include "./ratingMenuCustomizer.h"
|
|
#include "./ifc_skinhelper.h"
|
|
#include "./ifc_skinnedrating.h"
|
|
|
|
#include "../Plugins/General/gen_ml/ml_ipc_0313.h"
|
|
|
|
#define RATING_MINSPACECX 16
|
|
|
|
RatingMenuCustomizer::RatingMenuCustomizer(HMENU hMenu, ifc_skinnedrating *skinnedRating)
|
|
: ref(1), menu(hMenu), skin(skinnedRating)
|
|
{
|
|
if (NULL != skin)
|
|
skin->AddRef();
|
|
}
|
|
|
|
RatingMenuCustomizer::~RatingMenuCustomizer()
|
|
{
|
|
if (NULL != skin)
|
|
skin->Release();
|
|
}
|
|
|
|
HRESULT RatingMenuCustomizer::CreateInstance(HMENU hMenu, ifc_skinnedrating *skinnedRating, RatingMenuCustomizer **instance)
|
|
{
|
|
if (NULL == instance) return E_POINTER;
|
|
*instance = NULL;
|
|
|
|
if (NULL == hMenu || NULL == skinnedRating) return E_INVALIDARG;
|
|
|
|
*instance = new RatingMenuCustomizer(hMenu, skinnedRating);
|
|
if (NULL == *instance) return E_OUTOFMEMORY;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
size_t RatingMenuCustomizer::AddRef()
|
|
{
|
|
return InterlockedIncrement((LONG*)&ref);
|
|
}
|
|
|
|
size_t RatingMenuCustomizer::Release()
|
|
{
|
|
if (0 == ref)
|
|
return ref;
|
|
|
|
LONG r = InterlockedDecrement((LONG*)&ref);
|
|
if (0 == r)
|
|
delete(this);
|
|
|
|
return r;
|
|
}
|
|
|
|
int RatingMenuCustomizer::QueryInterface(GUID interface_guid, void **object)
|
|
{
|
|
if (NULL == object) return E_POINTER;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
INT RatingMenuCustomizer::CustomDraw(HMENU menuInstance, INT action, HDC hdc, LPARAM param)
|
|
{
|
|
if (menuInstance != menu)
|
|
return FALSE;
|
|
|
|
switch(action)
|
|
{
|
|
case MLMENU_ACTION_MEASUREITEM: return MeasureRating(hdc, (MEASUREITEMSTRUCT*)param);
|
|
case MLMENU_ACTION_DRAWITEM: return MLMENU_WANT_DRAWPART;
|
|
case MLMENU_ACTION_DRAWBACK: break;
|
|
case MLMENU_ACTION_DRAWICON: break;
|
|
case MLMENU_ACTION_DRAWTEXT: return DrawRating(hdc, (DRAWITEMSTRUCT*)param);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HRESULT RatingMenuCustomizer::GetValue(INT itemId, INT *valueOut)
|
|
{
|
|
if (NULL == menu) return E_UNEXPECTED;
|
|
|
|
WCHAR szBuffer[32] = {0};
|
|
INT cchBuffer = GetMenuStringW(menu, itemId, szBuffer, ARRAYSIZE(szBuffer), MF_BYCOMMAND);
|
|
if (cchBuffer < 1 || cchBuffer > 5)
|
|
return E_INVALIDARG;
|
|
|
|
for (INT i = 1; i < cchBuffer; i++)
|
|
{
|
|
if (szBuffer[i -1] != szBuffer[i])
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (NULL != valueOut)
|
|
*valueOut = cchBuffer;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
INT RatingMenuCustomizer::MeasureRating(HDC hdc, MEASUREITEMSTRUCT *pmis)
|
|
{
|
|
RECT rect;
|
|
if (NULL == skin || NULL == hdc ||
|
|
FAILED(GetValue(pmis->itemID, NULL)) ||
|
|
FAILED(skin->CalcMinRect(5, &rect)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pmis->itemHeight = rect.bottom - rect.top + 6;
|
|
|
|
TEXTMETRIC tm;
|
|
if (GetTextMetrics(hdc, &tm) &&
|
|
(UINT)(tm.tmHeight + 2) > pmis->itemHeight)
|
|
{
|
|
pmis->itemHeight = tm.tmHeight + 2;
|
|
}
|
|
|
|
INT spaceCX = (pmis->itemHeight > RATING_MINSPACECX) ? pmis->itemHeight : RATING_MINSPACECX;
|
|
pmis->itemWidth = rect.right - rect.left + (2 * spaceCX) - (GetSystemMetrics(SM_CXMENUCHECK) - 1);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
INT RatingMenuCustomizer::DrawRating(HDC hdc, DRAWITEMSTRUCT *pdis)
|
|
{
|
|
INT value;
|
|
if (NULL == skin || NULL == hdc || FAILED(GetValue(pdis->itemID, &value)))
|
|
return FALSE;
|
|
|
|
INT spaceCX = ((pdis->rcItem.bottom - pdis->rcItem.top) > RATING_MINSPACECX) ?
|
|
(pdis->rcItem.bottom - pdis->rcItem.top) :
|
|
RATING_MINSPACECX;
|
|
|
|
RECT rect;
|
|
CopyRect(&rect, &pdis->rcItem);
|
|
rect.left += spaceCX;
|
|
|
|
UINT menuState = GetMenuState(menu, pdis->itemID, MF_BYCOMMAND);
|
|
UINT trackingValue = (0 == ((MF_DISABLED | MF_GRAYED) & menuState)) ? value : 0;
|
|
|
|
return SUCCEEDED(skin->Draw(hdc, 5, value, trackingValue, &rect, RDS_LEFT | RDS_VCENTER | RDS_HOT));
|
|
}
|
|
|
|
#define CBCLASS RatingMenuCustomizer
|
|
START_DISPATCH;
|
|
CB(API_CUSTOMDRAW, CustomDraw);
|
|
END_DISPATCH;
|
|
#undef CBCLASS
|
|
|