windows-nt/Source/XPSP1/NT/multimedia/media/deluxe2/main/shellico.cpp
2020-09-26 16:20:57 +08:00

566 lines
16 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SHELLICO.CPP
//
// Shell tray icon handler
//
// Copyright (c) Microsoft Corporation 1998
//
// 3/15/98 David Stewart / dstewart
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <shellapi.h>
#include "shellico.h"
#include "mmenu.h"
#include "resource.h"
#define IDM_HOMEMENU_BASE (LAST_SEARCH_MENU_ID + 1)
#define IDM_NETMENU_BASE (LAST_SEARCH_MENU_ID + 100)
#define IDM_DISCLIST_BASE 20000
#define SHELLTIMERID 1500
//file-global variables
PCOMPNODE g_pNode = NULL;
IMMComponentAutomation* g_pAuto = NULL;
HWND g_hwnd = NULL;
HINSTANCE g_hInst = NULL;
BOOL g_fShellIconCreated = FALSE;
//icon
HICON hIconPlay = NULL;
HICON hIconPause = NULL;
HICON hIconNoDisc = NULL;
extern fOptionsDlgUp;
extern nCDMode;
extern BOOL fPlaying;
extern BOOL IsDownloading();
extern CustomMenu* g_pMenu;
extern "C" void NormalizeNameForMenuDisplay(TCHAR* szInput, TCHAR* szOutput, DWORD cbLen);
void CheckDiscState()
{
if (g_fShellIconCreated)
{
MMMEDIAID mmMedia;
mmMedia.nDrive = -1;
g_pAuto->OnAction(MMACTION_GETMEDIAID,&mmMedia);
if (mmMedia.dwMediaID != 0)
{
ShellIconSetState(fPlaying ? PAUSE_ICON : PLAY_ICON);
}
else
{
ShellIconSetState(NODISC_ICON);
}
}
}
BOOL CreateShellIcon(HINSTANCE hInst, HWND hwndOwner, PCOMPNODE pNode, TCHAR* sztip)
{
BOOL retval = FALSE;
g_hInst = hInst;
HRESULT hr = pNode->pComp->QueryInterface(IID_IMMComponentAutomation,(void**)&g_pAuto);
if (SUCCEEDED(hr))
{
g_pNode = pNode;
//load all of the icon images
hIconPlay = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_SHELL_PLAY), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
hIconPause = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_SHELL_PAUSE), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
hIconNoDisc = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_SHELL_NODISC), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
//now, create the tray icon
g_hwnd = hwndOwner;
NOTIFYICONDATA nData;
nData.cbSize = sizeof(nData);
nData.hWnd = hwndOwner;
nData.uID = SHELLMESSAGE_CDICON;
nData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
nData.uCallbackMessage = SHELLMESSAGE_CDICON;
nData.hIcon = hIconPlay;
_tcscpy(nData.szTip,sztip);
retval = Shell_NotifyIcon(NIM_ADD,&nData);
if (!retval)
{
g_pAuto->Release();
g_pAuto = NULL;
}
else
{
g_fShellIconCreated = TRUE;
CheckDiscState();
}
}
return (retval);
}
void DestroyShellIcon()
{
g_fShellIconCreated = FALSE;
if (g_pAuto)
{
//g_pAuto was addref'ed when we qi'ed for it.
g_pAuto->Release();
}
NOTIFYICONDATA nData;
nData.cbSize = sizeof(nData);
nData.uID = SHELLMESSAGE_CDICON;
nData.hWnd = g_hwnd;
Shell_NotifyIcon(NIM_DELETE,&nData);
//kill the icons
DestroyIcon(hIconPlay);
DestroyIcon(hIconPause);
DestroyIcon(hIconNoDisc);
hIconPlay = NULL;
hIconPause = NULL;
hIconNoDisc = NULL;
}
//works around bug in all Windows versions
//where ampersands are stripped from tooltips on shell icon
void EscapeTooltip(TCHAR* szInput, TCHAR* szOutput, DWORD cbLen)
{
ZeroMemory(szOutput,cbLen);
WORD index1 = 0;
WORD index2 = 0;
for (; ((index1 < _tcslen(szInput)) && (index2 < ((cbLen/sizeof(TCHAR))-1))); index1++)
{
szOutput[index2] = szInput[index1];
if (szOutput[index2] == TEXT('&'))
{
szOutput[++index2] = TEXT('&');
szOutput[++index2] = TEXT('&');
}
index2++;
}
}
void ShellIconSetTooltip()
{
if (g_fShellIconCreated)
{
NOTIFYICONDATA nData;
nData.cbSize = sizeof(nData);
nData.hWnd = g_hwnd;
nData.uID = SHELLMESSAGE_CDICON;
nData.uFlags = NIF_TIP;
MMMEDIAID mmMedia;
mmMedia.nDrive = -1;
mmMedia.szTrack[0] = TEXT('\0');
g_pAuto->OnAction(MMACTION_GETMEDIAID,&mmMedia);
TCHAR szTempTip[MAX_PATH+sizeof(TCHAR)];
TCHAR szEscapeTip[MAX_PATH+sizeof(TCHAR)];
if ((mmMedia.dwMediaID != 0) || (_tcslen(mmMedia.szTrack)!=0))
{
//128 + 128 + 4 = 260 ... that's max_path
wsprintf(szTempTip,TEXT("%s (%s)"),mmMedia.szTitle,mmMedia.szTrack);
}
else
{
_tcscpy(szTempTip,mmMedia.szTitle);
}
//escape out & symbols if they are in the string
if (_tcschr(szTempTip,TEXT('&')))
{
EscapeTooltip(szTempTip,szEscapeTip,sizeof(szEscapeTip));
_tcscpy(szTempTip,szEscapeTip);
}
//truncate long tip to size of tooltip
szTempTip[(sizeof(nData.szTip)/sizeof(TCHAR))-1] = TEXT('\0');
_tcscpy(nData.szTip,szTempTip);
Shell_NotifyIcon(NIM_MODIFY,&nData);
//bit of a hack, but if we're getting a new tool tip, then we might be need to turn
//on or off the "nodisc" state
CheckDiscState();
}
}
void CreateTransportMenu(CustomMenu* pMenu, CustomMenu* pTransMenu)
{
//play or pause
if (fPlaying)
{
pTransMenu->AppendMenu(IDB_PLAY,g_hInst,IDS_SH_PAUSE);
}
else
{
pTransMenu->AppendMenu(IDB_PLAY,g_hInst,IDS_SH_PLAY);
}
//stop
pTransMenu->AppendMenu(IDB_STOP,g_hInst,IDS_SH_STOP);
//eject
pTransMenu->AppendMenu(IDB_EJECT,g_hInst,IDS_SH_EJECT);
//previous track
pTransMenu->AppendMenu(IDB_PREVTRACK,g_hInst,IDS_SH_PREVTRACK);
//next track
pTransMenu->AppendMenu(IDB_NEXTTRACK,g_hInst,IDS_SH_NEXTTRACK);
pMenu->AppendMenu(g_hInst,IDS_SH_TRANS,pTransMenu);
}
void CreateOptionsMenu(CustomMenu* pMenu, CustomMenu* pOptionsMenu)
{
pOptionsMenu->AppendMenu(IDM_OPTIONS,g_hInst,IDM_OPTIONS);
pOptionsMenu->AppendMenu(IDM_PLAYLIST,g_hInst,IDM_PLAYLIST);
pOptionsMenu->AppendSeparator();
//do not bother graying out the playlist menu, it causes too much delay in odbc load
/*
LPCDDATA pData = GetCDData();
if (pData)
{
if (FAILED(pData->CheckDatabase(g_hwnd)))
{
EnableMenuItem(pOptionsMenu->GetMenuHandle(),
IDM_PLAYLIST,
MF_BYCOMMAND | MF_GRAYED);
}
}
*/
pOptionsMenu->AppendMenu(IDM_HELP,g_hInst,IDM_HELP);
pMenu->AppendMenu(g_hInst,IDS_SH_OPTIONS,pOptionsMenu);
}
void CreateModeMenu(CustomMenu* pMenu, CustomMenu* pModeMenu)
{
pModeMenu->AppendMenu(IDM_MODE_NORMAL,g_hInst,IDI_MODE_NORMAL,IDM_MODE_NORMAL);
pModeMenu->AppendMenu(IDM_MODE_RANDOM,g_hInst,IDI_MODE_RANDOM,IDM_MODE_RANDOM);
pModeMenu->AppendMenu(IDM_MODE_REPEATONE,g_hInst,IDI_MODE_REPEATONE,IDM_MODE_REPEATONE);
pModeMenu->AppendMenu(IDM_MODE_REPEATALL,g_hInst,IDI_MODE_REPEATALL,IDM_MODE_REPEATALL);
pModeMenu->AppendMenu(IDM_MODE_INTRO,g_hInst,IDI_MODE_INTRO,IDM_MODE_INTRO);
pModeMenu->SetMenuDefaultItem(nCDMode,FALSE);
pMenu->AppendMenu(g_hInst,IDS_SH_MODE,pModeMenu);
}
void CreateNetMenu(CustomMenu* pMenu, CustomMenu* pNetMenu, CustomMenu* pSearchSubMenu, CustomMenu* pProviderSubMenu)
{
MMMEDIAID mmMedia;
mmMedia.nDrive = -1;
g_pAuto->OnAction(MMACTION_GETMEDIAID,&mmMedia);
BOOL fContinue = TRUE;
//append static menu choices
if (IsDownloading())
{
pNetMenu->AppendMenu(IDM_NET_CANCEL,g_hInst,IDM_NET_CANCEL);
}
else
{
pNetMenu->AppendMenu(IDM_NET_UPDATE,g_hInst,IDM_NET_UPDATE);
if (mmMedia.dwMediaID == 0)
{
//need to gray out menu
MENUITEMINFO mmi;
mmi.cbSize = sizeof(mmi);
mmi.fMask = MIIM_STATE;
mmi.fState = MFS_GRAYED;
HMENU hMenu = pNetMenu->GetMenuHandle();
SetMenuItemInfo(hMenu,IDM_NET_UPDATE,FALSE,&mmi);
}
}
//if networking is not allowed, gray it out ...
//don't worry about cancel case, it won't be there
LPCDDATA pData = GetCDData();
if (mmMedia.dwMediaID != 0)
{
//don't allow searching if title isn't available
if (pData)
{
if (pData->QueryTitle(mmMedia.dwMediaID))
{
pSearchSubMenu->AppendMenu(IDM_NET_BAND,g_hInst,IDM_NET_BAND);
pSearchSubMenu->AppendMenu(IDM_NET_CD,g_hInst,IDM_NET_CD);
pSearchSubMenu->AppendMenu(IDM_NET_ROLLINGSTONE_ARTIST,g_hInst,IDM_NET_ROLLINGSTONE_ARTIST);
pSearchSubMenu->AppendMenu(IDM_NET_BILLBOARD_ARTIST,g_hInst,IDM_NET_BILLBOARD_ARTIST);
pSearchSubMenu->AppendMenu(IDM_NET_BILLBOARD_ALBUM,g_hInst,IDM_NET_BILLBOARD_ALBUM);
pNetMenu->AppendMenu(g_hInst,IDM_NET_SEARCH_HEADING,pSearchSubMenu);
}
} //end if pdata
}
//display any provider home pages
DWORD i = 0;
LPCDOPT pOpt = GetCDOpt();
if( pOpt )
{
LPCDOPTIONS pCDOpts = pOpt->GetCDOpts();
LPCDPROVIDER pProviderList = pCDOpts->pProviderList;
while (pProviderList!=NULL)
{
TCHAR szProviderMenu[MAX_PATH];
TCHAR szHomePageFormat[MAX_PATH/2];
LoadString(g_hInst,IDS_HOMEPAGEFORMAT,szHomePageFormat,sizeof(szHomePageFormat)/sizeof(TCHAR));
wsprintf(szProviderMenu,szHomePageFormat,pProviderList->szProviderName);
pProviderSubMenu->AppendMenu(IDM_HOMEMENU_BASE+i,szProviderMenu);
pProviderList = pProviderList->pNext;
i++;
} //end while
pNetMenu->AppendMenu(g_hInst,IDM_NET_PROVIDER_HEADING,pProviderSubMenu);
} //end home pages
//display internet-loaded disc menus
if (mmMedia.dwMediaID != 0)
{
if (pData)
{
if (pData->QueryTitle(mmMedia.dwMediaID))
{
LPCDTITLE pCDTitle = NULL;
HRESULT hr = pData->LockTitle(&pCDTitle,mmMedia.dwMediaID);
if (SUCCEEDED(hr))
{
for (i = 0; i < pCDTitle->dwNumMenus; i++)
{
if (i==0)
{
pNetMenu->AppendSeparator();
}
TCHAR szDisplayNet[MAX_PATH];
NormalizeNameForMenuDisplay(pCDTitle->pMenuTable[i].szMenuText,szDisplayNet,sizeof(szDisplayNet));
pNetMenu->AppendMenu(i + IDM_NETMENU_BASE,szDisplayNet);
}
pData->UnlockTitle(pCDTitle,FALSE);
}
} //end if query title
}
}
pMenu->AppendMenu(g_hInst,IDS_SH_NET,pNetMenu);
}
void CreateTrackMenu(CustomMenu* pMenu, CustomMenu* pTrackMenu)
{
int i = 0;
HRESULT hr = S_OK;
while (SUCCEEDED(hr))
{
MMTRACKORDISC mmTrack;
mmTrack.nNumber = i++;
hr = g_pAuto->OnAction(MMACTION_GETTRACKINFO,&mmTrack);
if (SUCCEEDED(hr))
{
pTrackMenu->AppendMenu(mmTrack.nID + IDM_TRACKLIST_SHELL_BASE, mmTrack.szName);
if (mmTrack.fCurrent)
{
pTrackMenu->SetMenuDefaultItem(mmTrack.nID + IDM_TRACKLIST_SHELL_BASE,FALSE);
} //end if current
} //end if ok
} //end while
pMenu->AppendMenu(g_hInst,IDS_SH_TRACK,pTrackMenu);
}
void CreateDiscMenu(CustomMenu* pMenu, CustomMenu* pDiscMenu)
{
int i = 0;
HRESULT hr = S_OK;
while (SUCCEEDED(hr))
{
MMTRACKORDISC mmDisc;
mmDisc.nNumber = i++;
hr = g_pAuto->OnAction(MMACTION_GETDISCINFO,&mmDisc);
if (SUCCEEDED(hr))
{
pDiscMenu->AppendMenu(mmDisc.nID + IDM_DISCLIST_BASE, mmDisc.szName);
if (mmDisc.fCurrent)
{
pDiscMenu->SetMenuDefaultItem(mmDisc.nID + IDM_DISCLIST_BASE,FALSE);
} //end if current
}
}
pMenu->AppendMenu(g_hInst,IDS_SH_DISC,pDiscMenu);
}
void CALLBACK lButtonTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
KillTimer(hwnd,idEvent);
if (fPlaying)
{
g_pAuto->OnAction(MMACTION_PAUSE,NULL);
//ShellIconSetState(PLAY_ICON);
}
else
{
g_pAuto->OnAction(MMACTION_PLAY,NULL);
//ShellIconSetState(PAUSE_ICON);
}
}
LRESULT ShellIconHandeMessage(LPARAM lParam)
{
switch (lParam)
{
case (WM_LBUTTONDOWN) :
{
SetTimer(g_hwnd,SHELLTIMERID,GetDoubleClickTime()+100,(TIMERPROC)lButtonTimerProc);
}
break;
case (WM_LBUTTONDBLCLK) :
{
KillTimer(g_hwnd,SHELLTIMERID);
if ((IsWindowVisible(g_hwnd)) && (!IsIconic(g_hwnd)))
{
ShowWindow(g_hwnd,SW_HIDE);
}
else
{
if (IsIconic(g_hwnd))
{
ShowWindow(g_hwnd,SW_RESTORE);
}
ShowWindow(g_hwnd,SW_SHOW);
BringWindowToTop(g_hwnd);
SetForegroundWindow(g_hwnd);
}
}
break;
case (WM_RBUTTONUP) :
{
if (!fOptionsDlgUp)
{
CustomMenu* pTrackMenu = NULL;
CustomMenu* pDiscMenu = NULL;
CustomMenu* pOptionsMenu = NULL;
CustomMenu* pNetMenu = NULL;
CustomMenu* pSearchSubMenu = NULL;
CustomMenu* pProviderSubMenu = NULL;
CustomMenu* pModeMenu = NULL;
CustomMenu* pTransMenu = NULL;
AllocCustomMenu(&g_pMenu);
AllocCustomMenu(&pTrackMenu);
AllocCustomMenu(&pDiscMenu);
AllocCustomMenu(&pOptionsMenu);
AllocCustomMenu(&pNetMenu);
AllocCustomMenu(&pSearchSubMenu);
AllocCustomMenu(&pProviderSubMenu);
AllocCustomMenu(&pModeMenu);
AllocCustomMenu(&pTransMenu);
if (g_pMenu)
{
g_pMenu->AppendMenu(IDM_ABOUT,g_hInst,IDM_ABOUT);
g_pMenu->AppendSeparator();
CreateTransportMenu(g_pMenu,pTransMenu);
CreateOptionsMenu(g_pMenu,pOptionsMenu);
CreateNetMenu(g_pMenu,pNetMenu,pSearchSubMenu,pProviderSubMenu);
CreateModeMenu(g_pMenu,pModeMenu);
CreateDiscMenu(g_pMenu,pDiscMenu);
CreateTrackMenu(g_pMenu,pTrackMenu);
g_pMenu->AppendSeparator();
g_pMenu->AppendMenu(IDM_EXIT_SHELL,g_hInst,IDM_EXIT);
POINT mouse;
GetCursorPos(&mouse);
RECT rect;
SetRect(&rect,0,0,0,0);
SetForegroundWindow(g_hwnd);
g_pMenu->TrackPopupMenu(0,mouse.x,mouse.y,g_hwnd,&rect);
pTrackMenu->Destroy();
pDiscMenu->Destroy();
pOptionsMenu->Destroy();
pNetMenu->Destroy();
pSearchSubMenu->Destroy();
pProviderSubMenu->Destroy();
pModeMenu->Destroy();
pTransMenu->Destroy();
}
if (g_pMenu)
{
g_pMenu->Destroy();
g_pMenu = NULL;
}
} //end if ok to do
else
{
MessageBeep(0);
}
} //end right-button up
break;
}
return 0;
}
void ShellIconSetState(int nIconType)
{
if (g_fShellIconCreated)
{
int iID = IDI_SHELL_PLAY;
HICON hIcon = hIconPlay;
switch(nIconType)
{
case PAUSE_ICON :
{
iID = IDI_SHELL_PAUSE;
hIcon = hIconPause;
}
break;
case NODISC_ICON :
{
iID = IDI_SHELL_NODISC;
hIcon = hIconNoDisc;
}
break;
}
NOTIFYICONDATA nData;
nData.cbSize = sizeof(nData);
nData.hWnd = g_hwnd;
nData.uID = SHELLMESSAGE_CDICON;
nData.uFlags = NIF_ICON;
nData.hIcon = hIcon;
Shell_NotifyIcon(NIM_MODIFY,&nData);
}
}