view.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. #include <strsafe.h>
  2. #include "main.h"
  3. #include "../nu/DialogSkinner.h"
  4. #include "../nu/ListView.h"
  5. #include "../../General/gen_ml/ml_ipc.h"
  6. #include "../../General/gen_ml/menu.h"
  7. #include "../WAT/WAT.h"
  8. INT_PTR CALLBACK view_NFTDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam);
  9. static W_ListView m_nft_list;
  10. static HWND m_headerhwnd, m_hwnd;
  11. extern C_Config *g_config;
  12. extern char *g_ext_list;
  13. static int customAllowed;
  14. static viewButtons view;
  15. C_Config *g_wa_config = 0;
  16. char *g_ext_list = 0;
  17. // used for the send-to menu bits
  18. static INT_PTR IPC_LIBRARY_SENDTOMENU;
  19. static librarySendToMenuStruct s;
  20. BOOL myMenu = FALSE;
  21. extern HMENU g_context_menus, g_context_menus2;
  22. extern HCURSOR hDragNDropCursor;
  23. static int NFT_contextMenu( INT_PTR param1, HWND hHost, POINTS pts )
  24. {
  25. return TRUE;
  26. }
  27. static int pluginHandleIpcMessage(int msg, int param)
  28. {
  29. return (int)SendMessage( plugin.hwndLibraryParent, WM_ML_IPC, param, msg );
  30. }
  31. INT_PTR nft_pluginMessageProc(int message_type, INT_PTR param1, INT_PTR param2, INT_PTR param3)
  32. {
  33. if (message_type == ML_MSG_NO_CONFIG)
  34. {
  35. return TRUE;
  36. }
  37. else if (message_type == ML_MSG_TREE_ONCREATEVIEW && param1 == nft_treeItem )
  38. {
  39. return (INT_PTR)WASABI_API_CREATEDIALOGW(IDD_VIEW_NFT, (HWND)param2, view_NFTDialogProc);
  40. }
  41. else if (message_type == ML_MSG_NAVIGATION_CONTEXTMENU)
  42. {
  43. return NFT_contextMenu(param1, (HWND)param2, MAKEPOINTS(param3));
  44. }
  45. else if (message_type == ML_MSG_ONSENDTOSELECT || message_type == ML_MSG_TREE_ONDROPTARGET)
  46. {
  47. // set with droptarget defaults =)
  48. UINT_PTR type = 0,data = 0;
  49. if (message_type == ML_MSG_ONSENDTOSELECT)
  50. {
  51. if (param3 != (INT_PTR)nft_pluginMessageProc) return 0;
  52. type=(int)param1;
  53. data = (int)param2;
  54. }
  55. else
  56. {
  57. if (param1 != nft_treeItem ) return 0;
  58. type=(int)param2;
  59. data=(int)param3;
  60. if (!data)
  61. {
  62. return (type == ML_TYPE_ITEMRECORDLISTW || type == ML_TYPE_ITEMRECORDLIST ||
  63. type == ML_TYPE_FILENAMES || type == ML_TYPE_STREAMNAMES ||
  64. type == ML_TYPE_FILENAMESW || type == ML_TYPE_STREAMNAMESW ||
  65. type == ML_TYPE_CDTRACKS ||
  66. type == ML_TYPE_PLAYLIST || type == ML_TYPE_PLAYLISTS) ? 1 : -1;
  67. }
  68. }
  69. }
  70. return 0;
  71. }
  72. static HRGN g_rgnUpdate = NULL;
  73. static int offsetX = 0, offsetY = 0;
  74. typedef struct _LAYOUT
  75. {
  76. INT id;
  77. HWND hwnd;
  78. INT x;
  79. INT y;
  80. INT cx;
  81. INT cy;
  82. DWORD flags;
  83. HRGN rgn;
  84. }
  85. LAYOUT, PLAYOUT;
  86. #define SETLAYOUTPOS(_layout, _x, _y, _cx, _cy) { _layout->x=_x; _layout->y=_y;_layout->cx=_cx;_layout->cy=_cy;_layout->rgn=NULL; }
  87. #define SETLAYOUTFLAGS(_layout, _r) \
  88. { \
  89. BOOL fVis; \
  90. fVis = (WS_VISIBLE & (LONG)GetWindowLongPtr(_layout->hwnd, GWL_STYLE)); \
  91. if (_layout->x == _r.left && _layout->y == _r.top) _layout->flags |= SWP_NOMOVE; \
  92. if (_layout->cx == (_r.right - _r.left) && _layout->cy == (_r.bottom - _r.top)) _layout->flags |= SWP_NOSIZE; \
  93. if ((SWP_HIDEWINDOW & _layout->flags) && !fVis) _layout->flags &= ~SWP_HIDEWINDOW; \
  94. if ((SWP_SHOWWINDOW & _layout->flags) && fVis) _layout->flags &= ~SWP_SHOWWINDOW; \
  95. }
  96. #define LAYOUTNEEEDUPDATE(_layout) ((SWP_NOMOVE | SWP_NOSIZE) != ((SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW | SWP_SHOWWINDOW) & _layout->flags))
  97. #define GROUP_MIN 0x1
  98. #define GROUP_MAX 0x2
  99. #define GROUP_STATUSBAR 0x1
  100. #define GROUP_MAIN 0x2
  101. static void LayoutWindows(HWND hwnd, BOOL fRedraw, BOOL fUpdateAll = FALSE)
  102. {
  103. static INT controls[] =
  104. {
  105. GROUP_STATUSBAR, GROUP_MAIN, IDC_LIST_NFT
  106. };
  107. INT index;
  108. RECT rc, rg, ri;
  109. LAYOUT layout[sizeof(controls)/sizeof(controls[0])], *pl;
  110. BOOL skipgroup;
  111. HRGN rgn = NULL;
  112. GetClientRect(hwnd, &rc);
  113. if ( rc.right == rc.left || rc.bottom == rc.top )
  114. return;
  115. if ( rc.right > WASABI_API_APP->getScaleX( 4 ) )
  116. rc.right -= WASABI_API_APP->getScaleX( 4 );
  117. SetRect(&rg, rc.left, rc.top, rc.right, rc.top);
  118. pl = layout;
  119. skipgroup = FALSE;
  120. InvalidateRect(hwnd, NULL, TRUE);
  121. for (index = 0; index < sizeof(controls) / sizeof(*controls); index++)
  122. {
  123. if (controls[index] >= GROUP_MIN && controls[index] <= GROUP_MAX) // group id
  124. {
  125. skipgroup = FALSE;
  126. switch (controls[index])
  127. {
  128. case GROUP_MAIN:
  129. SetRect(&rg, rc.left + WASABI_API_APP->getScaleX(1), rc.top, rc.right, rc.bottom);
  130. break;
  131. }
  132. continue;
  133. }
  134. if (skipgroup) continue;
  135. pl->id = controls[index];
  136. pl->hwnd = GetDlgItem(hwnd, pl->id);
  137. if (!pl->hwnd) continue;
  138. GetWindowRect(pl->hwnd, &ri);
  139. MapWindowPoints(HWND_DESKTOP, hwnd, (LPPOINT)&ri, 2);
  140. pl->flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOCOPYBITS;
  141. switch (pl->id)
  142. {
  143. case IDC_LIST_NFT:
  144. pl->flags |= (rg.top < rg.bottom) ? SWP_SHOWWINDOW : SWP_HIDEWINDOW;
  145. SETLAYOUTPOS(pl, rg.left, rg.top + WASABI_API_APP->getScaleY(1),
  146. rg.right - rg.left + WASABI_API_APP->getScaleY(1),
  147. (rg.bottom - rg.top) - WASABI_API_APP->getScaleY(2));
  148. break;
  149. }
  150. SETLAYOUTFLAGS(pl, ri);
  151. if (LAYOUTNEEEDUPDATE(pl))
  152. {
  153. if (SWP_NOSIZE == ((SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_NOSIZE) & pl->flags) &&
  154. ri.left == (pl->x + offsetX) && ri.top == (pl->y + offsetY) && IsWindowVisible(pl->hwnd))
  155. {
  156. SetRect(&ri, pl->x, pl->y, pl->cx + pl->x, pl->y + pl->cy);
  157. ValidateRect(hwnd, &ri);
  158. }
  159. pl++;
  160. }
  161. else if ((fRedraw || (!offsetX && !offsetY)) && IsWindowVisible(pl->hwnd))
  162. {
  163. ValidateRect(hwnd, &ri);
  164. if (GetUpdateRect(pl->hwnd, NULL, FALSE))
  165. {
  166. if (!rgn) rgn = CreateRectRgn(0, 0, 0, 0);
  167. GetUpdateRgn(pl->hwnd, rgn, FALSE);
  168. OffsetRgn(rgn, pl->x, pl->y);
  169. InvalidateRgn(hwnd, rgn, FALSE);
  170. }
  171. }
  172. }
  173. if (pl != layout)
  174. {
  175. LAYOUT *pc;
  176. HDWP hdwp = BeginDeferWindowPos((INT)(pl - layout));
  177. for(pc = layout; pc < pl && hdwp; pc++)
  178. {
  179. hdwp = DeferWindowPos(hdwp, pc->hwnd, NULL, pc->x, pc->y, pc->cx, pc->cy, pc->flags);
  180. }
  181. if (hdwp) EndDeferWindowPos(hdwp);
  182. if (!rgn) rgn = CreateRectRgn(0, 0, 0, 0);
  183. if (fRedraw)
  184. {
  185. GetUpdateRgn(hwnd, rgn, FALSE);
  186. for(pc = layout; pc < pl && hdwp; pc++)
  187. {
  188. if (pc->rgn)
  189. {
  190. OffsetRgn(pc->rgn, pc->x, pc->y);
  191. CombineRgn(rgn, rgn, pc->rgn, RGN_OR);
  192. }
  193. }
  194. RedrawWindow(hwnd, NULL, rgn, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASENOW | RDW_ALLCHILDREN);
  195. }
  196. if (g_rgnUpdate)
  197. {
  198. GetUpdateRgn(hwnd, g_rgnUpdate, FALSE);
  199. for(pc = layout; pc < pl && hdwp; pc++)
  200. {
  201. if (pc->rgn)
  202. {
  203. OffsetRgn(pc->rgn, pc->x, pc->y);
  204. CombineRgn(g_rgnUpdate, g_rgnUpdate, pc->rgn, RGN_OR);
  205. }
  206. }
  207. }
  208. for(pc = layout; pc < pl && hdwp; pc++) if (pc->rgn) DeleteObject(pc->rgn);
  209. }
  210. if (rgn) DeleteObject(rgn);
  211. ValidateRgn(hwnd, NULL);
  212. }
  213. static BOOL NFT_OnDisplayChange()
  214. {
  215. ListView_SetTextColor(m_nft_list.getwnd(),dialogSkinner.Color(WADLG_ITEMFG));
  216. ListView_SetBkColor(m_nft_list.getwnd(),dialogSkinner.Color(WADLG_ITEMBG));
  217. ListView_SetTextBkColor(m_nft_list.getwnd(),dialogSkinner.Color(WADLG_ITEMBG));
  218. m_nft_list.SetFont(dialogSkinner.GetFont());
  219. LayoutWindows(m_hwnd, TRUE);
  220. return 0;
  221. }
  222. enum
  223. {
  224. BPM_ECHO_WM_COMMAND = 0x1, // send WM_COMMAND and return value
  225. BPM_WM_COMMAND = 0x2, // just send WM_COMMAND
  226. };
  227. static BOOL NFT_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  228. {
  229. return FALSE;
  230. }
  231. static BOOL NFT_OnDestroy(HWND hwnd)
  232. {
  233. m_hwnd = 0;
  234. return FALSE;
  235. }
  236. static BOOL NFT_OnNotify(HWND hwnd, NMHDR *notification)
  237. {
  238. if (notification->idFrom== IDC_LIST_NFT )
  239. {
  240. if (notification->code == LVN_BEGINDRAG)
  241. {
  242. SetCapture(hwnd);
  243. }
  244. }
  245. return FALSE;
  246. }
  247. static BOOL NFT_OnInitDialog(HWND hwndDlg, HWND hwndFocus, LPARAM lParam)
  248. {
  249. m_hwnd = hwndDlg;
  250. m_nft_list.setwnd(GetDlgItem(hwndDlg, IDC_LIST_NFT ));
  251. if (!view.play)
  252. {
  253. SENDMLIPC(plugin.hwndLibraryParent, ML_IPC_GET_VIEW_BUTTON_TEXT, (WPARAM)&view);
  254. }
  255. NFT_OnDisplayChange();
  256. m_headerhwnd = ListView_GetHeader( m_nft_list.getwnd() );
  257. // v5.66+ - re-use the old predixis parts so the button can be used functionally via ml_enqplay
  258. // pass the hwnd, button id and plug-in id so the ml plug-in can check things as needed
  259. customAllowed = FALSE;
  260. MLSKINWINDOW m = {0};
  261. m.skinType = SKINNEDWND_TYPE_DIALOG;
  262. m.style = SWS_USESKINCOLORS | SWS_USESKINCURSORS | SWS_USESKINFONT;
  263. m.hwndToSkin = hwndDlg;
  264. MLSkinWindow(plugin.hwndLibraryParent, &m);
  265. ShellExecuteW( NULL, L"open", NFT_BASE_URL, NULL, NULL, SW_SHOWNORMAL );
  266. delete g_wa_config;
  267. SetTimer( hwndDlg, 100, 15, NULL );
  268. return TRUE;
  269. }
  270. INT_PTR CALLBACK view_NFTDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,LPARAM lParam)
  271. {
  272. INT_PTR a = dialogSkinner.Handle(hwndDlg, uMsg, wParam, lParam);
  273. if (a) return a;
  274. switch(uMsg)
  275. {
  276. HANDLE_MSG(hwndDlg, WM_INITDIALOG, NFT_OnInitDialog);
  277. HANDLE_MSG(hwndDlg, WM_COMMAND, NFT_OnCommand);
  278. HANDLE_MSG(hwndDlg, WM_DESTROY, NFT_OnDestroy);
  279. case WM_WINDOWPOSCHANGED:
  280. if ((SWP_NOSIZE | SWP_NOMOVE) != ((SWP_NOSIZE | SWP_NOMOVE) & ((WINDOWPOS*)lParam)->flags) ||
  281. (SWP_FRAMECHANGED & ((WINDOWPOS*)lParam)->flags))
  282. {
  283. LayoutWindows(hwndDlg, !(SWP_NOREDRAW & ((WINDOWPOS*)lParam)->flags));
  284. }
  285. return 0;
  286. case WM_USER + 0x200:
  287. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 1); // yes, we support no - redraw resize
  288. return TRUE;
  289. case WM_USER + 0x201:
  290. offsetX = (short)LOWORD(wParam);
  291. offsetY = (short)HIWORD(wParam);
  292. g_rgnUpdate = (HRGN)lParam;
  293. return TRUE;
  294. case WM_PAINT:
  295. {
  296. int tab[] = { IDC_LIST_NFT |DCW_SUNKENBORDER};
  297. dialogSkinner.Draw(hwndDlg, tab, sizeof(tab) / sizeof(tab[0]));
  298. }
  299. return 0;
  300. case WM_INITMENUPOPUP:
  301. if (wParam && (HMENU)wParam == s.build_hMenu && s.mode==1)
  302. {
  303. myMenu = TRUE;
  304. if(SendMessage(plugin.hwndWinampParent, WM_WA_IPC, (WPARAM)&s, IPC_LIBRARY_SENDTOMENU)==0xffffffff)
  305. s.mode=2;
  306. myMenu = FALSE;
  307. }
  308. return 0;
  309. case WM_DISPLAYCHANGE:
  310. return NFT_OnDisplayChange();
  311. case WM_NOTIFY:
  312. return NFT_OnNotify(hwndDlg, (LPNMHDR)lParam);
  313. }
  314. return FALSE;
  315. }