 |

|
Noce but you should now update this for c#
cheers,
Donsw
My Recent Article : Backup of Data files - Full and Incremental
|
|
|
|

|
The current code does not delete the icon from the system tray unless you move the mouse over it.
To fix this problem, you simply need to add a default block to the OnTrayNotify function.
LONG MyDialog::OnTrayNotify ( WPARAM wParam, LPARAM lParam )
{
switch (lParam)
{
case MyMessageID:
{
break ;
}
default:
{
DefWindowProc(WM_TRAY_NOTIFY, wParam, lParam);
}
break;
}
return (0) ;
}
By the way. Thanks for the great class, it saved me much pain.
|
|
|
|

|
Hi Ash,
This is a great code that is very easy to use. However, when I run my application as service, my icon is not loaded although the application is running. I have done some searching on the web and one of the reason given is because my application is now service, it will load my application before the system tray is available. Therefore, it failed to load the icon.
I am wondering if you are able to monitor if the icon is successfully loaded onto the system tray? I tried using m_pTray, but that does not help. If you are able to monitor if the icon is successfully loaded or not, then I will be able to write a routine to re-load the icon until it is successfully loaded onto the system tray.
Please help.
|
|
|
|

|
I really like this app. I had gone through many other tray icon apps, but found this one very small and good one.
Very simply we can add tray functionality to our existing application.
Thanks
Yogesh V Dhongade
|
|
|
|

|
Hi I've been looking for the small nuisance that my application currently has, so I posted a help to MSDN newsgroup but no one answered so far. After I saw your post, I was hoping that I could use yours, but when I tested, yours also behaved the same, i.e. when I right-click on the icon, not only your "Restore" popup menus but also the taskbar popup menu, such as, "Toolbars", "Adjust Date/Time", etc. are displayed, so "Restore" menu is displayed behind the taskbar menus and eventually it is hidden.
If I right-click one more time, then only "Restore" menu is displayed. This happens alternatively. In other words, if I click again, then both menus are displayed.
I'd REALLY appreciate it if anyone can show me how to resolve this.
Here is my post to MSDN:
++++++++++++++++++++++++++++++++++++++++++++
I wrote an MFC program whose icon, tooltip and menus are available in systray.
When I right-click on the icon, not only my popup menus but also the taskbar popup menu, such as, "Toolbars", "Adjust Date/Time", etc. are displayed.
If I right-click one more time, then only my menus are displayed. This happens alternatively. In other words, if I click again, then both menus are displayed.
I followed the exact steps that were posted on MSDN, such as,
afx_msg LONG CAutoUpdatesDlg::OnSysTrayIconClick( WPARAM wParam, LPARAM lParam )
{
switch (lParam){
case WM_LBUTTONDOWN:
OnSysTrayInstallupdates();
break;
case WM_RBUTTONDOWN:
ShowTrayPopupMenu();
break ;
}
// PostMessage( WM_NULL, 0, 0 );
return 0;
}
void CAutoUpdatesDlg::ShowTrayPopupMenu()
{
CMenu mnTrayPopup;
mnTrayPopup.LoadMenu(IDR_TRAY_POPUP);
POINT CurPos;
GetCursorPos (&CurPos);
CMenu *mnItem1 = mnTrayPopup.GetSubMenu(0);
SetForegroundWindow();
mnItem1->TrackPopupMenu( TPM_RIGHTBUTTON | TPM_RIGHTALIGN,
CurPos.x, CurPos.y, this );
PostMessage( WM_NULL, 0, 0 );
}
Is this a VC7 bug? Or am I missing anything?
TIA.
|
|
|
|

|
I owe you an apology. For some reason, that behavior occurs only my development machine. When I tested yours and my app on the different XP, the popup menus were displayed correctly without any problem that I described earlier.
So now I am wondering what caused it on my machine.
Thanks.
|
|
|
|

|
I'm having the same problem here.
|
|
|
|

|
I managed to avoid this problem by handling the WM_RBUTTONUP message instead of the WM_RBUTTONDOWN
|
|
|
|

