winamp/Src/omBrowser/ratingMenuCustomizer.cpp
2024-09-24 14:54:57 +02:00

161 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