Important alert: (current site time 7/16/2013 4:41:04 AM EDT)
 

article

using trayicons

Email
Submitted on: 8/1/2005 11:00:35 AM
By: Lrd.Sandman 
Level: Intermediate
User Rating: By 7 Users
Compatibility: Delphi 7
Views: 19837
 
     Explains how to use the trayicon and switching icons/animating.

 
 
Terms of Agreement:   
By using this article, you agree to the following terms...   
  1. You may use this article in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this article (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this article from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the article or article's description.
				
-TrayIcon

 

Creating trayicons through ShellApi
A trayicon allows your users to access your program without having to view an actual form. Imagine writing a file-packer, it's okay to keep seeing the form if you're using it for 5 minutes. But now there's someone that wants to pack a couple of DVD's. That'll take a long time, possibly days depending on your programs speed. Running the program for a few days isn't a problem for most users, but it'll get killed along the way if you keep it on the taskbar. An explorer error, a miss-click, friends or colleagues that close it and on top of that, most people find not used windows highly annoying.

For all these reasons and more, we're going to implement a trayicon. This is easier then it looks, let's fire up a new project.
First add the shellapi to your 'uses':

uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, shellapi;

This one's obvious, you'll need the shellapi if you want to use it ^_^. Now add a constant below your uses:

const
WM_ICONTRAY = WM_USER + 1;

and insert 'TrayIconData: TNotifyIconData;' under the  form type. Now for the hardest part we'll have to get the icon up and running in the traybar. This is (for now) done in our oncreate event of the form and goes as follows:

with TrayIconData do
begin
   cbSize := SizeOf(TrayIconData);
   Wnd := Handle;
   uID := 0;
   uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
   uCallbackMessage := WM_ICONTRAY;
   hIcon := Application.Icon.Handle;
   StrPCopy(szTip, Application.Title);
end;

if Shell_NotifyIcon(NIM_ADD, @TrayIconData) then

else
   showmessage('failed');

It sets the properties of our tryicon. There are 2 interesting things in this though, the uFlags and the hIcon. Flags are used to indicate what kind of extra's our trayicon will have, here it 'adds' a message, an icon and a tip to our trayicon. There's more information about this below.
The hIcon is an easy one, it sets the icon (in this case to the icon of the application).
Finally the trayicon is actually added to the tray by using shell_notifyIcon. The NIM_ADD basically 'adds' a new trayicon to the traybar with properties TrayIconData (do not forget the @ it's the pointer sign, see below as well).

 

You can already run the above, though when closing the program you'll notice that the trayicon stays until the mouse goes over it. So we have to make sure that the icon is remove when our program stops, put the following line in the ondestroy event of our form:

Shell_NotifyIcon(NIM_DELETE, @TrayIconData);

This should look familiar. It does the same as the one above, but it deletes it instead.
It looks nice and all, but you'll want to use the trayicon for something. Returning a state, menu or just a simple message that your program is still running, so lets add a message when the icon is clicked.

 

Add the following function to the form..

procedure TrayMsg(var Msg: TMessage); message WM_ICONTRAY;

The following code should be in this function:

case Msg.lParam of
     WM_LBUTTONDOWN:
     begin
          ShowMessage('Left button clicked!');
     end;
     WM_RBUTTONDOWN:
     begin
          ShowMessage('Right button clicked!');
     end;
end;

The TrayMsg function receives a WM_ICONTRAY message when your icon is clicked with the left or right mouse button. You can put anything you want in here, though this should make the difference between mouse buttons very clear. WM_LBUTTONDOWN representing the actual downclick (a click consist of a down and a up, like your finger when clicking the mouse) of the left mouse button. WM_RBUTTONDOWN does the same but then for the right button.

Run the program and click your trayicon, handy isn't it?

 

Now (yes as you can see it does matter to us what ppl want) for using different icons and animating. It can be done really easy, create an TIcon and load a icon file and reload the trayicon;

var
   icon1 : TIcon;
   icon2 : TIcon;
   icon3 : TIcon;
begin
   icon1 := TIcon.create;
   icon2 := TIcon.create;
   icon3 := TIcon.create;

   Shell_NotifyIcon(NIM_DELETE, @TrayIconData);

   icon1.loadfromfile('place and name of your icon');
   icon2.loadfromfile('place and name of your icon');
   icon3.loadfromfile('place and name of your icon');

   TrayIconData.hIcon := icon1.handle;     //Or whichever you want to load

   Shell_NotifyIcon(NIM_ADD, @TrayIconData);
end;

The difference with the code at the top of the page is that here we're setting the icon to our own and not that of our application. It unloads the icon (shell_notifyicon(nim_delete[...]) then sets the icon to icon1 and reloads (shell_notifyicon(nim_add[...]) it again, changing the icon on your traybar.

A little side-note here; hIcon is not the actual icon file, it's the handle of the icon file.

 

 

  


Other 7 submission(s) by this author

 


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this article (in the Intermediate category)?
(The article with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments
8/3/2005 5:28:02 AM

Is the extra info still on the site?
(If this comment was disrespectful, please report it.)

 
8/7/2005 7:14:47 PMLrd.Sandman

Yeah update version of the tutorial plus extra info on trayicondata en pointers on
http://devcenter.darkangeldev.com
(If this comment was disrespectful, please report it.)

 
4/6/2008 8:53:38 AMXardas

It gives me an error: Published field 'TrayIconData' not a class nor interface type what i should do ?
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular article, please click here instead.)
 

To post feedback, first please login.