Systray.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:11k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "stdafx.h"
  22. #include "resource.h"
  23. #include "DirectVobSubFilter.h"
  24. #include "......DSUtilDSUtil.h"
  25. // hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
  26. static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd);
  27. static HHOOK g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
  28. static UINT WM_DVSPREVSUB = RegisterWindowMessage(TEXT("WM_DVSPREVSUB"));
  29. static UINT WM_DVSNEXTSUB = RegisterWindowMessage(TEXT("WM_DVSNEXTSUB"));
  30. static UINT WM_DVSHIDESUB = RegisterWindowMessage(TEXT("WM_DVSHIDESUB"));
  31. static UINT WM_DVSSHOWSUB = RegisterWindowMessage(TEXT("WM_DVSSHOWSUB"));
  32. static UINT WM_DVSSHOWHIDESUB = RegisterWindowMessage(TEXT("WM_DVSSHOWHIDESUB"));
  33. static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated"));
  34. static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON"));
  35. LRESULT CALLBACK HookProc(UINT code, WPARAM wParam, LPARAM lParam)
  36. {
  37. MSG* msg = (MSG*)lParam;
  38. if(msg->message == WM_KEYDOWN)
  39. {
  40. switch(msg->wParam)
  41. {
  42. case VK_F13: PostMessage(HWND_BROADCAST, WM_DVSPREVSUB, 0, 0); break;
  43. case VK_F14: PostMessage(HWND_BROADCAST, WM_DVSNEXTSUB, 0, 0); break;
  44. case VK_F15: PostMessage(HWND_BROADCAST, WM_DVSHIDESUB, 0, 0); break;
  45. case VK_F16: PostMessage(HWND_BROADCAST, WM_DVSSHOWSUB, 0, 0); break;
  46. case VK_F17: PostMessage(HWND_BROADCAST, WM_DVSSHOWHIDESUB, 0, 0); break;
  47. default: break;
  48. }
  49. }
  50. // Always call next hook in chain 
  51. return CallNextHookEx(g_hHook, code,  wParam, lParam);
  52. class CSystrayWindow : public CWnd
  53. {
  54. SystrayIconData* m_tbid;
  55. void StepSub(int dir)
  56. {
  57. int iSelected, nLangs;
  58. if(FAILED(m_tbid->dvs->get_LanguageCount(&nLangs))) return;
  59. if(FAILED(m_tbid->dvs->get_SelectedLanguage(&iSelected))) return;
  60.         if(nLangs > 0) m_tbid->dvs->put_SelectedLanguage((iSelected+dir+nLangs)%nLangs);
  61. }
  62. void ShowSub(bool fShow)
  63. {
  64. m_tbid->dvs->put_HideSubtitles(!fShow);
  65. }
  66. void ToggleSub()
  67. {
  68. bool fShow;
  69. if(FAILED(m_tbid->dvs->get_HideSubtitles(&fShow))) return;
  70. m_tbid->dvs->put_HideSubtitles(!fShow);
  71. }
  72. public:
  73. CSystrayWindow(SystrayIconData* tbid) : m_tbid(tbid) {}
  74. protected:
  75. DECLARE_MESSAGE_MAP()
  76. public:
  77. afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  78. afx_msg void OnClose();
  79. afx_msg void OnDestroy();
  80. afx_msg void OnTimer(UINT nIDEvent);
  81. afx_msg LRESULT OnDVSPrevSub(WPARAM, LPARAM);
  82. afx_msg LRESULT OnDVSNextSub(WPARAM, LPARAM);
  83. afx_msg LRESULT OnDVSHideSub(WPARAM, LPARAM);
  84. afx_msg LRESULT OnDVSShowSub(WPARAM, LPARAM);
  85. afx_msg LRESULT OnDVSShowHideSub(WPARAM, LPARAM);
  86. afx_msg LRESULT OnTaskBarRestart(WPARAM, LPARAM);
  87. afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM);
  88. };
  89. BEGIN_MESSAGE_MAP(CSystrayWindow, CWnd)
  90. ON_WM_CREATE()
  91. ON_WM_CLOSE()
  92. ON_WM_DESTROY()
  93. ON_WM_TIMER()
  94. ON_REGISTERED_MESSAGE(WM_DVSPREVSUB, OnDVSPrevSub)
  95. ON_REGISTERED_MESSAGE(WM_DVSNEXTSUB, OnDVSNextSub)
  96. ON_REGISTERED_MESSAGE(WM_DVSHIDESUB, OnDVSHideSub)
  97. ON_REGISTERED_MESSAGE(WM_DVSSHOWSUB, OnDVSShowSub)
  98. ON_REGISTERED_MESSAGE(WM_DVSSHOWHIDESUB, OnDVSShowHideSub)
  99. ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart)
  100. ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon)
  101. END_MESSAGE_MAP()
  102. int CSystrayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
  103. {
  104. if(CWnd::OnCreate(lpCreateStruct) == -1)
  105. return -1;
  106. if(g_hHook == INVALID_HANDLE_VALUE)
  107. {
  108. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  109. // g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, AfxGetInstanceHandle(), 0);
  110. }
  111. SetTimer(1, 5000, NULL);
  112. PostMessage(s_uTaskbarRestart);
  113. return 0;
  114. }
  115. void CSystrayWindow::OnClose()
  116. {
  117. DestroyWindow();
  118. }
  119. void CSystrayWindow::OnDestroy()
  120. {
  121. NOTIFYICONDATA tnid; 
  122. tnid.cbSize = sizeof(NOTIFYICONDATA); 
  123. tnid.hWnd = m_hWnd;
  124. tnid.uID = IDI_ICON1; 
  125. Shell_NotifyIcon(NIM_DELETE, &tnid); 
  126. if(g_hHook != INVALID_HANDLE_VALUE)
  127. {
  128. UnhookWindowsHookEx(g_hHook);
  129. g_hHook = (HHOOK)INVALID_HANDLE_VALUE;
  130. }
  131. PostQuitMessage(0); 
  132. }
  133. void CSystrayWindow::OnTimer(UINT nIDEvent)
  134. {
  135. if(nIDEvent == 1)
  136. {
  137. UINT fScreenSaver = 0;
  138. if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fScreenSaver, 0))
  139. {
  140. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all...
  141. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fScreenSaver, 0, SPIF_SENDWININICHANGE);
  142. }
  143. }
  144. CWnd::OnTimer(nIDEvent);
  145. }
  146. LRESULT CSystrayWindow::OnDVSPrevSub(WPARAM, LPARAM)
  147. {StepSub(-1); return 0;}
  148. LRESULT CSystrayWindow::OnDVSNextSub(WPARAM, LPARAM)
  149. {StepSub(+1); return 0;}
  150. LRESULT CSystrayWindow::OnDVSHideSub(WPARAM, LPARAM)
  151. {ShowSub(false); return 0;}
  152. LRESULT CSystrayWindow::OnDVSShowSub(WPARAM, LPARAM)
  153. {ShowSub(true); return 0;}
  154. LRESULT CSystrayWindow::OnDVSShowHideSub(WPARAM, LPARAM)
  155. {ToggleSub(); return 0;}
  156. LRESULT CSystrayWindow::OnTaskBarRestart(WPARAM, LPARAM)
  157. {
  158. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  159. if(m_tbid->fShowIcon)
  160. {
  161. NOTIFYICONDATA tnid; 
  162. tnid.cbSize = sizeof(NOTIFYICONDATA); 
  163. tnid.hWnd = m_hWnd; 
  164. tnid.uID = IDI_ICON1; 
  165. tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1));
  166. // tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_LOADTRANSPARENT);
  167. tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
  168. tnid.uCallbackMessage = WM_NOTIFYICON; 
  169. lstrcpyn(tnid.szTip, TEXT("DirectVobSub"), sizeof(tnid.szTip)); 
  170. BOOL res = Shell_NotifyIcon(NIM_ADD, &tnid); 
  171. if(tnid.hIcon) DestroyIcon(tnid.hIcon); 
  172. return res?0:-1;
  173. }
  174. return 0;
  175. }
  176. LRESULT CSystrayWindow::OnNotifyIcon(WPARAM wParam, LPARAM lParam)
  177. {
  178.     if((UINT)wParam != IDI_ICON1)
  179. return -1;
  180. HWND hWnd = m_hWnd;
  181. switch((UINT)lParam)
  182. {
  183. case WM_LBUTTONDBLCLK:
  184. {
  185. // IMPORTANT: we must not hold the graph at the same time as showing the property page 
  186. // or else when closing the app the graph doesn't get released and dvobsub's JoinFilterGraph
  187. // is never called to close us down.
  188. CComPtr<IBaseFilter> pBF2;
  189. BeginEnumFilters(m_tbid->graph, pEF, pBF)
  190. {
  191. if(!CComQIPtr<IDirectVobSub>(pBF))
  192. continue;
  193. if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph) 
  194. {
  195. HWND hwnd;
  196. if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
  197. || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
  198. hWnd = hwnd;
  199. }
  200. pBF2 = pBF;
  201. break;
  202. }
  203. EndEnumFilters
  204. if(pBF2)
  205. ShowPPage(pBF2, hWnd);
  206. }
  207. break;
  208. case WM_RBUTTONDOWN:
  209. {
  210. POINT p;
  211. GetCursorPos(&p);
  212. CInterfaceArray<IAMStreamSelect> pStreams;
  213. CStringArray names;
  214. BeginEnumFilters(m_tbid->graph, pEF, pBF)
  215. {
  216. CString name = GetFilterName(pBF);
  217. if(name.IsEmpty()) continue;
  218. if(CComQIPtr<IAMStreamSelect> pSS = pBF)
  219. {
  220. pStreams.Add(pSS);
  221. names.Add(name);
  222. }
  223. }
  224. EndEnumFilters
  225. CMenu popup;
  226. popup.CreatePopupMenu();
  227. for(int j = 0; j < pStreams.GetCount(); j++)
  228. {
  229. bool fMMSwitcher = !names[j].Compare(_T("Morgan Stream Switcher"));
  230. DWORD cStreams = 0;
  231. pStreams[j]->Count(&cStreams);
  232. DWORD flags, group, prevgroup = -1;
  233. for(UINT i = 0; i < cStreams; i++)
  234. {
  235. WCHAR* pName = NULL;
  236. if(S_OK == pStreams[j]->Info(i, 0, &flags, 0, &group, &pName, 0, 0))
  237. {
  238. if(prevgroup != group && i > 1) 
  239. {
  240. if(fMMSwitcher) {cStreams = i; break;}
  241. popup.AppendMenu(MF_SEPARATOR);
  242. }
  243. prevgroup = group;
  244. if(pName)
  245. {
  246. popup.AppendMenu(MF_ENABLED|MF_STRING|(flags?MF_CHECKED:MF_UNCHECKED), (1<<15)|(j<<8)|(i), CString(pName));
  247. CoTaskMemFree(pName);
  248. }
  249. }
  250. }
  251. if(cStreams > 0) popup.AppendMenu(MF_SEPARATOR);
  252. }
  253. int i;
  254. TCHAR* str;
  255. for(i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++)
  256. {
  257. if(_tcsncmp(str, _T("DivX MPEG"), 9) || m_tbid->fRunOnce) // divx3's ppage will crash if the graph hasn't been run at least once yet
  258. popup.AppendMenu(MF_ENABLED|MF_STRING|MF_UNCHECKED, (1<<14)|(i), str);
  259. delete [] str;
  260. }
  261. SetForegroundWindow();
  262. UINT id = popup.TrackPopupMenu(TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, CWnd::FromHandle(hWnd), 0);
  263. PostMessage(WM_NULL);
  264. if(id & (1<<15)) 
  265. {
  266. pStreams[(id>>8)&0x3f]->Enable(id&0xff, AMSTREAMSELECTENABLE_ENABLE);
  267. }
  268. else if(id & (1<<14))
  269. {
  270. if(CComQIPtr<IVideoWindow> pVW = m_tbid->graph)
  271. {
  272. HWND hwnd;
  273. if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd))
  274. || SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd)))
  275. hWnd = hwnd;
  276. }
  277. CallPPage(m_tbid->graph, id&0xff, hWnd);
  278. }
  279. }
  280. break; 
  281. default: 
  282. break; 
  283. }
  284. return 0;
  285. }
  286. //
  287. DWORD CALLBACK SystrayThreadProc(void* pParam)
  288. {
  289. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  290. CSystrayWindow wnd((SystrayIconData*)pParam);
  291. if(!wnd.CreateEx(0, AfxRegisterWndClass(0), _T("DVSWND"), WS_OVERLAPPED, CRect(0, 0, 0, 0), NULL, 0, NULL))
  292. return -1;
  293. ((SystrayIconData*)pParam)->hSystrayWnd = wnd.m_hWnd;
  294. MSG msg;
  295. while(GetMessage(&msg, NULL/*wnd.m_hWnd*/, 0, 0))
  296. {
  297. TranslateMessage(&msg);
  298. DispatchMessage(&msg);
  299. }
  300. return 0;
  301. }
  302. // TODO: replace this function
  303. // hWnd == INVALID_HANDLE_VALUE - get name, hWnd != INVALID_HANDLE_VALUE - show ppage
  304. static TCHAR* CallPPage(IFilterGraph* pGraph, int idx, HWND hWnd)
  305. {
  306. int i = 0;
  307. bool fFound = false;
  308. WCHAR* wstr = NULL;
  309. CComPtr<IBaseFilter> pFilter;
  310. CAUUID caGUID;
  311. caGUID.pElems = NULL;
  312. BeginEnumFilters(pGraph, pEF, pBF)
  313. {
  314. CComQIPtr<ISpecifyPropertyPages> pSPS = pBF;
  315. if(!pSPS) continue;
  316. if(i == idx)
  317. pFilter = pBF;
  318. pSPS->GetPages(&caGUID);
  319. wstr = _wcsdup(CStringW(GetFilterName(pBF))); // double char-wchar conversion happens in the non-unicode build, but anyway... :)
  320. break;
  321. }
  322. i++;
  323. }
  324. EndEnumFilters
  325. TCHAR* ret = NULL;
  326. if(pFilter)
  327. {
  328. if(hWnd != INVALID_HANDLE_VALUE)
  329. {
  330. ShowPPage(pFilter, hWnd);
  331. }
  332. else
  333. {
  334. if(ret = new TCHAR[wcslen(wstr)+1])
  335. _tcscpy(ret, CString(wstr));
  336. }
  337. }
  338. if(caGUID.pElems) CoTaskMemFree(caGUID.pElems);
  339. if(wstr) free(wstr);
  340. return(ret);
  341. }