www.pudn.com > VOBSUB.rar > Systray.cpp


#include "stdafx.h" 
#include "resource.h" 
 
#include "DirectVobSubFilter.h" 
#include "misc.h" 
 
static HHOOK g_hHook = (HHOOK)INVALID_HANDLE_VALUE; 
 
static UINT WM_DVSPREVSUB = RegisterWindowMessage(TEXT("WM_DVSPREVSUB")); 
static UINT WM_DVSNEXTSUB = RegisterWindowMessage(TEXT("WM_DVSNEXTSUB")); 
static UINT WM_DVSHIDESUB = RegisterWindowMessage(TEXT("WM_DVSHIDESUB")); 
static UINT WM_DVSSHOWSUB = RegisterWindowMessage(TEXT("WM_DVSSHOWSUB")); 
static UINT WM_DVSSHOWHIDESUB = RegisterWindowMessage(TEXT("WM_DVSSHOWHIDESUB")); 
static UINT s_uTaskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); 
static UINT WM_NOTIFYICON = RegisterWindowMessage(TEXT("MYWM_NOTIFYICON")); 
 
LRESULT CALLBACK HookProc(UINT code, WPARAM wParam, LPARAM lParam) 
{ 
	MSG* msg = (MSG*)lParam; 
 
	if(msg->message == WM_KEYDOWN) 
	{ 
		switch(msg->wParam) 
		{ 
		case VK_F13: PostMessage(HWND_BROADCAST, WM_DVSPREVSUB, 0, 0); break; 
		case VK_F14: PostMessage(HWND_BROADCAST, WM_DVSNEXTSUB, 0, 0); break; 
		case VK_F15: PostMessage(HWND_BROADCAST, WM_DVSHIDESUB, 0, 0); break; 
		case VK_F16: PostMessage(HWND_BROADCAST, WM_DVSSHOWSUB, 0, 0); break; 
		case VK_F17: PostMessage(HWND_BROADCAST, WM_DVSSHOWHIDESUB, 0, 0); break; 
		default: break; 
		} 
	} 
 
	// Always call next hook in chain  
	return CallNextHookEx(g_hHook, code,  wParam, lParam); 
}  
 
 
class CSystrayWindow : public CWnd 
{ 
	SystrayIconData* m_tbid; 
 
	void StepSub(int dir) 
	{ 
		int iSelected, nLangs; 
		if(FAILED(m_tbid->dvs->get_LanguageCount(&nLangs))) return; 
		if(FAILED(m_tbid->dvs->get_SelectedLanguage(&iSelected))) return; 
        if(nLangs > 0) m_tbid->dvs->put_SelectedLanguage((iSelected+dir+nLangs)%nLangs); 
	} 
 
	void ShowSub(bool fShow) 
	{ 
		m_tbid->dvs->put_HideSubtitles(!fShow); 
	} 
 
	void ToggleSub() 
	{ 
		bool fShow; 
		if(FAILED(m_tbid->dvs->get_HideSubtitles(&fShow))) return; 
		m_tbid->dvs->put_HideSubtitles(!fShow); 
	} 
 
public: 
	CSystrayWindow(SystrayIconData* tbid) : m_tbid(tbid) {} 
 
protected: 
	DECLARE_MESSAGE_MAP() 
 
public: 
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); 
	afx_msg void OnClose(); 
	afx_msg void OnDestroy(); 
	afx_msg void OnTimer(UINT nIDEvent); 
	afx_msg LRESULT OnDVSPrevSub(WPARAM, LPARAM); 
	afx_msg LRESULT OnDVSNextSub(WPARAM, LPARAM); 
	afx_msg LRESULT OnDVSHideSub(WPARAM, LPARAM); 
	afx_msg LRESULT OnDVSShowSub(WPARAM, LPARAM); 
	afx_msg LRESULT OnDVSShowHideSub(WPARAM, LPARAM); 
	afx_msg LRESULT OnTaskBarRestart(WPARAM, LPARAM); 
	afx_msg LRESULT OnNotifyIcon(WPARAM, LPARAM); 
}; 
 
BEGIN_MESSAGE_MAP(CSystrayWindow, CWnd) 
	ON_WM_CREATE() 
	ON_WM_CLOSE() 
	ON_WM_DESTROY() 
	ON_WM_TIMER() 
	ON_REGISTERED_MESSAGE(WM_DVSPREVSUB, OnDVSPrevSub) 
	ON_REGISTERED_MESSAGE(WM_DVSNEXTSUB, OnDVSNextSub) 
	ON_REGISTERED_MESSAGE(WM_DVSHIDESUB, OnDVSHideSub) 
	ON_REGISTERED_MESSAGE(WM_DVSSHOWSUB, OnDVSShowSub) 
	ON_REGISTERED_MESSAGE(WM_DVSSHOWHIDESUB, OnDVSShowHideSub) 
	ON_REGISTERED_MESSAGE(s_uTaskbarRestart, OnTaskBarRestart) 
	ON_REGISTERED_MESSAGE(WM_NOTIFYICON, OnNotifyIcon) 
