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;
}