Introduction

Welcome to my second article of Simplicity Is Virtue philosophy. Never heard of it? Of course, I created it.. (-: (If you're really interested what the heck is that, then take a look at my first article.) This article is aimed towards beginners, so all of you coding gurus and wizards can skip all of this. In this article, you can learn how to:

create, modify and remove a tray icon

define and use home-made window messages

Before we begin, let me explain why create YET ANOTHER tray icon class, when there are so many of them, free for use. Well, I was browsing the net, searching for a tray icon class, just being lazy of typing my own code. I actually found a whole bunch of them, free, powerful and quite often - loaded with features I don't need. That means - very irritating to use. So I said to myself, Today IS a good day to die, and started coding the most simple tray icon class anyone could ever think of . Let us begin.

Preparations

Before we do anything, let us recall: you create a tray icon by creating a NOTIFYICONDATA structure, and giving it to the Shell_NotifyIcon API function. That tends to be quite irritating, especially if you change the icon or the tooltip frequently during runtime. Because of that, we will create a new class, and provide ourselves a simple and clean interface.

First, we create a new dialog based project, all other options are irrelevant. We begin by adding a new generic class to our project. I named mine "CSimpleTray". Now, we will take care of the private class variables: we need a single icon, a single tooltip, and a single NOTIFYICONDATA structure. Besides that, we would need an indicator whether our icon is shown or not, so we will create a BOOL variable called m_bEnabled. The class should look like this by now:

Now let's see: besides showing and hiding the icon, we want to be able to change the icon and tooltip during runtime, and basically that's all we will do here. Simple interface will consist only of these functions:

void Show();

void Hide();

void SetIcon( HICON hIcon );

void SetTooltip( LPCTSTR lpTooltip );

Still, there is only one thing to think of: we want our icon to actually DO something when our user clicks on it. To implement that, we will make our icon send a notification to the app's main dialog, simply by sending a custom window message. First things first, we will define the message before our tray icon class declaration, like this:

// SimpleTray.h
// at the beggining of the file, before class declaration
#define WM_TRAYNOTIFY WM_APP+1

Now, we need to mess a bit with the dialog itself, add a new protected function declared like this:

afx_msg void OnTrayNotify( WPARAM wParam, LPARAM lParam );

Ok, so now that we have #defined a window message and a function, we need to connect them. You do this by manually adding an entry to the framework's message map:

Note that there is no semicolon at the end of the line. Now, every time our dialog receives WM_TRAYNOTIFY message, it will call the message we created - OnTrayNotify. Of course, you will need to #include the class declaration file, otherwise the compiler will complain that WM_TRAYNOTIFY is not defined.

// TrayDemoDlg.cpp
// at the beggining of the file
#include"stdafx.h"#include"TrayDemo.h"#include"TrayDemoDlg.h"#include"SimpleTray.h" // <--thisone

How to use it?

The most simple way would be to use your applications icon, and show the damn thing at the program startup, inside OnInitDialog(). First, add a private variable of type CSimpleTray to the dialog class:

All you need to do now, is set the icon's behavior, and you do that inside OnTrayNotify. For example, we want to display a menu when a user right clicks on our icon. I created mine like this:

If you press CTRL+W to open the class wizard, you will get a dialog box with two options: to create a new class for your menu, or to select an existing one. Choose "Select an existing class" and press OK. On the next dialog, you can see a list of classes available in your project. The most appropriate class would be your main dialog class, in this case CTrayDemoDlg. Select it and press OK. Now you can edit the code for your popup menu, and it will be inside CTrayDemoDlg class.

We also might want to hide the taskbar button of your dialog, and we can do it inside OnInitDialog(). The demo app demonstrates how to accomplish that, and how to implement a simple "animation" - a flashing tray icon.

THE END - I hope someone will find this article useful in some way! (-:

Copyright

As for the copyright, all of this is copyrighted by me (T1TAN) and my pseudo-company SprdSoft Inc. That means that you can use this code in any app (private or commercial) without any restrictions whatsoever, since our company supports open source and free software. However, if you are going to use (parts of) the code, I'd like to hear from you, just to keep track of things.

If you have any comments, ideas or anything else about the article/code, feel free to contact me, I'd be glad to hear from you.

Greets & good programming!

History

25/01/2004 - First release.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

Do you know how to force the tooltip to popup without the cursor being over the icon? I would like to notify the user of that a new version is available. I can change the icon, but I would also like to popup a message.

I tried the szInfo, but not having much luck. Anyone know how to get this to work in VC6.0.

Have you considered a balloon pop-up[^]? I'm not working in VC6.0 anymore, but you can always extend this class and add the balloon feature yourself (combining my article and the one linked in this post).

If you don't want balloons or find them irritating you can use something like this[^]