toolbarRating.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. #include "main.h"
  2. #include "./toolbarRating.h"
  3. #include "./toolbar.h"
  4. #include "./graphics.h"
  5. #include "./resource.h"
  6. #include "./ifc_skinhelper.h"
  7. #include "./ifc_skinnedrating.h"
  8. #include "./menu.h"
  9. #include "../Plugins/General/gen_ml/ml_ipc_0313.h"
  10. #include <strsafe.h>
  11. #define RATING_SPACECX_PX 4
  12. #define RATING_SPACECX_UNIT 2
  13. #define RATING_STARSTYLE (RDS_LEFT | RDS_TOP)
  14. BYTE rating;
  15. BYTE highlighted;
  16. BYTE focused;
  17. RECT ratingRect;
  18. RECT textRect;
  19. INT baseLine;
  20. ifc_skinnedrating *skinnedRating;
  21. ToolbarRating::ToolbarRating(LPCSTR pszName, UINT nStyle, LPCWSTR pszText, LPCWSTR pszDescription) :
  22. ToolbarItem(pszName, nStyle, ICON_NONE, pszText, pszDescription),
  23. rating(0), highlighted(0), focused(0), baseLine(0), skinnedRating(NULL)
  24. {
  25. ifc_skinhelper *skinHelper;
  26. if (SUCCEEDED(Plugin_GetSkinHelper(&skinHelper)))
  27. {
  28. if (FAILED(skinHelper->QueryInterface(IFC_SkinnedRating, (void**)&skinnedRating)))
  29. skinnedRating = NULL;
  30. skinHelper->Release();
  31. }
  32. }
  33. ToolbarRating::~ToolbarRating()
  34. {
  35. if (NULL != skinnedRating)
  36. skinnedRating->Release();
  37. }
  38. ToolbarItem* CALLBACK ToolbarRating::CreateInstance(ToolbarItem::Template *item)
  39. {
  40. if (NULL == item)
  41. return NULL;
  42. return new ToolbarRating( (NULL != item->name) ? item->name : TOOLCLS_RATING,
  43. item->style,
  44. item->text,
  45. item->description);
  46. }
  47. static BOOL ToolbarRating_GetTextSize(LPCWSTR pszText, HWND hToolbar, SIZE *textSize)
  48. {
  49. BOOL result = FALSE;
  50. WCHAR szText[64] = {0};
  51. if (IS_INTRESOURCE(pszText))
  52. {
  53. Plugin_LoadString((INT)(INT_PTR)pszText, szText, ARRAYSIZE(szText));
  54. pszText = szText;
  55. }
  56. INT cchText = (NULL != pszText) ? lstrlenW(pszText) : 0;
  57. if (0 != cchText)
  58. {
  59. HDC hdc = GetDCEx(hToolbar, NULL, DCX_CACHE | DCX_NORESETATTRS);
  60. if (NULL != hdc)
  61. {
  62. HFONT font = (HFONT)SendMessage(hToolbar, WM_GETFONT, 0, 0L);
  63. HFONT originalFont = (HFONT)SelectObject(hdc, font);
  64. result = GetTextExtentPoint32(hdc, pszText, cchText, textSize);
  65. SelectObject(hdc, originalFont);
  66. ReleaseDC(hToolbar, hdc);
  67. }
  68. }
  69. return result;
  70. }
  71. BOOL ToolbarRating::AdjustRect(HWND hToolbar, RECT *proposedRect)
  72. {
  73. TOOLBARTEXTMETRIC ttm;
  74. if (NULL == skinnedRating || FAILED(skinnedRating->CalcMinRect(5, &ratingRect)))
  75. ::SetRectEmpty(&ratingRect);
  76. if (!Toolbar_GetTextMetrics(hToolbar, &ttm))
  77. ZeroMemory(&ttm, sizeof(TOOLBARTEXTMETRIC));
  78. ::SetRectEmpty(&textRect);
  79. ToolbarRating_GetTextSize(text, hToolbar, ((SIZE*)&textRect) + 1);
  80. INT spaceCX = MulDiv(RATING_SPACECX_UNIT, ttm.aveCharWidth, 4);
  81. LONG cx = (ratingRect.right - ratingRect.left) + 2*spaceCX + (textRect.right - textRect.left) + 4;
  82. ::OffsetRect(&textRect, spaceCX, ttm.origY - proposedRect->top);
  83. baseLine = ttm.baseY;
  84. ::OffsetRect(&ratingRect,
  85. spaceCX + (textRect.right - textRect.left) + 4,
  86. (ttm.origY - proposedRect->top) + baseLine - (ratingRect.bottom - ratingRect.top) + 1);
  87. proposedRect->right = proposedRect->left + cx;
  88. return TRUE;
  89. }
  90. BOOL ToolbarRating::Paint(HWND hToolbar, HDC hdc, const RECT *paintRect, UINT state)
  91. {
  92. RECT cotrolRect;
  93. CopyRect(&cotrolRect, &ratingRect);
  94. ::OffsetRect(&cotrolRect, rect.left, rect.top);
  95. INT trackingVal = (0 != (stateHighlighted & style)) ? highlighted : rating;
  96. UINT fStyle = RATING_STARSTYLE | RDS_OPAQUE;
  97. if (0 == rating || 0 != ((stateFocused | stateHighlighted) & state))
  98. fStyle |= RDS_SHOWEMPTY;
  99. if (0 == (stateDisabled & style))
  100. fStyle |= RDS_HOT;
  101. HRGN rgn = CreateRectRgnIndirect(&rect);
  102. HRGN rgn2 = CreateRectRgnIndirect(&textRect);
  103. OffsetRgn(rgn2, rect.left, rect.top);
  104. CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
  105. SetRectRgn(rgn2, cotrolRect.left, cotrolRect.top, cotrolRect.right, cotrolRect.bottom);
  106. CombineRgn(rgn, rgn, rgn2, RGN_DIFF);
  107. HBRUSH hb = Toolbar_GetBkBrush(hToolbar);
  108. FillRgn(hdc, rgn, hb);
  109. DeleteObject(rgn);
  110. DeleteObject(rgn2);
  111. if (!::IsRectEmpty(&textRect))
  112. {
  113. WCHAR szText[64], *pszText(text);
  114. if (IS_INTRESOURCE(pszText))
  115. {
  116. Plugin_LoadString((INT)(INT_PTR)pszText, szText, ARRAYSIZE(szText));
  117. pszText = szText;
  118. }
  119. INT cchText = lstrlenW(pszText);
  120. if (0 != cchText)
  121. {
  122. UINT originalAlign = SetTextAlign(hdc, TA_LEFT | TA_BASELINE);
  123. RECT rc;
  124. CopyRect(&rc, &textRect);
  125. ::OffsetRect(&rc, rect.left, rect.top);
  126. ExtTextOut(hdc, rc.left, rc.top + baseLine, ETO_OPAQUE, &rc, pszText, cchText, NULL);
  127. if ((TA_LEFT | TA_BASELINE) != originalAlign) SetTextAlign(hdc, originalAlign);
  128. }
  129. }
  130. if (NULL == skinnedRating || FAILED(skinnedRating->Draw(hdc, 5, rating, trackingVal, &cotrolRect, fStyle)))
  131. {
  132. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &cotrolRect, NULL, 0, NULL);
  133. }
  134. else
  135. {
  136. if (stateFocused == ((stateFocused | stateNoFocusRect) & state) && focused > 0 && focused < 6)
  137. {
  138. RECT focusRect;
  139. CopyRect(&focusRect, &cotrolRect);
  140. INT starWidth = (cotrolRect.right - cotrolRect.left)/5;
  141. focusRect.left += starWidth * (focused - 1);
  142. focusRect.right = focusRect.left + starWidth;
  143. InflateRect(&focusRect, 1, 1);
  144. COLORREF origBk = SetBkColor(hdc, 0x00000000);
  145. COLORREF origFg = SetTextColor(hdc, 0x00FFFFFF);
  146. DrawFocusRect(hdc, &focusRect);
  147. if (origBk != 0x00000000) SetBkColor(hdc, origBk);
  148. if (origFg != 0x00FFFFFF) SetTextColor(hdc, origFg);
  149. }
  150. }
  151. return TRUE;
  152. }
  153. void ToolbarRating::MouseMove(HWND hToolbar, UINT mouseFlags, POINT pt)
  154. {
  155. BYTE tracking = 0;
  156. UINT state = 0;
  157. if (PtInItem(pt))
  158. {
  159. state = stateHighlighted;
  160. RECT controlRect;
  161. CopyRect(&controlRect, &ratingRect);
  162. ::OffsetRect(&controlRect, rect.left, rect.top);
  163. POINT ptTest = pt;
  164. ptTest.y = controlRect.top;
  165. LONG result;
  166. if (NULL == skinnedRating || FAILED(skinnedRating->HitTest(pt, 5, &controlRect, RATING_STARSTYLE, &result)))
  167. result = 0;
  168. UINT hitTest = HIWORD(result);
  169. if (0 != ((RHT_ONVALUE | RHT_ONVALUEABOVE | RHT_ONVALUEBELOW) & hitTest))
  170. tracking = (BYTE)LOWORD(result);
  171. }
  172. BOOL invalidate = FALSE;
  173. if (tracking != highlighted)
  174. {
  175. highlighted = tracking;
  176. invalidate = TRUE;
  177. }
  178. if ((stateHighlighted & style) != (stateHighlighted & state))
  179. {
  180. style |= ((style & ~stateHighlighted) | state);
  181. invalidate = TRUE;
  182. }
  183. if (FALSE != invalidate)
  184. {
  185. RECT invalidRect;
  186. CopyRect(&invalidRect, &ratingRect);
  187. ::OffsetRect(&invalidRect, rect.left, rect.top);
  188. InvalidateRect(hToolbar, &invalidRect, FALSE);
  189. Toolbar_UpdateTip(hToolbar);
  190. }
  191. }
  192. void ToolbarRating::MouseLeave(HWND hToolbar)
  193. {
  194. BOOL invalidate = FALSE;
  195. if (highlighted != 0)
  196. {
  197. highlighted = 0;
  198. invalidate = TRUE;
  199. }
  200. if (0 != (stateHighlighted & style))
  201. {
  202. style &= ~stateHighlighted;
  203. invalidate = TRUE;
  204. }
  205. if (FALSE != invalidate)
  206. {
  207. RECT invalidRect;
  208. CopyRect(&invalidRect, &ratingRect);
  209. ::OffsetRect(&invalidRect, rect.left, rect.top);
  210. InvalidateRect(hToolbar, &invalidRect, FALSE);
  211. }
  212. }
  213. void ToolbarRating::LButtonDown(HWND hToolbar, UINT mouseFlags, POINT pt)
  214. {
  215. style |= statePressed;
  216. }
  217. void ToolbarRating::LButtonUp(HWND hToolbar, UINT mouseFlags, POINT pt)
  218. {
  219. style &= ~statePressed;
  220. }
  221. void ToolbarRating::Click(HWND hToolbar, UINT mouseFlags, POINT pt)
  222. {
  223. if (0 == (ToolbarItem::statePressed & style))
  224. return;
  225. RECT controlRect;
  226. CopyRect(&controlRect, &ratingRect);
  227. ::OffsetRect(&controlRect, rect.left, rect.top);
  228. POINT ptTest = pt;
  229. ptTest.y = controlRect.top;
  230. LONG result;
  231. if (NULL == skinnedRating || FAILED(skinnedRating->HitTest(pt, 5, &controlRect, RATING_STARSTYLE, &result)))
  232. result = 0;
  233. if (0 != ((RHT_ONVALUE | RHT_ONVALUEABOVE | RHT_ONVALUEBELOW) & HIWORD(result)) && LOWORD(result) > 0)
  234. {
  235. SendRating(hToolbar, LOWORD(result));
  236. }
  237. }
  238. void ToolbarRating::SendRating(HWND hToolbar, INT ratingValue)
  239. {
  240. INT commandId = 0;
  241. switch(ratingValue)
  242. {
  243. case 1: commandId = ID_RATING_VALUE_1; break;
  244. case 2: commandId = ID_RATING_VALUE_2; break;
  245. case 3: commandId = ID_RATING_VALUE_3; break;
  246. case 4: commandId = ID_RATING_VALUE_4; break;
  247. case 5: commandId = ID_RATING_VALUE_5; break;
  248. }
  249. if (0 != commandId)
  250. Toolbar_SendCommand(hToolbar, commandId);
  251. }
  252. void ToolbarRating::UpdateSkin(HWND hToolbar)
  253. {
  254. }
  255. BOOL ToolbarRating::PtInItem(POINT pt)
  256. {
  257. return (pt.x >= (rect.left + textRect.left) && pt.x < (rect.left + ratingRect.right) && rect.bottom != rect.top);
  258. }
  259. BOOL ToolbarRating::SetValueInt(HWND hToolbar, INT value)
  260. {
  261. if (value < 0) value = 0;
  262. if (value > 5) value = 5;
  263. if (rating != value)
  264. {
  265. rating = value;
  266. RECT invalidRect;
  267. CopyRect(&invalidRect, &ratingRect);
  268. ::OffsetRect(&invalidRect, rect.left, rect.top);
  269. InvalidateRect(hToolbar, &invalidRect, FALSE);
  270. }
  271. return TRUE;
  272. }
  273. static LPCWSTR ToolbarRating_FormatRating(INT ratingValue, LPWSTR pszBuffer, INT cchBufferMax)
  274. {
  275. INT stringId;
  276. switch(ratingValue)
  277. {
  278. case 5: stringId = IDS_RATING_5; break;
  279. case 4: stringId = IDS_RATING_4; break;
  280. case 3: stringId = IDS_RATING_3; break;
  281. case 2: stringId = IDS_RATING_2; break;
  282. case 1: stringId = IDS_RATING_1; break;
  283. default: stringId = IDS_RATING_0; break;
  284. }
  285. Plugin_LoadString(stringId, pszBuffer, cchBufferMax);
  286. return pszBuffer;
  287. }
  288. INT ToolbarRating::GetTip(LPTSTR pszBuffer, INT cchBufferMax)
  289. {
  290. WCHAR szText[64] = {0}, szRated[32] = {0};
  291. size_t remaining = 0;
  292. LPWSTR cursor;
  293. Plugin_LoadString(IDS_RATING_CURRENT, szText, ARRAYSIZE(szText));
  294. ToolbarRating_FormatRating(rating, szRated, ARRAYSIZE(szRated));
  295. HRESULT hr = StringCchPrintfEx(pszBuffer, cchBufferMax, &cursor, &remaining, STRSAFE_IGNORE_NULLS, TEXT("%s %s "), szText, szRated);
  296. if (FAILED(hr)) return 0;
  297. if (NULL != highlighted)
  298. {
  299. Plugin_LoadString(IDS_RATING_CHANGETO, szText, ARRAYSIZE(szText));
  300. ToolbarRating_FormatRating(highlighted, szRated, ARRAYSIZE(szRated));
  301. hr = StringCchPrintfEx(cursor, remaining, &cursor, &remaining, STRSAFE_IGNORE_NULLS, TEXT("\r\n%s %s "), szText, szRated);
  302. if (FAILED(hr)) return 0;
  303. }
  304. return cchBufferMax - (INT)remaining;
  305. }
  306. BOOL ToolbarRating::FillMenuInfo(HWND hToolbar, MENUITEMINFO *pmii, LPWSTR pszBuffer, INT cchBufferMax)
  307. {
  308. pmii->fMask = MIIM_STRING | MIIM_ID | MIIM_STATE | MIIM_SUBMENU;
  309. pmii->wID = 0;
  310. pmii->fState = MFS_ENABLED;
  311. pmii->dwTypeData = pszBuffer;
  312. pmii->hSubMenu = Menu_GetMenu(MENU_RATING, RATINGTOMCF(rating));
  313. if (IS_INTRESOURCE(text))
  314. {
  315. Plugin_LoadString((INT)(INT_PTR)text, pszBuffer, cchBufferMax);
  316. }
  317. else
  318. {
  319. if (FAILED(StringCchCopyEx(pszBuffer, cchBufferMax, text, NULL, NULL, STRSAFE_IGNORE_NULLS)))
  320. pszBuffer[0] = L'\0';
  321. }
  322. return TRUE;
  323. }
  324. void ToolbarRating::SetFocus(HWND hToolbar, ToolbarItem *focusItem, BOOL fSet)
  325. {
  326. if (FALSE != fSet)
  327. {
  328. focused = 1;
  329. if (NULL != focusItem)
  330. {
  331. INT mineIndex = Toolbar_FindItem(hToolbar, name);
  332. INT otherIndex = Toolbar_FindItem(hToolbar, focusItem->GetName());
  333. if (ITEM_ERR != mineIndex &&
  334. ITEM_ERR != otherIndex &&
  335. otherIndex > mineIndex)
  336. {
  337. focused = 5;
  338. }
  339. }
  340. }
  341. else
  342. {
  343. focused = 0;
  344. }
  345. InvalidateRect(hToolbar, &rect, FALSE);
  346. }
  347. BOOL ToolbarRating::KeyDown(HWND hToolbar, INT vKey, UINT flags)
  348. {
  349. switch(vKey)
  350. {
  351. case VK_LEFT:
  352. if (focused > 1)
  353. {
  354. focused--;
  355. InvalidateRect(hToolbar, &rect, FALSE);
  356. return TRUE;
  357. }
  358. break;
  359. case VK_RIGHT:
  360. if (focused < 5)
  361. {
  362. focused++;
  363. InvalidateRect(hToolbar, &rect, FALSE);
  364. return TRUE;
  365. }
  366. break;
  367. case VK_SPACE:
  368. case VK_RETURN:
  369. SetStyle(hToolbar, statePressed, statePressed);
  370. return TRUE;
  371. }
  372. return FALSE;
  373. }
  374. BOOL ToolbarRating::KeyUp(HWND hToolbar, INT vKey, UINT flags)
  375. {
  376. switch(vKey)
  377. {
  378. case VK_SPACE:
  379. case VK_RETURN:
  380. if (0 != (statePressed & style) && 0 != focused)
  381. {
  382. SetStyle(hToolbar, 0, statePressed);
  383. SendRating(hToolbar, focused);
  384. }
  385. return TRUE;
  386. }
  387. return FALSE;
  388. }