1
0

menuv5.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. /** (c) Nullsoft, Inc. C O N F I D E N T I A L
  2. ** Filename:
  3. ** Project:
  4. ** Description:
  5. ** Author:
  6. ** Created:
  7. **/
  8. #include "main.h"
  9. #include "menuv5.h"
  10. #include "../nu/AutoWide.h"
  11. #include "../Plugins/General/gen_ml/ml.h"
  12. #define TREE_LOCALMEDIA 1000
  13. #define TREE_PLAYLISTS 3001
  14. #define TREE_DEVICES 10000
  15. #define TREE_QUERIES 1000
  16. extern HINSTANCE language_pack_instance;
  17. void ensureInScreen(HMENU menu, int *x, int *y, int *flag, int width, int height);
  18. HMENU v5_top_menu = NULL;
  19. int MergeMenu(HMENU pMenuDestination, const HMENU pMenuAdd, int bTopLevel /*=false*/)
  20. {
  21. // Abstract:
  22. // Merges two menus.
  23. //
  24. // Parameters:
  25. // pMenuDestination - [in, retval] destination menu handle
  26. // pMenuAdd - [in] menu to merge
  27. // bTopLevel - [in] indicator for special top level behavior
  28. //
  29. // Return value:
  30. // <false> in case of error.
  31. //
  32. // Comments:
  33. // This function calles itself recursivley. If bTopLevel is set to true,
  34. // we append popups at top level or we insert before <Window> or <Help>.
  35. // get the number menu items in the menus
  36. int iMenuAddItemCount = GetMenuItemCount(pMenuAdd);
  37. int iMenuDestItemCount = GetMenuItemCount(pMenuDestination);
  38. int iLoop;
  39. // if there are no items return
  40. if( iMenuAddItemCount == 0 )
  41. return 1;
  42. // if we are not at top level and the destination menu is not empty
  43. // -> we append a seperator
  44. if( !bTopLevel && iMenuDestItemCount > 0 )
  45. AppendMenu(pMenuDestination, MF_SEPARATOR, 0, 0);
  46. // iterate through the top level of
  47. for( iLoop = 0; iLoop < iMenuAddItemCount; iLoop++ )
  48. {
  49. HMENU pSubMenu = 0;
  50. // get the menu string from the add menu
  51. wchar_t sMenuAddString[1024] = {0}; // hope it's enough
  52. GetMenuStringW(pMenuAdd, iLoop, sMenuAddString, 1024, MF_BYPOSITION);
  53. // try to get the submenu of the current menu item
  54. pSubMenu =GetSubMenu(pMenuAdd, iLoop);
  55. // check if we have a sub menu
  56. if (!pSubMenu)
  57. {
  58. // normal menu item
  59. // read the source and append at the destination
  60. UINT nState = GetMenuState(pMenuAdd, iLoop, MF_BYPOSITION);
  61. UINT nItemID = GetMenuItemID(pMenuAdd, iLoop);
  62. if(AppendMenuW(pMenuDestination, nState, nItemID, sMenuAddString))
  63. {
  64. // menu item added, don't forget to correct the item count
  65. iMenuDestItemCount++;
  66. }
  67. else
  68. {
  69. // MergeMenu: AppendMenu failed!
  70. return 0;
  71. }
  72. }
  73. else
  74. {
  75. HMENU NewPopupMenu=NULL;
  76. // create or insert a new popup menu item
  77. // default insert pos is like ap
  78. int iInsertPosDefault = -1;
  79. // if we are at top level merge into existing popups rather than
  80. // creating new ones
  81. if( bTopLevel )
  82. {
  83. //ASSERT( sMenuAddString != "&?" && sMenuAddString != "?" );
  84. //CString sAdd( sMenuAddString );
  85. //sAdd.Remove('&'); // for comparison of menu items supress '&'
  86. int bAdded = 0;
  87. int iLoop1=0;
  88. // try to find existing popup
  89. for( iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ )
  90. {
  91. // get the menu string from the destination menu
  92. wchar_t sDest[1024] = {0}; // hope it's enough
  93. GetMenuStringW(pMenuDestination, iLoop1, sDest, 1024, MF_BYPOSITION );
  94. //sDest.Remove( '&' ); // for a better compare (s.a.)
  95. //if( !lstrcmp(sAdd,sDest))
  96. {
  97. // we got a hit -> merge the two popups
  98. // try to get the submenu of the desired destination menu item
  99. HMENU pSubMenuDest = GetSubMenu(pMenuDestination, iLoop1 );
  100. if( pSubMenuDest )
  101. {
  102. // merge the popup recursivly and continue with outer for loop
  103. if( !MergeMenu( pSubMenuDest, pSubMenu, 0 ))
  104. return 0;
  105. bAdded = 1;
  106. break;
  107. }
  108. }
  109. // alternativ insert before <Window> or <Help>
  110. //if( iInsertPosDefault == -1 && ( sDest == "Window" || sDest == "?" || sDest == "Help" ))
  111. // iInsertPosDefault = iLoop1;
  112. }
  113. if( bAdded )
  114. {
  115. // menu added, so go on with loop over pMenuAdd's top level
  116. continue;
  117. }
  118. }
  119. // if the top level search did not find a position append the menu
  120. if( iInsertPosDefault == -1 )
  121. iInsertPosDefault = GetMenuItemCount(pMenuDestination);
  122. // create a new popup and insert before <Window> or <Help>
  123. NewPopupMenu = CreatePopupMenu();
  124. if( !NewPopupMenu)
  125. {
  126. // MergeMenu: CreatePopupMenu failed!
  127. return 0;
  128. }
  129. // merge the new popup recursivly
  130. if( !MergeMenu( NewPopupMenu, pSubMenu, 0 ))
  131. return 0;
  132. // insert the new popup menu into the destination menu
  133. HMENU hNewMenu = NewPopupMenu;
  134. {
  135. MENUITEMINFOW menuItem={sizeof(MENUITEMINFO),
  136. MIIM_TYPE|MIIM_SUBMENU,
  137. MFT_STRING,
  138. MFS_ENABLED,
  139. 0, //wID
  140. hNewMenu, // hSubMenu
  141. NULL, // hbmpChecked
  142. NULL, // hbmpUnchecked
  143. 0, // dwItemData
  144. sMenuAddString, // dwTypeData
  145. 0, // cch
  146. };
  147. if (InsertMenuItemW(pMenuDestination, iInsertPosDefault, TRUE, &menuItem))
  148. {
  149. // don't forget to correct the item count
  150. iMenuDestItemCount++;
  151. }
  152. else
  153. {
  154. // MergeMenu: InsertMenu failed!
  155. return 0;
  156. }
  157. }
  158. }
  159. }
  160. return 1;
  161. }
  162. int getMenuItemPos(HMENU menu, UINT command)
  163. {
  164. int i;
  165. for (i = 0;i < 256;i++)
  166. {
  167. MENUITEMINFO mii = {sizeof(mii), MIIM_ID, };
  168. if (!GetMenuItemInfo(menu, i, TRUE, &mii)) break;
  169. if (mii.wID == command) return i;
  170. }
  171. return -1;
  172. }
  173. extern int g_SkinTop, g_BookmarkTop;
  174. int V5_File_Menu(HWND hwnd, int x, int y, int width, int height)
  175. {
  176. int flag = TPM_LEFTALIGN;
  177. HMENU file_menu = GetSubMenu(v5_top_menu, 0);
  178. HMENU hMenu = GetSubMenu(file_menu, 3);
  179. MENUITEMINFOW i = {sizeof(i), };
  180. FILE *fp;
  181. int a = 34768;
  182. int offs = 3;
  183. int count = GetMenuItemCount(hMenu) + 1;
  184. i.fMask = MIIM_TYPE | MIIM_DATA | MIIM_ID;
  185. i.fType = MFT_STRING;
  186. i.wID = 34768;
  187. // remove all of the items we might have added - do by command for certainty
  188. while (count){
  189. if(!RemoveMenu(hMenu, a++, MF_BYCOMMAND)) break;
  190. count--;
  191. }
  192. fp = _wfopen(BOOKMARKFILE8, L"rt");
  193. if (fp)
  194. {
  195. while (1)
  196. {
  197. char ft[FILETITLE_SIZE] = {0}, fn[FILENAME_SIZE] = {0};
  198. fgets(fn, FILENAME_SIZE, fp);
  199. if (feof(fp)) break;
  200. fgets(ft, FILETITLE_SIZE, fp);
  201. if (feof(fp)) break;
  202. if (ft[0] && fn[0])
  203. {
  204. if (fn[lstrlenA(fn) - 1] == '\n') fn[lstrlenA(fn) - 1] = 0;
  205. if (ft[lstrlenA(ft) - 1] == '\n') ft[lstrlenA(ft) - 1] = 0;
  206. if (ft[0] && fn[0])
  207. {
  208. i.dwTypeData = AutoWideDup(ft, CP_UTF8);
  209. i.cch = lstrlenW(i.dwTypeData);
  210. RemoveMenu(hMenu, i.wID, MF_BYCOMMAND);
  211. InsertMenuItemW(hMenu, i.wID + offs - 34768, TRUE, &i);
  212. i.wID++;
  213. }
  214. }
  215. }
  216. fclose(fp);
  217. }
  218. g_BookmarkTop = i.wID;
  219. // put in a place holder item if there were no read bookmarks
  220. if (g_BookmarkTop == 34768)
  221. {
  222. i.dwTypeData = getStringW(IDS_NO_BOOKMARKS,NULL,0);
  223. i.cch = lstrlenW(i.dwTypeData);
  224. InsertMenuItemW(hMenu, i.wID + offs - 34768, TRUE, &i);
  225. EnableMenuItem(hMenu, i.wID, MF_BYCOMMAND | MF_GRAYED);
  226. }
  227. ensureInScreen(file_menu, &x, &y, &flag, width, height);
  228. DoTrackPopup(file_menu, flag, x, y, hwnd);
  229. return 1;
  230. }
  231. int V5_Play_Menu(HWND hwnd, int x, int y, int width, int height)
  232. {
  233. HMENU play_menu = GetSubMenu(v5_top_menu, 1);
  234. int flag = TPM_LEFTALIGN;
  235. ensureInScreen(play_menu, &x, &y, &flag, width, height);
  236. DoTrackPopup(play_menu, flag, x, y, hwnd);
  237. return 1;
  238. }
  239. int V5_Options_Menu(HWND hwnd, int x, int y, int width, int height)
  240. {
  241. int flag = TPM_LEFTALIGN;
  242. HMENU options_menu = GetSubMenu(v5_top_menu, 2);
  243. HMENU eqMenu = NULL;
  244. { // set options skin menu to the skin menu
  245. extern HMENU g_submenus_skins1;
  246. MENUITEMINFO mi = {sizeof(mi), MIIM_SUBMENU};
  247. mi.hSubMenu = g_submenus_skins1;
  248. SetMenuItemInfoW(options_menu, 0, TRUE, &mi);
  249. }
  250. eqMenu = GetSubMenu(options_menu, 2);
  251. CheckMenuItem(eqMenu, EQ_ENABLE, config_use_eq ? MF_CHECKED : MF_UNCHECKED);
  252. CheckMenuItem(options_menu, WINAMP_OPTIONS_DSIZE, config_dsize ? MF_CHECKED : MF_UNCHECKED);
  253. CheckMenuItem(options_menu, WINAMP_OPTIONS_AOT, config_aot ? MF_CHECKED : MF_UNCHECKED);
  254. CheckMenuItem(options_menu, WINAMP_OPTIONS_ELAPSED, config_timeleftmode ? MF_UNCHECKED : MF_CHECKED);
  255. CheckMenuItem(options_menu, WINAMP_OPTIONS_REMAINING, config_timeleftmode ? MF_CHECKED : MF_UNCHECKED);
  256. CheckMenuItem(options_menu, WINAMP_OPTIONS_PREFS, IsWindow(prefs_hwnd) ? MF_CHECKED : MF_UNCHECKED);
  257. ensureInScreen(options_menu, &x, &y, &flag, width, height);
  258. DoTrackPopup(options_menu, flag, x, y, hwnd);
  259. return 1;
  260. }
  261. int V5_Windows_Menu(HWND hwnd, int x, int y, int width, int height)
  262. {
  263. HMENU windows_menu = GetSubMenu(v5_top_menu, 3);
  264. int flag = TPM_LEFTALIGN;
  265. CheckMenuItem(windows_menu, WINAMP_OPTIONS_PLEDIT, config_pe_open ? MF_CHECKED : MF_UNCHECKED);
  266. CheckMenuItem(windows_menu, WINAMP_VISPLUGIN, vis_running() ? MF_CHECKED : MF_UNCHECKED);
  267. if (g_has_video_plugin) CheckMenuItem(windows_menu, WINAMP_OPTIONS_VIDEO, config_video_open ? MF_CHECKED : MF_UNCHECKED);
  268. ensureInScreen(windows_menu, &x, &y, &flag, width, height);
  269. DoTrackPopup(windows_menu, flag, x, y, hwnd);
  270. return 1;
  271. }
  272. int Help_Menu(HWND hwnd, int x, int y, int width, int height)
  273. {
  274. HMENU help_menu = GetSubMenu(v5_top_menu, 4);
  275. int flag = TPM_LEFTALIGN;
  276. MENUITEMINFOW i = {sizeof(i), };
  277. i.fMask = MIIM_TYPE;
  278. i.fType = MFT_STRING;
  279. i.dwTypeData = getStringW(IDS_WINAMP_MENUITEM, NULL, 0);
  280. i.cch = (UINT)wcslen(i.dwTypeData);
  281. SetMenuItemInfoW(help_menu, WINAMP_HELP_ABOUT, FALSE, &i);
  282. ensureInScreen(help_menu, &x, &y, &flag, width, height);
  283. DoTrackPopup(help_menu, flag, x, y, hwnd);
  284. return 1;
  285. }
  286. int V5_Help_Menu(HWND hwnd, int x, int y, int width, int height)
  287. {
  288. return Help_Menu(hwnd, x, y, width, height);
  289. }
  290. LRESULT sendMlIpc(int msg, WPARAM param);
  291. // TODO:: need to make this only show what's needed at the time ie it'll still show even if there's no ml_playlists
  292. // and properly show if there's no playlists
  293. int V5_PE_File_Menu(HWND hwnd, int x, int y, int width, int height)
  294. {
  295. int flag = TPM_LEFTALIGN;
  296. HMENU pefile_menu = GetSubMenu(v5_top_menu, 5);
  297. HMENU playlistsmenu = NULL;
  298. HMENU viewmenu = NULL;
  299. HWND mlwnd = (HWND)sendMlIpc(0, 0);
  300. int viewmenu_added = 0;
  301. g_open_ml_item_in_pe = 1;
  302. if (mlwnd)
  303. {
  304. mlGetTreeStruct mgts = { TREE_PLAYLISTS, 45000, -1 };
  305. playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
  306. if (playlistsmenu)
  307. {
  308. mlGetTreeStruct mgts = { TREE_QUERIES, 45000, -1 };
  309. viewmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
  310. if (GetMenuItemCount(playlistsmenu) == 0) InsertMenuW(playlistsmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, getStringW(IDS_ML_NO_PLAYLISTS,NULL,0));
  311. InsertMenuW(pefile_menu, 2, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)playlistsmenu, getStringW(IDS_ML_OPEN_PLAYLIST,NULL,0));
  312. if (viewmenu && GetMenuItemCount(viewmenu) > 0)
  313. {
  314. viewmenu_added = 1;
  315. InsertMenuW(pefile_menu, 3, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)viewmenu, getStringW(IDS_ML_OPEN_VIEW_RESULTS,NULL,0));
  316. }
  317. }
  318. }
  319. ModifyMenuW(pefile_menu, ID_PE_CLOSE, MF_BYCOMMAND | MF_STRING, ID_PE_CLOSE, config_pe_open ? getStringW(IDS_PE_CLOSE,NULL,0) : getStringW(IDS_PE_OPEN,NULL,0));
  320. ensureInScreen(pefile_menu, &x, &y, &flag, width, height);
  321. DoTrackPopup(pefile_menu, flag, x, y, hwnd);
  322. if (playlistsmenu)
  323. {
  324. if (viewmenu_added) RemoveMenu(pefile_menu, 3, MF_BYPOSITION);
  325. if (viewmenu) DestroyMenu(viewmenu);
  326. RemoveMenu(pefile_menu, 2, MF_BYPOSITION);
  327. DestroyMenu(playlistsmenu);
  328. }
  329. return 1;
  330. }
  331. int V5_PE_Playlist_Menu(HWND hwnd, int x, int y, int width, int height)
  332. {
  333. HMENU peplaylist_menu = GetSubMenu(v5_top_menu, 6);
  334. int flag = TPM_LEFTALIGN;
  335. ensureInScreen(peplaylist_menu, &x, &y, &flag, width, height);
  336. DoTrackPopup(peplaylist_menu, flag, x, y, hwnd);
  337. return 1;
  338. }
  339. int V5_PE_Sort_Menu(HWND hwnd, int x, int y, int width, int height)
  340. {
  341. HMENU pesort_menu = GetSubMenu(v5_top_menu, 7);
  342. int flag = TPM_LEFTALIGN;
  343. ensureInScreen(pesort_menu, &x, &y, &flag, width, height);
  344. DoTrackPopup(pesort_menu, flag, x, y, hwnd);
  345. return 1;
  346. }
  347. int V5_PE_Help_Menu(HWND hwnd, int x, int y, int width, int height)
  348. {
  349. return Help_Menu(hwnd, x, y, width, height);
  350. }
  351. int V5_ML_File_Menu(HWND hwnd, int x, int y, int width, int height)
  352. {
  353. int flag = TPM_LEFTALIGN;
  354. HMENU mlfile_menu = GetSubMenu(v5_top_menu, 8);
  355. HWND mlwnd = (HWND)sendMlIpc(0, 0);
  356. HWND mlplwnd = (HWND)SendMessageW(mlwnd, WM_ML_IPC, 0, ML_IPC_GETPLAYLISTWND);
  357. ModifyMenuW(mlfile_menu, 3, MF_BYPOSITION | (mlplwnd == NULL ? MF_GRAYED : 0), ID_MLFILE_SAVEPLAYLIST, getStringW(IDS_ML_EXPORT_PLAYLIST,NULL,0));
  358. {
  359. int visible = IsWindowVisible(mlwnd);
  360. int p = getMenuItemPos(mlfile_menu, ID_FILE_CLOSELIBRARY);
  361. if (p == -1) p = getMenuItemPos(mlfile_menu, ID_FILE_SHOWLIBRARY);
  362. ModifyMenuW(mlfile_menu, p, MF_BYPOSITION | MF_STRING, visible ? ID_FILE_CLOSELIBRARY : ID_FILE_SHOWLIBRARY, visible ? getStringW(IDS_ML_CLOSE_ML,NULL,0) : getStringW(IDS_ML_OPEN_ML,NULL,0));
  363. }
  364. ensureInScreen(mlfile_menu, &x, &y, &flag, width, height);
  365. DoTrackPopup(mlfile_menu, flag, x, y, hwnd);
  366. return 1;
  367. }
  368. int V5_ML_View_Menu(HWND hwnd, int x, int y, int width, int height)
  369. {
  370. int flag = TPM_LEFTALIGN;
  371. HMENU mlview_menu = GetSubMenu(v5_top_menu, 9), mediamenu = NULL;
  372. HWND mlwnd = (HWND)sendMlIpc(0, 0);
  373. if (mlwnd)
  374. {
  375. mlGetTreeStruct mgts = { 0, 45000, -1 };
  376. mediamenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
  377. if (mediamenu)
  378. {
  379. MergeMenu(mediamenu, mlview_menu, 0);
  380. //InsertMenu(mediamenu, 0, MF_BYPOSITION | MF_STRING, ID_MLVIEW_MEDIA, "All &Media");
  381. //InsertMenu(mlview_menu, 1, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)mediamenu, "&Local Media");
  382. }/*
  383. mgts.item_start = TREE_PLAYLISTS;
  384. playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (int) & mgts, ML_IPC_GETTREE);
  385. if (playlistsmenu)
  386. {
  387. if (GetMenuItemCount(playlistsmenu) == 0) InsertMenu(playlistsmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, "No playlists");
  388. InsertMenu(mlview_menu, 2, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)playlistsmenu, "&Playlists");
  389. }
  390. mgts.item_start = TREE_DEVICES;
  391. devicesmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (int) & mgts, ML_IPC_GETTREE);
  392. if (devicesmenu)
  393. {
  394. if (GetMenuItemCount(devicesmenu) == 0) InsertMenu(devicesmenu, 0, MF_BYPOSITION | MF_STRING | MF_GRAYED, 0, "No devices");
  395. InsertMenu(mlview_menu, 3, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT)devicesmenu, "&Devices");
  396. }*/
  397. }
  398. g_open_ml_item_in_pe = 0;
  399. //ID_MLVIEW_PLAYLISTS
  400. //ID_MLVIEW_DEVICES
  401. ensureInScreen(mediamenu, &x, &y, &flag, width, height);
  402. DoTrackPopup(mediamenu, flag, x, y, hwnd);
  403. /*
  404. if (devicesmenu)
  405. {
  406. RemoveMenu(mlview_menu, 3, MF_BYPOSITION);
  407. DestroyMenu(devicesmenu);
  408. }
  409. if (playlistsmenu)
  410. {
  411. RemoveMenu(mlview_menu, 2, MF_BYPOSITION);
  412. DestroyMenu(playlistsmenu);
  413. }*/
  414. if (mediamenu)
  415. {
  416. //RemoveMenu(mlview_menu, 1, MF_BYPOSITION);
  417. DestroyMenu(mediamenu);
  418. }
  419. return 1;
  420. }
  421. int V5_ML_Help_Menu(HWND hwnd, int x, int y, int width, int height)
  422. {
  423. return Help_Menu(hwnd, x, y, width, height);
  424. }
  425. int V5_PE_ListOfPlaylists_Menu(int x, int y)
  426. {
  427. HMENU viewmenu = NULL;
  428. mlGetTreeStruct mgts = { TREE_PLAYLISTS, 55000, -1 };
  429. HWND mlwnd = (HWND)sendMlIpc(0, 0);
  430. HMENU playlistsmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) & mgts, ML_IPC_GETTREE);
  431. if (playlistsmenu)
  432. {
  433. InsertMenuW(playlistsmenu, 0, MF_BYPOSITION | MF_STRING, ID_MANAGEPLAYLISTS, getStringW(IDS_ML_MANAGE_PLAYLISTS,NULL,0));
  434. {
  435. mlGetTreeStruct mgts = { TREE_QUERIES, 55000, -1 };
  436. viewmenu = (HMENU)SendMessageW(mlwnd, WM_ML_IPC, (WPARAM) &mgts, ML_IPC_GETTREE);
  437. }
  438. if (viewmenu && GetMenuItemCount(viewmenu) > 0)
  439. InsertMenuW(playlistsmenu, 1, MF_BYPOSITION | MF_ENABLED | MF_POPUP, (UINT_PTR)viewmenu, getStringW(IDS_ML_SMART_VIEW_RESULTS,NULL,0));
  440. InsertMenu(playlistsmenu, 1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
  441. g_open_ml_item_in_pe = 1;
  442. DoTrackPopup(playlistsmenu, TPM_LEFTALIGN, x, y, hMainWindow);
  443. }
  444. DestroyMenu(playlistsmenu);
  445. DestroyMenu(viewmenu);
  446. return 1;
  447. }
  448. void getViewportFromPoint(POINT *pt, RECT *r)
  449. {
  450. if (!r || !pt) return ;
  451. {
  452. HMONITOR hm;
  453. hm = MonitorFromPoint(*pt, MONITOR_DEFAULTTONULL);
  454. if (hm)
  455. {
  456. MONITORINFOEXW mi;
  457. memset(&mi, 0, sizeof(mi));
  458. mi.cbSize = sizeof(mi);
  459. if (GetMonitorInfo(hm, &mi))
  460. {
  461. *r = mi.rcMonitor;
  462. return ;
  463. }
  464. }
  465. }
  466. }
  467. #undef GetSystemMetrics
  468. void ensureInScreen(HMENU menu, int *x, int *y, int *flag, int width, int height)
  469. {
  470. POINT pt = {*x, *y};
  471. int nitems = GetMenuItemCount(menu);
  472. int i;
  473. RECT mwr;
  474. RECT monitor;
  475. int rightdone = 0;
  476. int bottomdone = 0;
  477. int xedge = GetSystemMetrics(SM_CXEDGE);
  478. int yedge = GetSystemMetrics(SM_CYEDGE);
  479. int itemheight = GetSystemMetrics(SM_CYMENU);
  480. int checkmarkwidth = GetSystemMetrics(SM_CXMENUCHECK);
  481. int cury = *y + yedge + 1;
  482. GetWindowRect(hMainWindow, &mwr);
  483. getViewportFromPoint(&pt, &monitor);
  484. /*if (nitems*GetSystemMetrics(SM_CYMENU)+yedge*2+*y > monitor.bottom) {
  485. bottomdone = 1;
  486. *y -= height;
  487. *flag &= ~TPM_TOPALIGN;
  488. *flag |= TPM_BOTTOMALIGN;
  489. }*/
  490. for (i = 0;i < nitems;i++)
  491. {
  492. SIZE s={0};
  493. RECT item;
  494. MENUITEMINFOW info = {sizeof(info), MIIM_DATA | MIIM_TYPE | MIIM_STATE | MIIM_ID, MFT_STRING, };
  495. GetMenuItemRect(hMainWindow, menu, i, &item);
  496. item.left -= mwr.left;
  497. item.top -= mwr.top;
  498. item.right -= mwr.left;
  499. item.bottom -= mwr.top;
  500. if (item.top == 0 && item.left == 0)
  501. {
  502. // item has never been shown so MS wont give us the rect, I HATE THEM ! I HATE THEM SO MUCH ARRRG !
  503. // y
  504. item.top = cury;
  505. {
  506. GetMenuItemInfoW(menu, i, TRUE, &info);
  507. if (info.fType & MFT_SEPARATOR)
  508. cury += (itemheight - 1) >> 1;
  509. else
  510. {
  511. cury += itemheight - 2;
  512. //info.dwTypeData = (LPTSTR) MALLOC(++info.cch + 1);
  513. GetMenuItemInfoW(menu, i, TRUE, &info);
  514. //info.dwTypeData[info.cch] = 0;
  515. }
  516. }
  517. item.bottom = cury;
  518. // x
  519. if (info.dwTypeData)
  520. {
  521. LOGFONT m_lf;
  522. HFONT font = nullptr;
  523. HDC dc = nullptr;
  524. NONCLIENTMETRICS nm = {sizeof (NONCLIENTMETRICS), };
  525. memset((PVOID) &m_lf, 0, sizeof (LOGFONT));
  526. SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, nm.cbSize, &nm, 0);
  527. m_lf = nm.lfMenuFont;
  528. font = CreateFontIndirectW(&m_lf);
  529. dc = GetDC(hMainWindow);
  530. GetTextExtentPoint32(dc, info.dwTypeData, lstrlen(info.dwTypeData), &s);
  531. ReleaseDC(hMainWindow, dc);
  532. DeleteObject(font);
  533. //free(info.dwTypeData);
  534. }
  535. if (!(info.fType & MFT_SEPARATOR))
  536. {
  537. item.left = *x + xedge + 1;
  538. item.right = item.left + s.cx + checkmarkwidth * 2 + xedge + 1;
  539. }
  540. else
  541. {
  542. item.left = *x + xedge + 1;
  543. item.right = item.left + xedge + 1;
  544. }
  545. }
  546. else
  547. {
  548. item.left += *x;
  549. item.top += *y;
  550. item.right += *x;
  551. item.bottom += *y;
  552. item.right += xedge * 2 + 2; // to avoid last test
  553. cury = item.bottom;
  554. }
  555. if (!bottomdone && cury > monitor.bottom)
  556. {
  557. bottomdone = 1;
  558. *y -= height;
  559. *flag &= ~TPM_TOPALIGN;
  560. *flag |= TPM_BOTTOMALIGN;
  561. }
  562. if (!rightdone && item.right > monitor.right)
  563. {
  564. rightdone = 1;
  565. *x += width;
  566. *flag &= ~TPM_LEFTALIGN;
  567. *flag |= TPM_RIGHTALIGN;
  568. }
  569. if (rightdone && bottomdone) return ;
  570. }
  571. cury += yedge + 1;
  572. if (!bottomdone && cury > monitor.bottom)
  573. {
  574. //bottomdone = 1;
  575. *y -= height;
  576. *flag &= ~TPM_TOPALIGN;
  577. *flag |= TPM_BOTTOMALIGN;
  578. }
  579. }