|
1) There is erroneous behavior in the code in that if you right-click on the tray icon then click on another application window (making it active), then left-mouse click or right-click and RESTORE... it will restore the window, but it will be behind the previously active window, thus not visible.
To correct this behavior modify the OnTrayRestore() function as follows:
if (m_bHidden)
{
ShowWindow (SW_RESTORE) ;
CRect rectWindow;
GetWindowRect(&rectWindow);
SetWindowPos(&wndTopMost, rectWindow.left, rectWindow.top,
rectWindow.Width(), rectWindow.Height(), SWP_SHOWWINDOW);
m_bHidden = FALSE ;
}
This will always restore your window to the top of the z-order (other topmost windows excepted of course).
2) If you're running a true tray app, it's probably not a good idea for users to be able to terminate an application with the ESC key, or the close button on the window. Valuable data may be accidentally lost in this way, not to mention it defeats the purpose of running it in the tray.
To correct this, I added an EXIT item on the popup menu, giving the handling function this code: m_ExitCode=1; exit(1); I then simply overrode the OnClose() function, where I deleted the call to base class and inserted the following code: if(m_ExitCode != 1)
OnHide();
This way the application can only be terminated from the tray menu. Much tidier I think.
GREAT CODE. Thanks for sharing. I will definitely use it. I hope these suggestions were helpful.
In business, if two people always agree, one of them is unnecessary.
|
|
|
|

|
Hi ashman,
First like to say it was really a nice piece of code.
Two problems observed....
(1) if you kill the process of trayicon the icon does not get removed from system tray till you bring mouse over it.. can by some means... taskbar icons can be refreshed.
(2) On win 98/me double click activity doesnot work.. perhaps wm_lbtndblclk have some limitation.. how to overcome..
bye
smarty
|
|
|
|

|
For question 2:
Head towards OnTrayRestore() in yourProgramDlg.cpp.
Remove the line m_bHidden = FALSE;
So your code should look like this:
void CYourProgamDlg::OnTrayRestore()
{
if(m_bHidden)
ShowWindow(SW_RESTORE);
}
Now you can hide and restore and double click to your hearts content
Im not sure about question one sorry.
Will update my article.
Thanks
Ashman
I'm normally not a praying man, but if you're up there, please save me Superman.
|
|
|
|

|
Hello ashman,
I want to perform some different functionality wrt double click.. so can you tell me how is there any message can be captured apart from wm_lbtndblclk(as this one not work on win98)... i hope so you got my point...
Bye
|
|
|
|

|
You are going to have to extend on your question. I didn't quite understand. Are you saying you want to use another mouse flag rather than dblclick to open the tray icon?
Thanks
Ashman
I'm normally not a praying man, but if you're up there, please save me Superman.
|
|
|
|

|
Hello ashman,
It works...
I was trying to integrate your code on a demo project with some other ui dialog. There in case of win 98/me I found double click was not working.
I had a impression wm_dblclk message not working...
But that was not the case ... It was due to error which states that an outgoing call can be made only when the incoming calls were depleted.. I freed up the message queue before making any outer calls
I solved it..
thxs a lot... Had done it...
Bye
smarty9071
|
|
|
|

|
it seems that the domodal function automatically set the window as visible
how to start a dialog based application in the tray without showing the dialog at all before you click on the icon?
I don't want a "hide it just after creating it" method : that makes a noticeable flipping window
thanks!
|
|
|
|

|
Hi,
u can apply a trick...
use timer to hide the dialog window after 2 second in your main application.
or logically use the following code to hide the dialog inside initinstance of your app
CWnd* pWnd = CWnd::GetDesktopWindow();
m_pMainWnd = m_pDlg;
m_pDlg->Create(,pWnd);
m_pDlg->ShowWindow(SW_HIDE);
remove the doModal code..
bye
smarty 9071
|
|
|
|
|

|
I tested the demo at my machine, I found when I repeat to hide and restore several times, it will not work correctly.
Is it has a bug or my machine has some problem?
The environment of the demo runs at is Windows 2000 anc VC6.
|
|
|
|

|
Hey ashman
Excellent work. This is one of the best examples for a newbie that I've seen on this site. A lot of the times, authors label the article for a beginner, and then leave out this or that and it makes the beginner (like myself) pull out his hair trying to figure out why there are 79 compiler errors. A lot of other times, they slap a beginner example together, and it's great, but there's no walkthrough to tell beginners how to take their code and put it in yours.
This is a great example. Everything that you need to make it work in your own application.
You've got my 5 vote. Keep up the good work, and thanks for the efforts!
Shultas
|
|
|
|

