travelLogHelper.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include "main.h"
  2. #include "./travelLogHelper.h"
  3. #include "./graphics.h"
  4. #include "./resource.h"
  5. #include "./ifc_skinhelper.h"
  6. #include "./ifc_imageloader.h"
  7. #include "./menu.h"
  8. #include "../Plugins/General/gen_ml/ml_ipc_0313.h"
  9. #include <exdisp.h>
  10. #include <tlogstg.h>
  11. #define TRAVELLOGPOPUP_MAXCHARWIDTH 42
  12. TravelLogHelper::TravelLogHelper(IWebBrowser2 *pWeb)
  13. : ref(1), pWeb2(pWeb), bitmap(NULL), pixelData(NULL), firstFwd(FALSE), entriesCount(0), backEntry(-1)
  14. {
  15. if (NULL != pWeb2)
  16. pWeb2->AddRef();
  17. }
  18. TravelLogHelper::~TravelLogHelper()
  19. {
  20. if (NULL != pWeb2)
  21. pWeb2->Release();
  22. if (NULL != bitmap)
  23. DeleteObject(bitmap);
  24. }
  25. HRESULT TravelLogHelper::CreateInstance(IWebBrowser2 *pWeb2, TravelLogHelper **instance)
  26. {
  27. if (NULL == instance) return E_POINTER;
  28. *instance = NULL;
  29. if (NULL == pWeb2)
  30. return E_INVALIDARG;
  31. *instance = new TravelLogHelper(pWeb2);
  32. if (NULL == *instance) return E_OUTOFMEMORY;
  33. return S_OK;
  34. }
  35. size_t TravelLogHelper::AddRef()
  36. {
  37. return InterlockedIncrement((LONG*)&ref);
  38. }
  39. size_t TravelLogHelper::Release()
  40. {
  41. if (0 == ref)
  42. return ref;
  43. LONG r = InterlockedDecrement((LONG*)&ref);
  44. if (0 == r)
  45. delete(this);
  46. return r;
  47. }
  48. int TravelLogHelper::QueryInterface(GUID interface_guid, void **object)
  49. {
  50. if (NULL == object) return E_POINTER;
  51. if (IsEqualIID(interface_guid, IFC_TravelLogHelper))
  52. *object = static_cast<ifc_travelloghelper*>(this);
  53. else if (IsEqualIID(interface_guid, IFC_MenuCustomizer))
  54. *object = static_cast<ifc_menucustomizer*>(this);
  55. else
  56. {
  57. *object = NULL;
  58. return E_NOINTERFACE;
  59. }
  60. if (NULL == *object)
  61. return E_UNEXPECTED;
  62. AddRef();
  63. return S_OK;
  64. }
  65. HRESULT TravelLogHelper::QueryStorage(ITravelLogStg **ppLog)
  66. {
  67. HRESULT hr;
  68. if (NULL == ppLog)
  69. return E_POINTER;
  70. *ppLog = NULL;
  71. if (NULL == pWeb2) return E_UNEXPECTED;
  72. IServiceProvider *pProvider;
  73. hr = pWeb2->QueryInterface(IID_IServiceProvider, (void**)&pProvider);
  74. if (SUCCEEDED(hr))
  75. {
  76. hr = pProvider->QueryService(SID_STravelLogCursor, ppLog);
  77. pProvider->Release();
  78. }
  79. return hr;
  80. }
  81. BOOL TravelLogHelper::DrawIcon(HMENU menuInstance, HDC hdc, DRAWITEMSTRUCT *pdis)
  82. {
  83. if (0 == (ODS_SELECTED & pdis->itemState))
  84. return FALSE;
  85. LONG entry = pdis->itemID - 101;
  86. if (entry < 0 || ((ULONG)entry) > entriesCount)
  87. return FALSE;
  88. BOOL fForward = (FALSE != firstFwd) ? TRUE : FALSE;
  89. if (-1 != backEntry && entry >= backEntry)
  90. fForward = !fForward;
  91. if (NULL == bitmap)
  92. {
  93. ifc_omimageloader *imageLoader;
  94. if (SUCCEEDED(Plugin_QueryImageLoader(Plugin_GetInstance(), MAKEINTRESOURCE(IDR_MENUARROW_IMAGE), FALSE, &imageLoader)))
  95. {
  96. if (SUCCEEDED(imageLoader->LoadBitmapEx(&bitmap, &header, &pixelData)))
  97. {
  98. if (header.biHeight < 0) header.biHeight = -header.biHeight;
  99. Image_Colorize((BYTE*)pixelData, header.biWidth, header.biHeight,
  100. header.biBitCount, GetBkColor(hdc), GetTextColor(hdc), TRUE);
  101. }
  102. imageLoader->Release();
  103. }
  104. }
  105. BOOL resultOk = FALSE;
  106. if (NULL != bitmap)
  107. {
  108. INT cx = header.biWidth/2;
  109. INT cy = header.biHeight;
  110. if (cy < 0) cy = -cy;
  111. INT side = (pdis->rcItem.bottom - pdis->rcItem.top - 2);
  112. if (cy < side) side = cy;
  113. INT top = pdis->rcItem.top + ((pdis->rcItem.bottom - pdis->rcItem.top) - side)/2;
  114. INT left = pdis->rcItem.left + (GetSystemMetrics(SM_CXMENUCHECK) - side)/2 + 3;
  115. resultOk = StretchDIBits(hdc, left, top, side, side,
  116. ((FALSE != fForward) ? cx : 0), 0, cx, cy, pixelData, (BITMAPINFO*)&header, DIB_RGB_COLORS, SRCCOPY);
  117. }
  118. return resultOk;
  119. }
  120. INT TravelLogHelper::CustomDraw(HMENU menuInstance, INT action, HDC hdc, LPARAM param)
  121. {
  122. switch(action)
  123. {
  124. case MLMENU_ACTION_DRAWITEM:
  125. return MLMENU_WANT_DRAWPART;
  126. case MLMENU_ACTION_DRAWICON:
  127. return DrawIcon(menuInstance, hdc, (DRAWITEMSTRUCT*)param);
  128. }
  129. return FALSE;
  130. }
  131. HRESULT TravelLogHelper::ShowPopup(UINT fuFlags, INT x, INT y, HWND hwnd, LPTPMPARAMS lptpm)
  132. {
  133. HRESULT hr;
  134. ITravelLogStg *pLog;
  135. hr = QueryStorage(&pLog);
  136. if (FAILED(hr) || NULL == pLog) return hr;
  137. DWORD entriesMax;
  138. if (FAILED(pLog->GetCount(TLEF_RELATIVE_FORE | TLEF_RELATIVE_BACK, &entriesMax)))
  139. entriesMax = 0;
  140. ITravelLogEntry **entries = NULL;
  141. INT selectedEntry = -1;
  142. firstFwd = (0 == (TPM_BOTTOMALIGN & fuFlags));
  143. entriesCount = 0;
  144. backEntry = -1;
  145. if (0 != entriesMax)
  146. {
  147. entries = (ITravelLogEntry**)calloc(entriesMax, sizeof(ITravelLogEntry*));
  148. if (NULL != entries)
  149. {
  150. IEnumTravelLogEntry *pEnum = NULL;
  151. TLENUMF tlenum = (0 != (TPM_BOTTOMALIGN & fuFlags)) ? TLEF_RELATIVE_BACK : TLEF_RELATIVE_FORE;
  152. if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum)))
  153. {
  154. ULONG fetched;
  155. pEnum->Reset();
  156. pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched);
  157. if (0 != fetched)
  158. {
  159. ITravelLogEntry *t, **l, **r;
  160. for (l = &entries[entriesCount], r = &entries[entriesCount + fetched - 1]; l < r; l++, r--)
  161. {
  162. t = *l;
  163. *l = *r;
  164. *r = t;
  165. }
  166. entriesCount += fetched;
  167. }
  168. pEnum->Release();
  169. }
  170. tlenum = (0 != (TLEF_RELATIVE_FORE & tlenum)) ?
  171. ((tlenum & ~TLEF_RELATIVE_FORE) | TLEF_RELATIVE_BACK) :
  172. tlenum = ((tlenum & ~TLEF_RELATIVE_BACK) | TLEF_RELATIVE_FORE);
  173. if (SUCCEEDED(pLog->EnumEntries(tlenum, &pEnum)))
  174. {
  175. ULONG fetched;
  176. pEnum->Reset();
  177. pEnum->Next(entriesMax - entriesCount, &entries[entriesCount], &fetched);
  178. if (0 != fetched)
  179. {
  180. backEntry = entriesCount;
  181. entriesCount += fetched;
  182. }
  183. pEnum->Release();
  184. }
  185. }
  186. if (entriesCount > 0)
  187. {
  188. HMENU hMenu = CreatePopupMenu();
  189. if (NULL != hMenu)
  190. {
  191. MENUITEMINFOW mii = {0};
  192. mii.cbSize = sizeof(MENUITEMINFOW);
  193. mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE;
  194. mii.fState = MFS_ENABLED | MFS_UNCHECKED;
  195. for (ULONG i = 0; i < entriesCount; i++)
  196. {
  197. if (NULL != entries[i])
  198. {
  199. LPWSTR pszTitle;
  200. if (SUCCEEDED(entries[i]->GetTitle(&pszTitle)) && NULL != pszTitle)
  201. {
  202. INT cchTitle = lstrlen(pszTitle);
  203. if (cchTitle > TRAVELLOGPOPUP_MAXCHARWIDTH)
  204. {
  205. pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH] = L'\0';
  206. for (INT k = 0; k < 3; k++)
  207. pszTitle[TRAVELLOGPOPUP_MAXCHARWIDTH - 1 - k] = L'.';
  208. }
  209. mii.dwTypeData = pszTitle;
  210. mii.wID = 101 + i;
  211. InsertMenuItem(hMenu, i, TRUE, &mii);
  212. CoTaskMemFree(pszTitle);
  213. }
  214. }
  215. }
  216. { // insert current page
  217. WCHAR szBuffer[256] = {0};
  218. Plugin_LoadString(IDS_CURRENT_PAGE, szBuffer, ARRAYSIZE(szBuffer));
  219. mii.dwTypeData = szBuffer;
  220. mii.fMask = MIIM_STRING | MIIM_ID | MIIM_STATE | MIIM_FTYPE;
  221. mii.fState = MFS_ENABLED | MFS_DEFAULT | MFS_CHECKED;
  222. mii.fType = MFT_STRING | MFT_RADIOCHECK;
  223. mii.wID = 100;
  224. if (-1 == backEntry)
  225. InsertMenuItem(hMenu, GetMenuItemCount(hMenu), TRUE, &mii);
  226. else
  227. InsertMenuItem(hMenu, 101 + backEntry, FALSE, &mii);
  228. }
  229. HANDLE hHook = Menu_InitializeHook(hwnd, this);
  230. UINT commandId = TrackPopupMenuEx(hMenu, fuFlags | TPM_RETURNCMD, x, y, hwnd, lptpm);
  231. if (NULL != hHook) Menu_RemoveHook(hHook);
  232. if (commandId > 100 && commandId <= (100 + entriesCount))
  233. selectedEntry = commandId - 101;
  234. DestroyMenu(hMenu);
  235. }
  236. }
  237. }
  238. if (-1 != selectedEntry && NULL != entries[selectedEntry])
  239. {
  240. pLog->TravelTo(entries[selectedEntry]);
  241. }
  242. if (NULL != entries)
  243. {
  244. for (ULONG i = 0; i < entriesCount; i++)
  245. {
  246. if (NULL != entries[i]) entries[i]->Release();
  247. }
  248. free(entries);
  249. }
  250. pLog->Release();
  251. return hr;
  252. }
  253. #define CBCLASS TravelLogHelper
  254. START_MULTIPATCH;
  255. START_PATCH(MPIID_TRAVELLOGHELPER)
  256. M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, ADDREF, AddRef);
  257. M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, RELEASE, Release);
  258. M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, QUERYINTERFACE, QueryInterface);
  259. M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_QUERYSTORAGE, QueryStorage);
  260. M_CB(MPIID_TRAVELLOGHELPER, ifc_travelloghelper, API_SHOWPOPUP, ShowPopup);
  261. NEXT_PATCH(MPIID_MENUCUSTOMIZER)
  262. M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, ADDREF, AddRef);
  263. M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, RELEASE, Release);
  264. M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, QUERYINTERFACE, QueryInterface);
  265. M_CB(MPIID_MENUCUSTOMIZER, ifc_menucustomizer, API_CUSTOMDRAW, CustomDraw);
  266. END_PATCH
  267. END_MULTIPATCH;
  268. #undef CBCLASS