364 lines
8.7 KiB
C++
364 lines
8.7 KiB
C++
|
// Tray.cpp
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "tray.h"
|
||
|
|
||
|
#define LEFT_MENU (0)
|
||
|
#define RIGHT_MENU (1)
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
CTrayIcon::CTrayIcon(HWND hWnd, HICON hIcon, LPCTSTR pszText, UINT uID) :
|
||
|
m_iDefaultCmd(-1)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::CTrayIcon", 2)
|
||
|
|
||
|
TRACEENTER(("(hwnd=%x,hIcon=%x,Text=%s,ID=%x)\n",
|
||
|
hWnd, hIcon, pszText, uID));
|
||
|
|
||
|
m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
|
||
|
m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
|
||
|
m_msgTaskbarCreated = RegisterWindowMessage(TEXT("TaskbarCreated"));
|
||
|
|
||
|
memset(&m_nid, 0, sizeof(m_nid));
|
||
|
|
||
|
m_nid.cbSize = sizeof(NOTIFYICONDATA);
|
||
|
m_nid.hWnd = hWnd;
|
||
|
m_nid.uID = uID;
|
||
|
|
||
|
m_nid.uFlags = NIF_MESSAGE;
|
||
|
m_nid.uCallbackMessage = RegisterWindowMessage(TEXT("{D0061156-D460-4230-AF87-9E7658AB987D}"));
|
||
|
|
||
|
if (hIcon)
|
||
|
{
|
||
|
m_nid.uFlags |= NIF_ICON;
|
||
|
m_nid.hIcon = hIcon;
|
||
|
}
|
||
|
|
||
|
if (pszText)
|
||
|
{
|
||
|
m_nid.uFlags |= NIF_TIP;
|
||
|
lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));
|
||
|
}
|
||
|
|
||
|
if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
|
||
|
{
|
||
|
TABSRVERR(("CTrayIcon::CTrayIcon: Shell_NotifyIcon failed (err=%d)\n",
|
||
|
GetLastError()));
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void CTrayIcon::Delete()
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::Delete", 2)
|
||
|
|
||
|
TRACEENTER(("()\n"));
|
||
|
|
||
|
if (m_nid.uFlags & NIF_ICON)
|
||
|
{
|
||
|
m_nid.uFlags = NIF_ICON;
|
||
|
if (!Shell_NotifyIcon(NIM_DELETE, &m_nid))
|
||
|
SetLastError(::GetLastError());
|
||
|
|
||
|
m_nid.uFlags = 0;
|
||
|
|
||
|
// Cleanup the icon...
|
||
|
if (m_nid.hIcon)
|
||
|
{
|
||
|
DestroyIcon(m_nid.hIcon);
|
||
|
m_nid.hIcon = 0;
|
||
|
}
|
||
|
|
||
|
// ...and the menus
|
||
|
HMENU hmLeft = m_hMenu[LEFT_MENU];
|
||
|
if (m_hMenu[LEFT_MENU])
|
||
|
{
|
||
|
DestroyMenu(m_hMenu[LEFT_MENU]);
|
||
|
m_hMenu[LEFT_MENU] = m_hSubMenu[LEFT_MENU] = 0;
|
||
|
}
|
||
|
|
||
|
// watch for right & left menus being the same
|
||
|
if (m_hMenu[RIGHT_MENU] && m_hMenu[RIGHT_MENU] != hmLeft)
|
||
|
{
|
||
|
DestroyMenu(m_hMenu[RIGHT_MENU]);
|
||
|
m_hMenu[RIGHT_MENU] = m_hSubMenu[RIGHT_MENU] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if 0
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HICON CTrayIcon::SetIcon(HICON hIcon)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::SetIcon", 2)
|
||
|
HICON hOldIcon = m_nid.hIcon;
|
||
|
|
||
|
TRACEENTER(("(hIcon=%x)\n", hIcon));
|
||
|
|
||
|
if (hIcon)
|
||
|
{
|
||
|
m_nid.hIcon = hIcon;
|
||
|
m_nid.uFlags |= NIF_ICON;
|
||
|
|
||
|
if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
|
||
|
SetLastError(::GetLastError());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Delete();
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("=%x\n", hOldIcon));
|
||
|
return hOldIcon;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void CTrayIcon::SetText(LPCTSTR pszText)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::SetText", 2)
|
||
|
|
||
|
TRACEENTER(("(Text=%s)\n", pszText));
|
||
|
|
||
|
if (pszText)
|
||
|
{
|
||
|
m_nid.uFlags |= NIF_TIP;
|
||
|
lstrcpyn(m_nid.szTip, pszText, sizeof(m_nid.szTip));
|
||
|
|
||
|
if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
|
||
|
SetLastError(::GetLastError());
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void CTrayIcon::BalloonToolTip(
|
||
|
LPCTSTR pszTitle,
|
||
|
LPCTSTR pszText,
|
||
|
UINT uTimeout,
|
||
|
DWORD dwFlags)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::BalloonToolTip", 2)
|
||
|
UINT uFlags = m_nid.uFlags;
|
||
|
|
||
|
TRACEENTER(("(Title=%s,Text=%s,Timeout=%d,Flags=%x)\n",
|
||
|
pszTitle, pszText, uTimeout, dwFlags));
|
||
|
|
||
|
m_nid.uFlags = NIF_INFO;
|
||
|
m_nid.uTimeout = uTimeout;
|
||
|
lstrcpyn(m_nid.szInfo, pszText, ARRAYSIZE(m_nid.szInfo));
|
||
|
lstrcpyn(m_nid.szInfoTitle, pszTitle, ARRAYSIZE(m_nid.szInfoTitle));
|
||
|
m_nid.dwInfoFlags = dwFlags;
|
||
|
|
||
|
if (!Shell_NotifyIcon(NIM_MODIFY, &m_nid))
|
||
|
{
|
||
|
TABSRVERR(("CTrayIcon::BalloonToolTip: Shell_NotifyIcon failed (err=%d)\n",
|
||
|
GetLastError()));
|
||
|
}
|
||
|
|
||
|
m_nid.uFlags = uFlags;
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#if 0
|
||
|
static VOID CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||
|
{
|
||
|
TRACEPROC("TimerProc", 5)
|
||
|
|
||
|
TRACEENTER(("(hwnd=%x,Msg=%s,EventId=%x,Time=%x)\n",
|
||
|
hWnd, LookupName(uMsg, WMMsgNames), idEvent, dwTime));
|
||
|
|
||
|
KillTimer(hWnd, idEvent);
|
||
|
CTrayIcon* This = reinterpret_cast<CTrayIcon*>(idEvent);
|
||
|
|
||
|
if (This->m_hSubMenu[LEFT_MENU])
|
||
|
This->DoMenu(This->m_hSubMenu[LEFT_MENU]);
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
BOOL CTrayIcon::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
|
||
|
LRESULT& lResult)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::WndProc", 5)
|
||
|
BOOL rc = FALSE;
|
||
|
|
||
|
TRACEENTER(("(hwnd=%x,Msg=%s,wParam=%x,lParam=%x)\n",
|
||
|
hWnd, LookupName(uMsg, WMMsgNames), wParam, lParam));
|
||
|
|
||
|
if (uMsg == m_msgTaskbarCreated)
|
||
|
{
|
||
|
lResult = OnTaskbarCreated();
|
||
|
rc = TRUE;
|
||
|
}
|
||
|
else if (uMsg == m_nid.uCallbackMessage)
|
||
|
{
|
||
|
lResult = OnNotify(lParam);
|
||
|
rc = TRUE;
|
||
|
}
|
||
|
else if (uMsg == WM_DESTROY)
|
||
|
{
|
||
|
// Our controlling window is being destroyed. Clean up if we
|
||
|
// haven't already, then pass on the WM_DESTROY
|
||
|
Delete();
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("=%x\n", rc));
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
LRESULT CTrayIcon::OnNotify(LPARAM lParam)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::OnNotify", 2)
|
||
|
TRACEENTER(("(lParam=%x)\n", lParam));
|
||
|
|
||
|
switch (lParam)
|
||
|
{
|
||
|
case WM_LBUTTONUP:
|
||
|
if (m_iDefaultCmd != -1)
|
||
|
PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
|
||
|
break;
|
||
|
|
||
|
#if 0
|
||
|
case WM_LBUTTONDOWN:
|
||
|
SetTimer(m_nid.hWnd, (UINT_PTR)this, GetDoubleClickTime(), TimerProc);
|
||
|
break;
|
||
|
|
||
|
case WM_LBUTTONDBLCLK:
|
||
|
KillTimer(m_nid.hWnd, (UINT_PTR)this);
|
||
|
|
||
|
if (m_iDefaultCmd != -1)
|
||
|
PostMessage(m_nid.hWnd, WM_COMMAND, m_iDefaultCmd, 0);
|
||
|
break;
|
||
|
#endif
|
||
|
|
||
|
case WM_RBUTTONUP:
|
||
|
if (m_hSubMenu[RIGHT_MENU])
|
||
|
DoMenu(m_hSubMenu[RIGHT_MENU]);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("=0\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
LRESULT CTrayIcon::OnTaskbarCreated()
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::OnTaskbarCreated", 2)
|
||
|
TRACEENTER(("()\n"));
|
||
|
|
||
|
if (m_nid.hWnd && m_nid.hIcon && (m_nid.uFlags & NIF_ICON))
|
||
|
{
|
||
|
if (!Shell_NotifyIcon(NIM_ADD, &m_nid))
|
||
|
{
|
||
|
TABSRVERR(("CTrayIcon::OnTaskbarCreated: Shell_NotifyIcon failed (err=%d)\n",
|
||
|
GetLastError()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("=0\n"));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
HMENU CTrayIcon::SetSubMenu(BOOL fLeftMenu, HMENU hMenu, int nPos)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::SetSubMenu", 2)
|
||
|
int idx = (fLeftMenu) ? LEFT_MENU : RIGHT_MENU;
|
||
|
HMENU hOldMenu = m_hMenu[idx];
|
||
|
|
||
|
TRACEENTER(("(fLeftMenu=%d,hMenu=%x,Pos=%d)\n", fLeftMenu, hMenu, nPos));
|
||
|
|
||
|
m_hMenu[idx] = m_hSubMenu[idx] = hMenu;
|
||
|
|
||
|
if (hMenu && nPos >= 0)
|
||
|
{
|
||
|
m_hSubMenu[idx] = GetSubMenu(hMenu, nPos); //NO TYPO
|
||
|
}
|
||
|
|
||
|
if (idx == LEFT_MENU)
|
||
|
{
|
||
|
m_iDefaultCmd = -1;
|
||
|
|
||
|
if (hMenu && m_hSubMenu[idx])
|
||
|
m_iDefaultCmd = GetMenuDefaultItem(m_hSubMenu[idx], FALSE, 0);
|
||
|
}
|
||
|
|
||
|
TRACEEXIT(("=%x\n", hOldMenu));
|
||
|
return hOldMenu;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void CTrayIcon::DoMenu(HMENU hMenu)
|
||
|
{
|
||
|
TRACEPROC("CTrayIcon::DoMenu", 2)
|
||
|
POINT pt;
|
||
|
UINT iCmd;
|
||
|
TCHAR tszMenuText[128];
|
||
|
|
||
|
TRACEENTER(("(hMenu=%x)\n", hMenu));
|
||
|
GetCursorPos(&pt);
|
||
|
|
||
|
SetForegroundWindow(m_nid.hWnd); // necessary?
|
||
|
|
||
|
LoadString(ghMod,
|
||
|
gdwfTabSrv & TSF_SUPERTIP_OPENED?
|
||
|
IDS_HIDE_SUPERTIP: IDS_SHOW_SUPERTIP,
|
||
|
tszMenuText,
|
||
|
ARRAYSIZE(tszMenuText));
|
||
|
ModifyMenu(hMenu,
|
||
|
IDM_OPEN,
|
||
|
MF_BYCOMMAND | MF_STRING,
|
||
|
IDM_OPEN,
|
||
|
tszMenuText);
|
||
|
|
||
|
LoadString(ghMod,
|
||
|
gdwfTabSrv & TSF_PORTRAIT_MODE?
|
||
|
IDS_SCREEN_LANDSCAPE: IDS_SCREEN_PORTRAIT,
|
||
|
tszMenuText,
|
||
|
ARRAYSIZE(tszMenuText));
|
||
|
ModifyMenu(hMenu,
|
||
|
IDM_TOGGLE_ROTATION,
|
||
|
MF_BYCOMMAND | MF_STRING,
|
||
|
IDM_TOGGLE_ROTATION,
|
||
|
tszMenuText);
|
||
|
|
||
|
iCmd = TrackPopupMenu(hMenu, /* TPM_RETURNCMD | */ TPM_NONOTIFY | TPM_RIGHTBUTTON,
|
||
|
pt.x, pt.y, 0, m_nid.hWnd, NULL);
|
||
|
|
||
|
PostMessage(m_nid.hWnd, WM_NULL, 0, 0); // MS doucmented work-around for taskbar menu
|
||
|
// problem with TrackPopupMenu - still needed?
|
||
|
|
||
|
//PostMessage(m_nid.hWnd, WM_COMMAND, iCmd, 0);
|
||
|
|
||
|
TRACEEXIT(("!\n"));
|
||
|
return;
|
||
|
}
|