Home · FAQ · Forums · Contact · Privacy Policy September 08 2008 20:14:10
Login

Username

Password


Not a member yet?
Click here to register.

Forgotten your password?
Request a new one here.
Games
Manic Miner
Jet Set Willy (in progress)
Cheese, Louise!
Hangman
Education
Flash Card Software
Programming
Delphi Tips/Tutorials
Shoutbox
You must login to post a message.

andrewbroad
19 August 2008
Yes indeed. During every Olympics since 2000, I've been thinking that Manic Miner and Jet Set Willy should be Olympic sports. On your marks, Jet Set, go!

jetsetdanny
19 August 2008
It's no wonder, really. Great minds think alike . And speaking of the Olympics, isn't it a shame that Flash Manic Miner is not an Olympic discipline?

andrewbroad
19 August 2008
Oops - that ) wasn't supposed to come out as a smiley! The Olympic Tennis has, of course, been the (latest) reason for my recent absence from the MM/JSW scene.

andrewbroad
19 August 2008
Wow, Danny, I just put that exact quote from Goldfinger (up to "heaviness" in my last Olympic Tennis report, and now I come here and see you've used it too!

jetsetdanny
19 August 2008
"This is gold, Mr Bond. All my life, I've been in love with its colour, its brilliance, its divine heaviness. I welcome any enterprise that will increase my stock, which is considerable."

jetsetdanny
19 August 2008
"Do or do not." Okay, I have done it, in-between my holiday trips. I have reclaimed Gold in Manic Miner.

andrewbroad
08 August 2008
I was watching Twin Peaks: Episode 1 the other day, and one of the characters said, "Jeez, Louise!" - so that's where it comes from!

andrewbroad
08 August 2008
Wow: I thought I was about to die at about 1600, but recovered for my second-best-ever game of Cheese, Louise with 3902! (Round 22 - ironically my best-ever was 3958 on Round 20).

andrewbroad
03 August 2008
Try not. Do or do not. There is no try... This organisation does not tolerate failure... The amazing sound of the killing hawks... From a great height, from a great heigh...eigh...eigh...eig
ht.


jetsetdanny
03 August 2008
I have tried to regain Gold, but I have failed due to stupid loss of life in Caverns 12 and 36, with no points gained from it. So it looks like Andrew will be reigning in MM in August...

andrewbroad
03 August 2008
Thanks, Danny. Ironically, it's not the birds that are the killers, but the crumbling floors. I died from a very long fall.

jetsetdanny
03 August 2008
Well done, Andrew, congratulations!

andrewbroad
03 August 2008
I WON THE GOLD MEDAL ON MY FIRST VISIT TO THE KILLER BIRDS!!! I got to Cavern 42 without loss of life, then sacrificed two lives, then died in Cavern 43 with my all-time high of 83092.

andrewbroad
01 August 2008
I feel that July's routine has served its purpose: I am now much more confident of reaching Cavern 31, much more familiar with the route through each cavern, and much more aware of the risks.

andrewbroad
01 August 2008
So from now on, I'm only going to play Flash MM at the weekends and holidays, trying to reach later caverns, and to set new all-time world highs for selected caverns.

andrewbroad
01 August 2008
Well, I certainly won't be playing Flash MM between working-days anymore. It has taken a very heavy toll on me in July: I have started losing other goals, and am now extremely tired.

jetsetdanny
01 August 2008
And in August I will be watching your progress every two or three days, as I will be offline most of the time (holiday away from home!). And hoping that my medals will withstand your assault .

jetsetdanny
01 August 2008
And then you will face the formidable Killer Birds! Anyway, improving your all-time personal high by just 1 points in the 60000 pts. range is an achievement worth congratulating!

andrewbroad
31 July 2008
Clearly, I have a lot of practising to do before I'm ready to pass Cavern 31, and then the floodgates should open for me if Caverns 32 to 42 are basically the same as 12 to 22.

andrewbroad
31 July 2008
I played my least efficient game of the whole month to reach Cavern 30, then sacrificed two lives there, and it paid off as I flunked Cavern 31 really badly, taking only one item.

Shoutbox Archive

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!

Google





Current high scores    

 Manic Miner
jetsetdanny83396
andrewbroad83092
jetsetdanny82424
jetsetdanny81881
jetsetdanny52868
andrewbroad40885
more... 
 Cheese, Louise!
andrewbroad3902
andrewbroad2100
andrewbroad2096
andrewbroad2026
andrewbroad2000
andrewbroad1994
more... 
Hosted by inter.net.nz slightly neurotic web hostingGames developed by g2 developmentPowered by PHP-Fusion v6.00.106 © 2003-2005