END_MESSAGE_MAP() 
 
int CSystrayWindow::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 
	if(CWnd::OnCreate(lpCreateStruct) == -1) 
		return -1; 
 
	if(g_hHook == INVALID_HANDLE_VALUE) 
	{ 
		AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
		g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)HookProc, AfxGetInstanceHandle(), 0); 
	} 
 
	SetTimer(1, 5000, NULL); 
 
	PostMessage(s_uTaskbarRestart); 
 
	return 0; 
} 
 
void CSystrayWindow::OnClose() 
{ 
	DestroyWindow(); 
} 
 
void CSystrayWindow::OnDestroy() 
{ 
	NOTIFYICONDATA tnid;  
	tnid.cbSize = sizeof(NOTIFYICONDATA);  
	tnid.hWnd = m_hWnd; 
	tnid.uID = IDI_ICON1;  
	Shell_NotifyIcon(NIM_DELETE, &tnid);  
 
	if(g_hHook != INVALID_HANDLE_VALUE) 
	{ 
		UnhookWindowsHookEx(g_hHook); 
		g_hHook = (HHOOK)INVALID_HANDLE_VALUE; 
	} 
 
	PostQuitMessage(0);  
} 
 
void CSystrayWindow::OnTimer(UINT nIDEvent) 
{ 
	if(nIDEvent == 1) 
	{ 
		UINT fScreenSaver = 0; 
		if(SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, (PVOID)&fScreenSaver, 0)) 
		{ 
			SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 0, 0, SPIF_SENDWININICHANGE); // this might not be needed at all... 
			SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, fScreenSaver, 0, SPIF_SENDWININICHANGE); 
		} 
	} 
 
	CWnd::OnTimer(nIDEvent); 
} 
 
LRESULT CSystrayWindow::OnDVSPrevSub(WPARAM, LPARAM) 
	{StepSub(-1); return 0;} 
LRESULT CSystrayWindow::OnDVSNextSub(WPARAM, LPARAM) 
	{StepSub(+1); return 0;} 
LRESULT CSystrayWindow::OnDVSHideSub(WPARAM, LPARAM) 
	{ShowSub(false); return 0;} 
LRESULT CSystrayWindow::OnDVSShowSub(WPARAM, LPARAM) 
	{ShowSub(true); return 0;} 
LRESULT CSystrayWindow::OnDVSShowHideSub(WPARAM, LPARAM) 
	{ToggleSub(); return 0;} 
 
LRESULT CSystrayWindow::OnTaskBarRestart(WPARAM, LPARAM) 
{ 
	AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
 
	if(m_tbid->fShowIcon) 
	{ 
		NOTIFYICONDATA tnid;  
		tnid.cbSize = sizeof(NOTIFYICONDATA);  
		tnid.hWnd = m_hWnd;  
		tnid.uID = IDI_ICON1;  
		tnid.hIcon = (HICON)LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1)); 
//		tnid.hIcon = (HICON)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 0, 0, LR_LOADTRANSPARENT); 
		tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;  
		tnid.uCallbackMessage = WM_NOTIFYICON;  
		lstrcpyn(tnid.szTip, TEXT("DirectVobSub"), sizeof(tnid.szTip));  
 
		BOOL res = Shell_NotifyIcon(NIM_ADD, &tnid);  
 
		if(tnid.hIcon) DestroyIcon(tnid.hIcon);  
 
		return res?0:-1; 
	} 
 
	return 0; 
} 
 
