1. Technology
Send to a Friend via Email

Your suggestion is on its way!

An email with a link to:

http://delphi.about.com/od/kbwinshell/l/aa122501a.htm

was emailed to:

Thanks for sharing About.com with others!

System Tray Delphi application - dirty and effective
Once you have placed a Delphi program's icon in the Tray, it's time to show a (customized) pop up menu near the icon and have the icon reflect the state of your application - even animate if you want so!
 More of this Feature
• Part 1: Placing your project's Icon in the Tray

• CODE
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Shell exposed by Delphi
• API and Delphi
• Top shell tricks
• Message handling
• Menu drawing

In the previous article, I've presented you with a quick and easy solution you can use to have your Delphi application's icon placed in the System Tray.

It's now time to have that icon animate and if needed reflect the state of your application. We'll do even more: let's create a custom menu that pops up when you click the icon.

   The Project
First we'll make our project do something useful. Use the code from the previous article and drop a TEdit and a TButton component on the form. The idea is simple: you write something in the Edit and the "Button" tries to execute it. This part is simple, and is not important now. What is important is how to create a pop up menu for the icon in the Tray and how to have that icon animate (or change to reflect the state of the application).

A PopUp Menu, a Timer, and a few icons
When developing projects that only appear in the Tray, you have only one option for presenting the user with the commands he or she can apply to the project - the PopUp menu. To spice this project a bit I'll create a custom drawn popup menu. The technique is called owner drawing. To start, drop a TPopupMenu on the form. Add 4 menu items: Show Form, Hide Form, AnimateIcon and Exit. The first two items and the last one describe themselves. The third item "AnimateIcon" will be used to start and stop the Tray icon animation.

For the animation part, you'll need a TTimer component - the OnTimer event will be used to change the icon in the tray. And finally you'll need several icons - the TImageList component will do the task. Drop it on the form and add two icons to it.

Tray - Design Time

The Code
The application should respond to a right click of the mouse by showing a pop up menu allowing the user to show or hide the form, start or stop the icon animation and to quit the application.

To show a popup, we need to modify the TrayMessage procedure a bit:

procedure TMainForm.TrayMessage(var Msg: TMessage);
var
  p : TPoint;
begin
  case Msg.lParam of
    WM_LBUTTONDOWN:
    begin
      ShowMessage('This icon responds 
                  to RIGHT BUTTON click!');
    end;
    WM_RBUTTONDOWN:
    begin
       SetForegroundWindow(Handle);
       GetCursorPos(p);
       PopUpMenu1.Popup(p.x, p.y);
       PostMessage(Handle, WM_NULL, 0, 0);
    end;
  end;
end;

The above code shows the popup near the icon and notifies the user that he should be using the right mouse button click. Note that the code lacks the MainForm.Show and MainForm.Hide commands - those are moved to the corresponding PopUp menu item OnClick events.

The above picture shows the popup menu at run time. Notice the custom (owner) drawing of the popup menu.

The "Animate Icon" item simply enables or disables the OnTimer event which is used to change the icon in the tray every second (the value is in the Interval property of the Timer1 component)

procedure TMainForm.Timer1Timer(Sender: TObject);
{$J+}
const
  Index : Integer = 0;
{$J-}
var
  Icon: TIcon;
begin
  Inc(Index);
  if Index = 2 then Index:=0;

  Icon:=TIcon.Create;
  try
    ImageList1.GetIcon(Index,Icon);
    TrayIconData.hIcon := Icon.Handle;
    Shell_NotifyIcon(NIM_Modify, @TrayIconData);
  finally
    Icon.Free;
  end;
end;

The code uses the NIM_Modify parameter of the Shell_NotifyIcon function to switch between those two icons stored in the ImageList component. The code changes the hIcon value of the TrayIconData structure - of course, you can change all the members of the TrayIconData.

Note: another approach would be to use custom resource file with more icons - to have each icon represent something meaningful - like the state of the application.

That's it. Dirty and effective. I'm not going to bother you with the project details here, be sure to download the entire code, you'll have plenty to play with.

©2014 About.com. All rights reserved.