Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

363 lines
8.7 KiB

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