local_menu.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include "./main.h"
  2. #include "./local_menu.h"
  3. #include "../nu/menuHelpers.h"
  4. #include "./resource.h"
  5. #include "./api__ml_online.h"
  6. #include "../../General/gen_ml/menu.h"
  7. #include <windows.h>
  8. #include <strsafe.h>
  9. #define MENU_SERVICECONTEXT 0
  10. #define MENU_GALERYCONTEXT 1
  11. #define MENU_RATING 2
  12. #define MENU_VIEW 3
  13. #define MENU_NAVIGATION 4
  14. #define MENU_TOOLBAR 5
  15. #define RATING_MARKER MAKELONG(MAKEWORD('R','A'),MAKEWORD('T','E'))
  16. #define RATING_MINSPACECX 16
  17. typedef BOOL (__cdecl *MLISSKINNEDPOPUPENABLED)(void);
  18. typedef HANDLE (__cdecl *MLINITSKINNEDPOPUPHOOK)(HWND /*hwnd*/, HMLIMGLST /*hmlil*/, INT /*width*/, UINT /*skinStyle*/,
  19. MENUCUSTOMIZEPROC /*customProc*/, ULONG_PTR /*customParam*/);
  20. typedef HANDLE (__cdecl *MLREMOVESKINNEDPOPUPHOOK)(HANDLE /*hPopupHook*/);
  21. #if 0
  22. static BOOL Menu_IsRatingStar(HMENU hMenu, INT itemId, INT *valueOut)
  23. {
  24. WCHAR szBuffer[8] = {0};
  25. INT cchBuffer = GetMenuStringW(hMenu, itemId, szBuffer, ARRAYSIZE(szBuffer), MF_BYCOMMAND);
  26. if (cchBuffer < 1 || cchBuffer > 5)
  27. return FALSE;
  28. for (INT i = 1; i < cchBuffer; i++)
  29. {
  30. if (szBuffer[i -1] != szBuffer[i])
  31. return FALSE;
  32. }
  33. if (NULL != valueOut)
  34. *valueOut = cchBuffer;
  35. return TRUE;
  36. }
  37. static BOOL Menu_MeasureRating(HMENU hMenu, HDC hdc, MEASUREITEMSTRUCT *pmis)
  38. {
  39. if (NULL == hdc || !Menu_IsRatingStar(hMenu, pmis->itemID, NULL))
  40. return FALSE;
  41. RECT rect;
  42. if (!MLRating_CalcRect(Plugin_GetLibrary(), NULL, 5, &rect))
  43. return FALSE;
  44. pmis->itemHeight = rect.bottom - rect.top + 6;
  45. TEXTMETRIC tm;
  46. if (GetTextMetrics(hdc, &tm) &&
  47. (UINT)(tm.tmHeight + 2) > pmis->itemHeight)
  48. {
  49. pmis->itemHeight = tm.tmHeight + 2;
  50. }
  51. INT spaceCX = (pmis->itemHeight > RATING_MINSPACECX) ? pmis->itemHeight : RATING_MINSPACECX;
  52. pmis->itemWidth = rect.right - rect.left + (2 * spaceCX) - (GetSystemMetrics(SM_CXMENUCHECK) - 1);
  53. return TRUE;
  54. }
  55. static BOOL Menu_DrawRating(HMENU hMenu, HDC hdc, DRAWITEMSTRUCT *pdis)
  56. {
  57. INT ratingValue;
  58. if (NULL == hdc || !Menu_IsRatingStar(hMenu, pdis->itemID, &ratingValue))
  59. return FALSE;
  60. INT spaceCX = ((pdis->rcItem.bottom - pdis->rcItem.top) > RATING_MINSPACECX) ?
  61. (pdis->rcItem.bottom - pdis->rcItem.top) :
  62. RATING_MINSPACECX;
  63. RATINGDRAWPARAMS rdp = {0};
  64. rdp.cbSize = sizeof(RATINGDRAWPARAMS);
  65. rdp.hdcDst = hdc;
  66. rdp.rc = pdis->rcItem;
  67. rdp.rc.left += spaceCX;
  68. rdp.value = ratingValue;
  69. rdp.maxValue = 5;
  70. UINT menuState = GetMenuState(hMenu, pdis->itemID, MF_BYCOMMAND);
  71. rdp.trackingValue = (0 == ((MF_DISABLED | MF_GRAYED) & menuState)) ? rdp.value : 0;
  72. rdp.fStyle = RDS_LEFT | RDS_VCENTER | RDS_HOT;
  73. rdp.hMLIL = NULL;
  74. rdp.index = 0;
  75. return MLRating_Draw(Plugin_GetLibrary(), &rdp);
  76. }
  77. static BOOL CALLBACK Menu_CustomDrawProc(INT action, HMENU hMenu, HDC hdc, LPARAM param, ULONG_PTR user)
  78. {
  79. switch(action)
  80. {
  81. case MLMENU_ACTION_MEASUREITEM:
  82. if (hMenu == (HMENU)user)
  83. return Menu_MeasureRating(hMenu, hdc, (MEASUREITEMSTRUCT*)param);
  84. break;
  85. case MLMENU_ACTION_DRAWITEM:
  86. if (hMenu == (HMENU)user)
  87. return MLMENU_WANT_DRAWPART;
  88. break;
  89. case MLMENU_ACTION_DRAWBACK:
  90. break;
  91. case MLMENU_ACTION_DRAWICON:
  92. break;
  93. case MLMENU_ACTION_DRAWTEXT:
  94. if (hMenu == (HMENU)user)
  95. return Menu_DrawRating(hMenu, hdc, (DRAWITEMSTRUCT*)param);
  96. break;
  97. }
  98. return FALSE;
  99. }
  100. #endif
  101. BOOL Menu_SetRatingValue(HMENU ratingMenu, INT ratingValue)
  102. {
  103. if (NULL == ratingMenu) return FALSE;
  104. INT ratingList[] = { ID_RATING_VALUE_1, ID_RATING_VALUE_2, ID_RATING_VALUE_3,
  105. ID_RATING_VALUE_4, ID_RATING_VALUE_5};
  106. ratingValue--;
  107. MENUITEMINFO mii = {0};
  108. mii.cbSize = sizeof(MENUITEMINFO);
  109. UINT type, state;
  110. for (INT i = 0; i < ARRAYSIZE(ratingList); i++)
  111. {
  112. mii.fMask = MIIM_STATE | MIIM_FTYPE;
  113. if (GetMenuItemInfo(ratingMenu, ratingList[i], FALSE, &mii))
  114. {
  115. if (ratingValue == i)
  116. {
  117. type = mii.fType | MFT_RADIOCHECK;
  118. state = mii.fState | MFS_CHECKED;
  119. }
  120. else
  121. {
  122. type = mii.fType & ~MFT_RADIOCHECK;
  123. state = mii.fState & ~MFS_CHECKED;
  124. }
  125. mii.fMask = 0;
  126. if (type != mii.fType)
  127. {
  128. mii.fType = type;
  129. mii.fMask |= MIIM_FTYPE;
  130. }
  131. if (state != mii.fState)
  132. {
  133. mii.fState = state;
  134. mii.fMask |= MIIM_STATE;
  135. }
  136. if (0 != mii.fMask)
  137. SetMenuItemInfo(ratingMenu, ratingList[i], FALSE, &mii);
  138. }
  139. }
  140. return TRUE;
  141. }
  142. static HMENU Menu_FindRatingMenuRecur(HMENU hMenu, MENUINFO *pmi, MENUITEMINFO *pmii)
  143. {
  144. if (GetMenuInfo(hMenu, pmi) && RATING_MARKER == pmi->dwMenuData)
  145. return hMenu;
  146. INT count = GetMenuItemCount(hMenu);
  147. for(INT i = 0; i < count; i++)
  148. {
  149. if (GetMenuItemInfo(hMenu, i, TRUE, pmii) && NULL != pmii->hSubMenu)
  150. {
  151. HMENU hRating = Menu_FindRatingMenuRecur(pmii->hSubMenu, pmi, pmii);
  152. if (NULL != hRating)
  153. return hRating;
  154. }
  155. }
  156. return NULL;
  157. }
  158. HMENU Menu_FindRatingMenu(HMENU hMenu)
  159. {
  160. if (NULL == hMenu)
  161. return NULL;
  162. MENUITEMINFO mii;
  163. mii.cbSize = sizeof(MENUITEMINFO);
  164. mii.fMask = MIIM_SUBMENU;
  165. MENUINFO mi;
  166. mi.cbSize = sizeof(MENUINFO);
  167. mi.fMask = MIM_MENUDATA;
  168. return Menu_FindRatingMenuRecur(hMenu, &mi, &mii);
  169. }
  170. static BOOL Menu_InsertRatingMenu(HMENU hDest, INT iPos, HMENU baseMenu, INT ratingValue)
  171. {
  172. if ( 0 == MenuHelper_CopyMenuEx(hDest, iPos, baseMenu, MENU_RATING, 1))
  173. return FALSE;
  174. MENUITEMINFO mii = {0};
  175. mii.cbSize = sizeof(MENUITEMINFO);
  176. mii.fMask = MIIM_SUBMENU;
  177. if (GetMenuItemInfo(hDest, iPos, TRUE, &mii))
  178. {
  179. if (NULL != mii.hSubMenu)
  180. {
  181. MENUINFO mi = {0};
  182. mi.cbSize = sizeof(MENUINFO);
  183. mi.fMask = MIM_MENUDATA;
  184. mi.dwMenuData = RATING_MARKER;
  185. SetMenuInfo(mii.hSubMenu, &mi);
  186. Menu_SetRatingValue(mii.hSubMenu, ratingValue);
  187. }
  188. }
  189. return TRUE;
  190. }
  191. static HMENU Menu_CreateRatingMenu(HMENU baseMenu, INT ratingValue)
  192. {
  193. HMENU menu = GetSubMenu(baseMenu, MENU_RATING);
  194. if (NULL == menu) return NULL;
  195. menu = MenuHelper_DuplcateMenu(menu);
  196. if (NULL == menu) return NULL;
  197. MENUINFO mi = {0};
  198. mi.cbSize = sizeof(MENUINFO);
  199. mi.fMask = MIM_MENUDATA;
  200. mi.dwMenuData = RATING_MARKER;
  201. SetMenuInfo(menu, &mi);
  202. Menu_SetRatingValue(menu, ratingValue);
  203. return menu;
  204. }
  205. static HMENU Menu_GetServiceContext(HMENU baseMenu, UINT flags, BOOL fGaleryMode)
  206. {
  207. HMENU menu = GetSubMenu(baseMenu, (FALSE == fGaleryMode) ? MENU_SERVICECONTEXT : MENU_GALERYCONTEXT);
  208. if (NULL == menu) return NULL;
  209. menu = MenuHelper_DuplcateMenu(menu);
  210. if (NULL == menu) return NULL;
  211. HMENU embedMenu;
  212. INT inserted;
  213. INT total = GetMenuItemCount(menu);
  214. if (FALSE == fGaleryMode)
  215. {
  216. // rating
  217. if (Menu_InsertRatingMenu(menu, 0, baseMenu, RATINGFROMMCF(flags)))
  218. total++;
  219. }
  220. if (0 != (MCF_NAVIGATION & flags))
  221. {// navigation
  222. embedMenu = GetSubMenu(baseMenu, MENU_NAVIGATION);
  223. if (NULL != embedMenu)
  224. {
  225. inserted = MenuHelper_CopyMenu(menu, 0, embedMenu);
  226. if (inserted > 0 && total > 0 && MenuHelper_InsertSeparator(menu, inserted))
  227. inserted++;
  228. total += inserted;
  229. }
  230. }
  231. if (0 != (MCF_VIEW & flags))
  232. {// view
  233. embedMenu = GetSubMenu(baseMenu, MENU_VIEW);
  234. if (NULL != embedMenu)
  235. {
  236. inserted = MenuHelper_CopyMenu(menu, 0, embedMenu);
  237. if (inserted > 0 && total > 0 && MenuHelper_InsertSeparator(menu, inserted))
  238. {
  239. inserted++;
  240. }
  241. total += inserted;
  242. }
  243. EnableMenuItem(menu, ID_VIEW_OPEN , MF_BYCOMMAND | ((0 == (MCF_VIEWACTIVE & flags)) ? MF_ENABLED : MF_DISABLED));
  244. if ( 0 == (MCF_VIEWACTIVE & flags))
  245. SetMenuDefaultItem(menu, ID_VIEW_OPEN, FALSE);
  246. }
  247. return menu;
  248. }
  249. static HMENU Menu_GetToolbarContext(HMENU baseMenu, UINT flags)
  250. {
  251. HMENU hMenu = GetSubMenu(baseMenu, MENU_TOOLBAR);
  252. return hMenu;
  253. }
  254. void Menu_ConvertRatingMenuStar(HMENU menu, UINT menu_id)
  255. {
  256. MENUITEMINFOW mi = {sizeof(mi), MIIM_DATA | MIIM_TYPE, MFT_STRING};
  257. wchar_t rateBuf[32], *rateStr = rateBuf;
  258. mi.dwTypeData = rateBuf;
  259. mi.cch = 32;
  260. if(GetMenuItemInfoW(menu, menu_id, FALSE, &mi))
  261. {
  262. while(rateStr && *rateStr)
  263. {
  264. if(*rateStr == L'*') *rateStr = L'\u2605';
  265. rateStr=CharNextW(rateStr);
  266. }
  267. SetMenuItemInfoW(menu, menu_id, FALSE, &mi);
  268. }
  269. }
  270. HMENU Menu_GetMenu(INT menuKind, UINT flags)
  271. {
  272. HMENU baseMenu = WASABI_API_LOADMENUW(IDR_CONTEXTMENU);
  273. if (NULL == baseMenu)
  274. return NULL;
  275. HMENU rate_hmenu = GetSubMenu(baseMenu,2);
  276. Menu_ConvertRatingMenuStar(rate_hmenu, ID_RATING_VALUE_5);
  277. Menu_ConvertRatingMenuStar(rate_hmenu, ID_RATING_VALUE_4);
  278. Menu_ConvertRatingMenuStar(rate_hmenu, ID_RATING_VALUE_3);
  279. Menu_ConvertRatingMenuStar(rate_hmenu, ID_RATING_VALUE_2);
  280. Menu_ConvertRatingMenuStar(rate_hmenu, ID_RATING_VALUE_1);
  281. switch(menuKind)
  282. {
  283. case OMMENU_SERVICECONTEXT:
  284. case OMMENU_GALERYCONTEXT:
  285. return Menu_GetServiceContext(baseMenu, flags, (OMMENU_GALERYCONTEXT == menuKind));
  286. case OMMENU_RATING:
  287. return Menu_CreateRatingMenu(baseMenu, RATINGFROMMCF(flags));
  288. case OMMENU_TOOLBAR:
  289. return Menu_GetToolbarContext(baseMenu, flags);
  290. }
  291. return NULL;
  292. }
  293. void Menu_ReleaseMenu(HMENU hMenu, INT menuKind)
  294. {
  295. if (NULL == hMenu)
  296. return;
  297. switch(menuKind)
  298. {
  299. case OMMENU_SERVICECONTEXT:
  300. DestroyMenu(hMenu);
  301. break;
  302. case OMMENU_GALERYCONTEXT:
  303. DestroyMenu(hMenu);
  304. break;
  305. case OMMENU_RATING:
  306. DestroyMenu(hMenu);
  307. break;
  308. case OMMENU_TOOLBAR:
  309. break;
  310. }
  311. }
  312. INT DoTrackPopup(HMENU hMenu, UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm)
  313. {
  314. if (NULL == hMenu)
  315. return NULL;
  316. return Menu_TrackPopupParam(Plugin_GetLibrary(), hMenu, fuFlags, x, y,
  317. hwnd, lptpm, (ULONG_PTR)Menu_FindRatingMenu(hMenu));
  318. }