|
Delphi Tips and Tutorials
System tray icons tutorial
Part 1 - Creating a system tray icon
Delphi tips and tutorials -> System tray icons tutorial -> Part 1 -> Part 2 -> Part 3
Part 1 Introduction
By the end of this tutorial, you will be able to:
- Write an application in Delphi which will show an icon in the system tray, and also remove this icon.
Source code for this tutorial
This tutorial starts from scratch to help you better understand the steps required to create a system tray icon.
If you do not want to follow the steps yourself, you can download the source code in an example project by clicking here.
Things to note
I use the terminology System Tray throughout this tutorial to refer to the
area containing icons next to the clock in Windows 2000 and above. You may also hear this area
called the Notification Area.
Tutorial begins here - 8 steps
STEP 1
This tutorial starts with a blank application. Start a new application by selecting File -> New -> Application
STEP 2
Add the following two variables to the private declarations section of TForm1:
{ Private declarations }
FIconShown: Boolean;
FTrayIconData: TNotifyIconData;
FIconShown will be set to true once we show the icon. We can use this variable to
ensure we don't waste time displaying the icon twice.
FTrayIconData is a structure that contains the actual icon itself. The type TNotifyIconData is
declared in the unit ShellApi, so you will need to add this unit to the uses clause.
STEP 3
In this step we will do the actual creating of the icon and showing it. Therefore, this is the most complicated
step, so pay close attention :-)
Create a new procedure called ShowTrayIcon. When called, this procedure will create an icon in the system tray.
procedure TForm1.ShowTrayIcon;
begin
if not FIconShown then
begin
with FTrayIconData do
begin
uID := 1;
Wnd := Handle;
cbSize := SizeOf(FTrayIconData);
hIcon := Application.Icon.Handle;
uCallbackMessage := WM_ICONRESPONSE;
uFlags := NIF_TIP + NIF_MESSAGE + NIF_ICON;
StrPCopy(szTip, 'Here is your system tray icon, at your service!');
end;
Shell_NotifyIcon(NIM_ADD, @FTrayIconData);
FIconShown := True;
end;
end;
The TNotifyIconData variable FTrayIcondata contains many horrible
properties that must be set. I will run through several of them here (however if you aren't interested, you can skip over them):
hIcon - the handle of the icon that will be used. Here we are telling the application
to use the same icon as the form itself. In Part 2 we will use a custom icon.
uCallbackMessage - the icon will post this message to the form when the icon is interacted
with (for example, when it is clicked). In this tutorial, nothing will happen when the icon is
clicked - this will be expanded in Part 2.
szTip - this is the tooltip that will show when you hover the mouse over the icon.
Some of the other properties will be touched on in later parts. To actually display the icon,
this procedure calls Shell_NotifyIcon with the NIM_ADD flag, and the
memory address of our FTrayIconData variable.
Now that that's out of the way, we need to declare WM_ICONRESPONSE. Add the following constant at the top of the unit -
after the first uses clause but before the type clause. This is a custom Windows message that
the tray icon will send when we interact with it.
const
WM_ICONRESPONSE = WM_USER + 1;
STEP 4
Now we need a similar procedure to hide the icon. You'll be pleased to know it's a lot simpler than the code to
create the icon! Here it is:
procedure TForm1.HideTrayIcon;
begin
if FIconShown then
begin
Shell_NotifyIcon(NIM_DELETE, @FTrayIconData);
FIconShown := False;
end;
end;
This procedure checks to see that the icon is actually being shown, and if it is, it
removes it by calling Shell_NotifyIcon with the NIM_DELETE flag.
STEP 5
Using the Delphi IDE, create a button on the form, and give it an amusing caption (perhaps something a bit more
imaginative than I have done here!):
We will code this button so that when clicked, it will cause the icon to be shown in the system tray, and when
clicked again, the icon will be removed from the tray.
STEP 6
Double-click the button to access the OnClick event. In this event, we want to call the ShowTrayIcon
procedure if the icon is not visible, and HideTrayIcon if the icon is visible. Here is the code - nice
and simple:
procedure TForm1.Button1Click(Sender: TObject);
begin
if FIconShown then
HideTrayIcon
else
ShowTrayIcon;
end;
This code reads simply: If the tray icon is currently visible, then hide it, else, show it.
STEP 7
There is one more thing that needs to be added to the project to get it to compile. Create a procedure with
the following signature and definition:
procedure IconResponse(var Msg: TMessage); message WM_ICONRESPONSE;
procedure TForm1.IconResponse(var Msg: TMessage);
begin
// Leave empty
end;
For now, leave this procedure empty. This procedure defines what happens when the user
clicks the icon in the tray. We will code this procedure in the next section of the tutorial.
STEP 8
One final piece of housekeeping. If you run the application now, then press the button to create the icon,
then close the application, the icon sticks around in the tray. When you hover over the icon, it will
remove itself from the tray.
What we want to do is remove the icon from the tray when the application is closed (if it is being shown).
Create a new OnDestroy event for Form1, and enter the following code:
procedure TForm1.FormDestroy(Sender: TObject);
begin
HideTrayIcon;
end;
As you may recall from Step 4, the HideTrayIcon procedure removes the icon from the tray
only if it actually exists there.
Tutorial complete
Run the application, and you should see your form appear with the "Click Me" button.
Click this button, and you will see your icon appear in the system tray! Click the button a second time, and the icon
will vanish.

There it is, on the left hand side!
If you hover the mouse over the icon, you should see the tool tip specified in Step 3!
If the project will not compile, see the Troubleshooting section at the bottom of the page.
Discussion
The icon is not very interesting is it - in fact it's the standard Delphi icon. Part 2
of this tutorial shows you how to change the icon to something more interesting, and also make it respond when
clicked.
Where to next?
Part 2 covers changing the icon,
and responding to mouse clicks by showing a popup menu.
Troubleshooting
Problem: Undeclared identifier: 'TNotifyIconData' (or Shell_NotifyIcon or NIM_DELETE or several others)
Solution: You need to add ShellAPI to the uses clause.
Problem 1: Undeclared identifier: 'WM_ICONRESPONSE'
Problem 2: Illegal message method index
Solution: Review step 3 above, and ensure you have added the WM_ICONRESPONSE constant
right at the top of the unit, after the uses clause but before the type clause.
Do you have another problem not covered above? It might be covered in the forum below.
If not, you can ask there yourself.
Forum coming very very soon!
|