LRESULT CSystrayWindow::OnNotifyIcon(WPARAM wParam, LPARAM lParam) 
{ 
    if((UINT)wParam != IDI_ICON1) 
		return -1; 
 
	HWND hWnd = m_hWnd; 
	 
	switch((UINT)lParam) 
	{ 
		case WM_LBUTTONDBLCLK: 
		{ 
			TCHAR* str; 
			for(int i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++) 
			{ 
				bool fDVS = !_tcsncmp(str, _T("DirectVobSub"), 12); 
 
				delete [] str; 
 
				if(fDVS) 
				{ 
					if(CComQIPtr pVW = m_tbid->graph)  
					{ 
						HWND hwnd; 
						if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd)) 
						|| SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd))) 
							hWnd = hwnd; 
					} 
 
					CallPPage(m_tbid->graph, i, hWnd); 
 
					break; 
				} 
 
			} 
		} 
		break; 
 
		case WM_RBUTTONDOWN: 
		{ 
			POINT p; 
			GetCursorPos(&p); 
 
			CArray  streams; 
			CStringArray names; 
 
			CComPtr pEnum; 
			if(FAILED(m_tbid->graph->EnumFilters(&pEnum))) break; 
 
			for(CComPtr pFilter; S_OK == pEnum->Next(1, &pFilter, NULL); pFilter = NULL) 
			{ 
				FILTER_INFO fi; 
				if(FAILED(pFilter->QueryFilterInfo(&fi))) 
					continue; 
 
				if(fi.pGraph) fi.pGraph->Release(); 
 
				IAMStreamSelect* pSS = NULL; 
				if(SUCCEEDED(pFilter.QueryInterface(&pSS))) 
				{ 
					streams.Add(pSS); 
					names.Add(fi.achName); 
				} 
			} 
 
			HMENU hMenu = CreatePopupMenu(); 
 
			for(int j = 0; j < streams.GetSize(); j++) 
			{ 
				bool fMMSwitcher = !names[j].Compare(_T("Morgan Stream Switcher")); 
 
				DWORD count = 0; 
				streams[j]->Count(&count); 
 
				DWORD flags, group, prevgroup = -1; 
				 
				for(UINT i = 0; i < count; i++) 
				{ 
					WCHAR* pWName = NULL; 
//AM_MEDIA_TYPE* pmt = NULL; 
//LCID lcid; 
//IUnknown* pU[2]; 
					if(S_OK == streams[j]->Info(i, 0/*&pmt*/, &flags, 0, &group, &pWName, 0, 0)) 
					{ 
//							if(pmt) DeleteMediaType(pmt); 
 
						if(prevgroup != group && i > 1)  
						{ 
							if(fMMSwitcher) {count = i; break;} 
							AppendMenu(hMenu, MF_ENABLED|MF_SEPARATOR, 0, 0); 
						} 
						prevgroup = group; 
 
						if(pWName) 
						{ 
							CString str = pWName; 
							AppendMenu(hMenu, MF_ENABLED|MF_STRING|(flags?MF_CHECKED:MF_UNCHECKED), (1<<15)|(j<<8)|(i), str); 
							CoTaskMemFree(pWName); 
						} 
					} 
				} 
 
				if(count > 0) AppendMenu(hMenu, MF_ENABLED|MF_SEPARATOR, 0, 0); 
			} 
 
			int i; 
 
			TCHAR* str; 
			for(i = 0; str = CallPPage(m_tbid->graph, i, (HWND)INVALID_HANDLE_VALUE); i++) 
			{ 
				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 
					AppendMenu(hMenu, MF_ENABLED|MF_STRING|MF_UNCHECKED, (1<<14)|(i), str); 
 
				delete [] str; 
			} 
 
			SetForegroundWindow(); 
			UINT id = TrackPopupMenu(hMenu, TPM_LEFTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hWnd, 0); 
			PostMessage(WM_NULL); 
 
			DestroyMenu(hMenu); 
 
			if(id & (1<<15))  
			{ 
				streams[(id>>8)&0x3f]->Enable(id&0xff, AMSTREAMSELECTENABLE_ENABLE); 
			} 
			else if(id & (1<<14)) 
			{ 
				if(CComQIPtr pVW = m_tbid->graph) 
				{ 
					HWND hwnd; 
					if(SUCCEEDED(pVW->get_Owner((OAHWND*)&hwnd)) 
					|| SUCCEEDED(pVW->get_MessageDrain((OAHWND*)&hwnd))) 
						hWnd = hwnd; 
				} 
 
				CallPPage(m_tbid->graph, id&0xff, hWnd); 
			} 
 
			for(i = 0; i < streams.GetSize(); i++) streams[i]->Release(); 
		} 
		break;  
 
		default:  
			break;  
	} 
 
	return 0; 
} 
 
// 
 
DWORD CALLBACK SystrayThreadProc(void* pParam) 
{ 
	AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
 
	CSystrayWindow wnd((SystrayIconData*)pParam); 
	if(!wnd.CreateEx(0, AfxRegisterWndClass(0), _T("DVSWND"), WS_OVERLAPPED, CRect(0, 0, 0, 0), NULL, 0, NULL)) 
		return -1; 
 
	((SystrayIconData*)pParam)->hSystrayWnd = wnd.m_hWnd; 
 
	MSG msg; 
	while(GetMessage(&msg, NULL, 0, 0)) 
	{ 
		TranslateMessage(&msg); 
		DispatchMessage(&msg); 
	} 
 
	return 0; 
}