|
I have windows XP and I want my program to automatically slip into tray without showing itself before.
HideApplication() works when I click on a button which triggers HideApplication() but not when I use it in BOOL CMyDlg::OnInitDialog(){
...
AfxGetApp()->HideApplication();
...
} or in
LRESULT CMyDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam){
...
if(message==WM_SHOWWINDOW){
AfxGetApp()->HideApplication();
}
...
}
How could I get the window closing when program initialised?
---
Blääh
|
|
|
|

|
Hey there
Why r u using AfxGetApp? There is a call: theApp.hideapplication(); in YourProgam.cpp or you should add one anyways.
This way in your initdialog(); you can use OnHide(); no need to call hideapplication because that would just hide the program and not set m_tray to true or false for the icon. Tell me if that helps or not. I have updated this code recently so it works more efficiantly.
Ashman
|
|
|
|

|
Hi dear,
The program is simply great. I used your code in my application. I am developing an application using MFC VC++ Version 6.0 for Windows 2000.
I have made my application run as a service. The application starts with an icon in the System tray. On double clicking the icon the application starts (ie. dialog boxes are displayed, some background operations are performed, etc..)
The application works very fine when i restrat the system i.e. the system tray icon appears and it performs the apporpriate functions . But when i loggoff the system and then loggin, the tray icon is freezed!!!
The tray icon then doesnot responds to the mouse events (double click , single click or right click)
I know that during loggoff the service keeps on running. And the application is performing its background operations also during loggoff, but the tray icon stops responding.
Do I need to refresh the tray icon ???? Or any alternate solution to above problem
Rohit
|
|
|
|

|
hi
i saw a good article about windows and logging out. It is a common problem. Ill see if I can find it, as i never have thought about that :S
Thanks for bringing up this problem though. Ill get onto it
Ashman
|
|
|
|

|
Dear Sir,
Thanks a lot for replying. I searched through net and got the solution. What is did is:
STEP1) I deleted the icon as soon as the log off event came
STEP2) Then created the icon again upon loggin in
STEP1)
///////deleting the icon upon log off
void CDRSDlg::OnEndSession(BOOL bEnding)
{
TRACE("\nInside EndSession");
const MSG* pMsg ;
pMsg = GetCurrentMessage();
if ( pMsg->lParam & ENDSESSION_LOGOFF )
{
TRACE("\nInvoking LOGOFF_EVENT");
deletesysicon();
}
}
//////////////////////
STEP2)
and then upon detecting the login i created the system tray icon ,for that i used some trick
And the problem was solved. Please send your valuable comments on this and any alternate solution.
Regards,
Rohit
|
|
|
|

|
Hi Ashley,
Thanks for a good tutorial.. There are some small additions/corrections to pieces of the code that would make it more usefull for future readers..
1) SetState... Shell_Notify Works Ok, but change like this an we will not refresh unless the icon is changing..
void CTrayNot::SetState(int id)
{
if (!m_bEnabled)
return;
if (m_tnd.hIcon != m_pIconList[id]) //OHM: 20030831 Only if The Icon is Changing
{
m_tnd.hIcon = m_pIconList[id];
Shell_NotifyIcon(NIM_MODIFY, &m_tnd);
}
}
2) New function (declare as appropriate..)
void CTrayNot::SetTip(LPCTSTR szTip)
{
if (m_bEnabled) //OHM: 20030831 Tray is Active
strcpy ( m_tnd.szTip, szTip); //OHM: 20030831 Tool Tip Text
}
3) Calling SetState should not be like this;
m_pTray->SetState(IDR_MAINFRAME); //IDR_MAINFRAME is defined like 128 in integer..
//But rather Like This
m_pTray->SetState(0); //Consistent with the first IDR_MAINFRAME resource loaded in position 0... (will also fix the dissapearing icon in SetState)..
Beyond That I think its Great..
Finally you may want to override WM_WINDOWPOSCHANGING Message(OnWindowPosChanging(WINDOWPOS* lpwndpos);) in your dialog like this;
void CYourDialogClass::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
if(!bVisible) //OHM: If Dialog is Hidden
lpwndpos->flags &= ~SWP_SHOWWINDOW;
CDialog::OnWindowPosChanging(lpwndpos);
}
Remember to Set;
bVisible = false; //OHM: Used to Control if Dialog is Visible
in the Dialogs Constructor..
Now Call Like this to show / Hide the Dialog;
Show:
bVisible = true;
this->ShowWindow(SW_SHOW);
Hide:
bVisible = false;
this->ShowWindow(SW_HIDE);
Best Regards,
Henrik Ohm
|
|
|
|

