Re: Gray out a system tray menu entry.
Your suggestions don't help me.
Years ago I picked up a system tray helper class from somewhere. I've used it in a bunch of programs
and enhanced it a couple of times. I'd rather modify the existing class then switch to a different
class. In this case I want to be able to include a grayed out menu item.
The class is actually two classes. The base class I just link in. I then instantiate the inherited
class and make some modifications in the inherited class and everything works.
The class does NOT use MFC command routing. Instead I believe it creates a window and uses the
WindowProc shown below. If the message is a certain type it calls OnTrayNotification which is also
shown below. Within OnTrayNotification is a call to CustomizeMenu which clears the menu and then
calls ::AppendMenu a bunch of times to add menu entries. I have tried setting the flags in
::AppendMenu to make a grayed out entry, but the system seems to ignore the gray out flag and makes
the menu entry full function.
Is there some other method or place where I can tell the system to gray out a system tray menu entry?
// This is the global (static) callback function for all TrayIcon windows
LRESULT PASCAL ZPsiSystemTray::WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// The option here is to maintain a list of all TrayIcon windows,
// and iterate through them. If you do this, remove these 3 lines.
ZPsiSystemTray* pTrayIcon = m_pThis;
if (pTrayIcon->GetSafeHwnd() != hWnd)
return ::DefWindowProc(hWnd, message, wParam, lParam);
// If maintaining a list of TrayIcon windows, then the following...
// pTrayIcon = GetFirstTrayIcon()
// while (pTrayIcon != NULL)
// {
// if (pTrayIcon->GetSafeHwnd() != hWnd) continue;
// Taskbar has been recreated - all TrayIcons must process this.
if (message == ZPsiSystemTray::m_nTaskbarCreatedMsg)
return pTrayIcon->OnTaskbarCreated(wParam, lParam);
// Animation timer
if (message == WM_TIMER && wParam == pTrayIcon->GetTimerID())
return pTrayIcon->OnTimer(wParam);
// Settings changed
if (message == WM_SETTINGCHANGE && wParam == pTrayIcon->GetTimerID())
return pTrayIcon->OnSettingChange(wParam, (LPCTSTR) lParam);
// Is the message from the icon for this TrayIcon?
if (message == pTrayIcon->GetCallbackMessage())
return pTrayIcon->OnTrayNotification(wParam, lParam);
// pTrayIcon = GetNextTrayIcon();
// }
// Message has not been processed, so default.
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
//-----------------------------------------------------------------------------
LRESULT ZPsiSystemTray::OnTrayNotification(UINT wParam, LONG lParam)
{
//Return quickly if its not for this tray icon
if (wParam != m_tnd.uID)
return 0L;
HWND hTargetWnd = GetTargetWnd();
if (!hTargetWnd)
return 0L;
// Clicking with right button brings up a context menu
#if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
BOOL bAltPressed = ((GetKeyState(VK_MENU) & (1 << (sizeof(SHORT)*8-1))) != 0);
if (LOWORD(lParam) == WM_LBUTTONUP && bAltPressed)
#else
if (LOWORD(lParam) == WM_RBUTTONUP)
#endif
{
HMENU hMenu = ::LoadMenu(m_hInstance, MAKEINTRESOURCE(m_tnd.uID));
if (!hMenu)
return 0;
HMENU hSubMenu = ::GetSubMenu(hMenu, 0);
if (!hSubMenu)
{
::DestroyMenu(hMenu); //Be sure to Destroy Menu Before Returning
return 0;
}
// customize the menu
// check if the menu should be displayed
// true = indicataes normal processing
// false = menu is not displayed or activated
// this allows the host to shut down the menu if desired
if (true == CustomizeMenu(hSubMenu))
{
#ifndef _WIN32_WCE
// Make chosen menu item the default (bold font)
::SetMenuDefaultItem(hSubMenu, m_DefaultMenuItemID, m_DefaultMenuItemByPos);
#endif
// Display and track the popup menu
POINT pos;
#ifdef _WIN32_WCE
DWORD messagepos = ::GetMessagePos();
pos.x = GET_X_LPARAM(messagepos);
pos.y = GET_Y_LPARAM(messagepos);
#else
GetCursorPos(&pos);
#endif
::SetForegroundWindow(m_tnd.hWnd);
::TrackPopupMenu(hSubMenu, 0, pos.x, pos.y, 0, hTargetWnd, NULL);
// Required. Read manual page for TrackPopupMenu for details.
::PostMessage(m_tnd.hWnd, WM_NULL, 0, 0);
}
// destroy the menu
DestroyMenu(hMenu);
}
#if defined(_WIN32_WCE) //&& _WIN32_WCE < 211
if (LOWORD(lParam) == WM_LBUTTONDBLCLK && bAltPressed)
#else
else if (LOWORD(lParam) == WM_LBUTTONDBLCLK)
#endif
{
// double click received, the default action is to execute default menu item
::SetForegroundWindow(m_tnd.hWnd);
UINT uItem;
if (m_DefaultMenuItemByPos)
{
HMENU hMenu = ::LoadMenu(m_hInstance, MAKEINTRESOURCE(m_tnd.uID));
if (!hMenu)
return 0;
HMENU hSubMenu = ::GetSubMenu(hMenu, 0);
if (!hSubMenu)
return 0;
uItem = ::GetMenuItemID(hSubMenu, m_DefaultMenuItemID);
DestroyMenu(hMenu);
}
else
uItem = m_DefaultMenuItemID;
::PostMessage(hTargetWnd, WM_COMMAND, uItem, 0);
}
return 1;
}
Ajay Kalra wrote:
On Jun 10, 12:20 am, TonyG <To...@junk.com> wrote:
Where do I use EnableMenuItem? I placed it near my AppendMenu and it didn't work. It is as if the
system is enabling all menu items.
How can I make this work?
Ajay Kalra wrote:
Use EnableMenuItem to enable/disable the menu item.
---
Ajay
"TonyG" <To...@junk.com> wrote in message
news:D6l3k.4737$89.1838@nlpi069.nbdc.sbc.com...
How do I gray out an entry in a system tray menu?
When I call ::append menu I have tried to set MF_GRAYED and it didn't
work. Can I make an entry gray? Perhaps is there some message I should
trap in my WindowProc?
Is there something else I should do?
If this menu is part of MFC's command routing, you will need to use
ON_UPDATE_COMMAN_UI mecahism as shown by AliR, otherwise
EnableMenuItem should work. Please show your code if its not working.
--
Ajay