diff options
Diffstat (limited to 'Src/omBrowser/ratingMenuCustomizer.cpp')
-rw-r--r-- | Src/omBrowser/ratingMenuCustomizer.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/Src/omBrowser/ratingMenuCustomizer.cpp b/Src/omBrowser/ratingMenuCustomizer.cpp new file mode 100644 index 00000000..bb397d42 --- /dev/null +++ b/Src/omBrowser/ratingMenuCustomizer.cpp @@ -0,0 +1,161 @@ +#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 + |