|
Uh,
I guess that I forgot that SetTip also needs to call Shell_NotifyIcon....
void CTrayNot::SetTip(LPCTSTR szTip)
{
if (!m_bEnabled) //OHM: 20030831 Tray is NOT Active
return;
if (m_tnd.szTip != szTip) //OHM: 20030831 Only if The Tip is Changing
{
strcpy ( m_tnd.szTip, szTip); //OHM: 20030831 Tool Tip Text
Shell_NotifyIcon(NIM_MODIFY, &m_tnd); //OHM: Make Sure that the new Tip is Displayed
}
}
/Henrik
|
|
|
|

|
what kind of base class is it?
|
|
|
|

|
How can we start out dialog minimized
|
|
|
|

|
To start your program with the dialog minimised, put a call to OnHide(); in your OnInitDialog(); function. You may also need to initiate a timer, I think I required a timer in order to get the program to hide properly:
BOOL CYourProgramDlg::OnInitDialog()
{
CDialog::OnInitDialog();
....
....
....
....
SetTimer(2, 1000, NULL);
m_pTray = NULL ;
OnHide();
}
In your OnTimer() function, make sure you include OnHide();
See how that works, if not email me and Ill send you a tutorial demo.
Thanks
Ashley Rowe (Ashman)
|
|
|
|

|
Ashman wrote: BOOL CYourProgramDlg::OnInitDialog()
{
CDialog::OnInitDialog();
....
....
....
....
SetTimer(2, 1000, NULL);
m_pTray = NULL ;
OnHide();
}
Hi, Hashman!
I don't know if you are supporting "System Tray Icons" anymore, but I can't let it start minimized (I spent two ours on this task!). Can You please send detailed code ?
Thanks in advance !!!
Marcolino
|
|
|
|

