TrayIcon1.SetDefaultMenuItem
(1)
TrayMenu.GetSubMenu
(1)
TrayMenu.LoadMenu
(1)
CVPGAgentDlg
(1)
TrayIcon1.Create
(1)
AfxGetInstanceHandle
(1)
CTrayNotifyIcon
(1)
SetSysTrayIcon
(1)

System tray menu questions.

Asked By dushkin
17-Mar-10 06:02 AM
Hi all.

I have two questions regarding a very simple tray application. The
application does nothing. It only appears in the system tray. I want
to add a floating menu to it with a "close" menu item that will close
the process. The application is an MFC dialog based application. I
work with VS2008.

My questions are:

1. I added a message handler to the "close" menu item. The handler is
called only after I first r-clicking the app icon, select the "close"
item and again r-clicking the app icon in the tray. Why?

2. Then, I put SendMessage(WM_CLOSE) in the handler. The application
was not closed. Why?

The code is as follows:

//-----------------------------------------------------------------
cpp file
//-----------------------------------------------------------------

BEGIN_MESSAGE_MAP(CVPGAgentDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(MYWM_NOTIFYICON,onTrayNotify)
//}}AFX_MSG_MAP
ON_WM_DESTROY()
ON_WM_CLOSE()
ON_COMMAND(ID_AGENTMENU_CLOSE, OnAgentClose)
END_MESSAGE_MAP()

void CVPGAgentDlg::SetSysTrayIcon(void)
{
HICON m_hicon = ::LoadIcon(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_SYSTRAYICON));

CString sTip(_T("PA Agent"));

m_pnId.cbSize = sizeof(NOTIFYICONDATA);
m_pnId.hWnd = this->GetSafeHwnd();
m_pnId.uID = IDI_SYSTRAYICON;
//ICON RESOURCE ID
m_pnId.uFlags = NIF_MESSAGE|NIF_ICON;
m_pnId.uCallbackMessage = MYWM_NOTIFYICON;
m_pnId.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
m_pnId.hIcon = m_hicon;
//ICON RESOURCE ID
lstrcpyn(m_pnId.szTip, (LPCTSTR)sTip, sizeof(m_pnId.szTip));

DWORD dwMessage = NIM_ADD;
Shell_NotifyIcon(dwMessage, &m_pnId);

m_TrayMenu.LoadMenu(IDR_MENU1);
}

LRESULT CVPGAgentDlg::onTrayNotify(WPARAM wParam,LPARAM lParam)
{
UINT uMsg = (UINT) lParam;
switch (uMsg )
{
case WM_LBUTTONDBLCLK:
this->ShowWindow(SW_SHOW);
break;
case WM_RBUTTONUP:
CPoint pt;
GetCursorPos(&pt);

SetForegroundWindow();
m_TrayMenu.GetSubMenu(0)->TrackPopupMenu(TPM_RIGHTALIGN|
TPM_LEFTBUTTON|TPM_RIGHTBUTTON,pt.x,pt.y,this);
PostMessage(WM_NULL, 0, 0);

break;
}
return TRUE;
}

void CVPGAgentDlg::OnAgentClose()
{
AfxMessageBox("a");
//SendMessage(WM_CLOSE);
}

void CVPGAgentDlg::OnDestroy()
{
Shell_NotifyIcon(NIM_DELETE,&m_pnId);
CDialog::OnDestroy();

// TODO: Add your message handler code here
}


//-----------------------------------------------------------------
h file:
//-----------------------------------------------------------------

And please...

dushkin replied to dushkin
17-Mar-10 06:08 AM
And please... I know that there is and AfxMessageBox in the function
and SendMessage is commented... this is not the reason the app is not
closed. It is only part of my tests

When I added this functionality to a recent program I used this class thatPJ

Tom Serface replied to dushkin
17-Mar-10 08:41 AM
When I added this functionality to a recent program I used this class that

http://www.naughter.com/ntray.html

It is very easy to add and does all the things you are asking for...
Basically, you can use the equivalent of a right click menu and the messages
are handled by the mainframe window just like any other messages that you would
typically do from menus or the toolbar.

Tom

tges'd

dushkin replied to Tom Serface
17-Mar-10 09:14 AM
t
ges
'd
PJ has had this for a while, but the technology has not changed much in
Tom Serface replied to dushkin
17-Mar-10 02:55 PM
PJ has had this for a while, but the technology has not changed much in the
last years so it still works really well.  Worth a look anyway.

Tm
FWIW, I could not find anything wrong with your code. It looks fine.
David Ching replied to dushkin
17-Mar-10 05:05 PM
FWIW, I could not find anything wrong with your code.  It looks fine.  You
might want to try PostMessage(WM_CLOSE) instead.  Does it still fail if the
dialog is visible?

Thanks,
David
eTom, I used your classes. Same results.
dushkin replied to Tom Serface
18-Mar-10 05:03 AM
e

Tom, I used your classes. Same results.
Here are the relevant code sections:

CTrayNotifyIcon g_TrayIcon1;

BEGIN_MESSAGE_MAP(CVPGAgentDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_WM_DESTROY()
ON_WM_CLOSE()
ON_COMMAND(ID_AGENTMENU_CLOSE, OnAgentClose)
ON_MESSAGE(WM_TRAYNOTIFY, OnTrayNotification)
END_MESSAGE_MAP()



void CVPGAgentDlg::OnAgentClose()
{
//AfxMessageBox("a");
PostMessage(WM_CLOSE);
}

void CVPGAgentDlg::OnDestroy()
{
CDialog::OnDestroy();

// TODO: Add your message handler code here
m_autoLog.Close();
}

int CVPGAgentDlg::CreateTrayIcon(void)
{
if (!g_TrayIcon1.Create(this, IDR_MENU1, _T("PA Automation Agent"),
m_hIcons[0], WM_TRAYNOTIFY))
{
AfxMessageBox(_T("Failed to create tray icon"), MB_OK |
MB_ICONSTOP);
return -1;
}
//For testing purposes, change the default menu item on the first
icon to be the bottom item on the context menu
g_TrayIcon1.SetDefaultMenuItem(ID_APP_ABOUT, FALSE);

return 0;
}

LRESULT CVPGAgentDlg::OnTrayNotification(WPARAM wParam, LPARAM lParam)
{
//Delegate all the work back to the default implementation in
//CTrayNotifyIcon.
g_TrayIcon1.OnTrayNotification(wParam, lParam);
return 0L;
}
Post Question To EggHeadCafe