|
In TrayNot.cpp, make a one line addition as below: CTrayNot::~CTrayNot() { if (m_bEnabled) { m_tnd.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP ; // add this line Shell_NotifyIcon (NIM_DELETE, &m_tnd); } } ScorpioMidget
|
|
|
|

|
hey, thanks for the great code it does exactly what i want on your demo. but in my implimentation, the dialog disapperes but no icon is added to the tray so there's no way to get it back. any sugestions? thanks georgeo
|
|
|
|

|
That happened to me quite a few times. Basically, your code isn't ordering the program to go through the processes of OnHide(), in other words all it is calling is: theApp.HideApplication();
In order to get past this, I would suggest creating a new function and calling it say,
HideProgram(); and within this function making a call to OnHide();
void CYourProgramDlg::HideProgram()
{
// Destroy the window, and update the mainframe.
OnHide();
}
Try that, again if it doesnt work, send me an email and Ill send you a working demo.
Thanks, Ashman
|
|
|
|

|
I had the same problem.
It was because I had put the 3 lines which initialise the icons (in the APP Class) after the call to DoModal. The application was in the task bar, but with no icon...
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
// Load Icons for Tray ***** BEFORE calling DoModal !!! *******
m_pIconList[0] = LoadIcon (MAKEINTRESOURCE(IDR_MAINFRAME));
m_pIconList[1] = LoadIcon (MAKEINTRESOURCE(IDR_MAINFRAME));
m_pIconList[2] = LoadIcon (MAKEINTRESOURCE(IDR_MAINFRAME));
CCTCAgentDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
|
|
|
|

|
The problem was solved when I added OnHide() here :
void CYourDlg::OnHideapp()
{
//This will be the onclick for the hide button
//in order to call that the app is minimised.
theApp.HideApplication();
OnHide(); //Icon will appear if you add this.
}
Thanks to the author for the code, saved hours for me.
|
|
|
|

|
Hi Ashley,
Thank you very much for your great work.
I have been trying to find a way to destroy the icon on the tray immediately after my application terminates. I tried every trick to no avail.
Now I follow your trick and it works!
The trick is to deallocate the NOTIFYICONDATA object immediately after Shell_NotifyIcon (NIM_DELETE, &m_tnd). The implication is to use pointer and allocate memory on the fly
and then deallocate after use.
Hoc
|
|
|
|

|
Exactly what I wanted! I looked at all the other implementations, but they were too confusing to add to my existing project. Your's is perfect!
Thanks for taking the time to do this and share it with the rest of us!
|
|
|
|

|
Hi! And how can I do it for SDI aplication ? Thanks. Termi
|
|
|
|

|
Hi, I was looking for just that, a way to minimize my app in the system tray! The only thing that I think you can improve is how you display your code on the web. If you put code marks between your code, I think it would make your code easier to read. For example: <code> Your code </code> Thanks again, ~Selevercin
|
|
|
|

|
Hi little but Great brain,
First time I clicked on hide dialog it got hidden & I said restore, dialog came up.
again I clicked on hide dialog it got hidden & I said restore but this time dialog did not pop up...
I had to remove it from task manager...
is it coz' of I am using win2k server...
Just check it & tell me...
Keep it up...
Paresh..
|
|
|
|

|
Hi,
I think he has forgotten to update the 'm_bHidden' variable in the OnHideapp() & CANCEL() functions . Insert
m_bHidden = TRUE;
in both the above said functions & it should be okay.
- Anil
|
|
|
|

|
Paresh
I am trying to creat system tray icon to my application. Able to create that but do not know how to handle on Right button. I have like min, max, about etc in that icon and I would appreciate if u let me know how to handle the code after press right button. Try to sample code if possible
MS
MS
|
|
|
|

|
I don't know, why you emphasize your age several times. Nevertheless, since you have posted an article on CodeProject, you should learn to browse here before. Perhaps someone else has covered this topic already. In this case the one and only CodeProject leader himself, Chris Maunder. Have a look at his article. So you do not have ro re-invent the wheel.
Regards
Thomas
Finally with Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|

|
Oh, I hadn't realised. I get confused between codeguru and codeproject and everything on them. I said my age twice, I didnt realise that the script would add the "About me" again. I emphasised my age so that none of you pros would ask questions I wouldn't be able to understand.
I wrote this article for other beginners like me who don't know the ways of teaching by such people like Chris. They write very good articles, but for some...understanding them is hard, I just wanted to try and explain it but also show how to set it so that when the dialog starts up, the icon will sit in the tray and not hide the window untill the button is pressed.
Anyways sorry
Ashley
http://www.settlers.net
|
|
|
|

|
Hehe, you remind me of what I was like in my early teens . Keep up the good stuff, and don't let these old farts get ya down.
Cheers,
swine
====================================
Check out Aephid Photokeeper, the POWERFUL digital
photo album solution at http://www.aephid.com
|
|
|
|

|
keep on innovating the wheel!....or find a replacement for the wheel...keep up the good work!
|
|
|
|

|
I really think he did a great article for a 15 years old guy. I didn't even know MFC nor Windows at its age. I was on my Atari ^^.
Moreover I really think it's not a "wheel" problem because he learnt a few things by developing its own System Tray system so he only wanted to share its knowledge with us. So the most important thing for us, it's not to avoid reinventing the wheel but trying to learn from each other.
Jean-Marc Molina
Email: jmmolina@ifrance.com
Web: http://goa.ifrance.com
|
|
|
|

|
Don't let that jealous punk get you down. He's just mad because you're half his age and twice as smart.
|
|
|
|

|
That's not fair
Regards
Thomas
Finally with Sonork id: 100.10453 Thömmi
Disclaimer: Because of heavy processing requirements, we are currently using some of your unused brain capacity for backup processing. Please ignore any hallucinations, voices or unusual dreams you may experience. Please avoid concentration-intensive tasks until further notice. Thank you.
|
|
|
|

|
xufei
|
|
|
|
 |