Help & Manual authoring tool
To place an icon in the taskbar tray you have to call the Shell_NotifyIcon API declared in the ShellAPI unit... Here is an example.

Starting an application as an icon in the system tray

Copyright © 2000 Ernesto De Spirito

Download the source code

EurekaLog - Catch and log every exception!

Placing an icon the system tray

The system tray is the area at the right of the task bar where "background" applications can place their icons. To place an icon in the tray you have to call the Shell_NotifyIcon API declared in the ShellAPI unit, passing it the constant NIM_ADD (to tell it to add an icon) and the address of a TNotifyIconData record with the icon information that includes the handle of the icon to show, the text to show as tool tip when the mouse is over the icon, the handle of the window that will receive the messages of the icon and the message type the icon will send to this window.

uses
   ..., ShellAPI;

const
  WM_ICONTRAY = WM_USER + 1;   // User-defined message

type
  ...

var
  ...
  NotifyIconData : TNotifyIconData;

implementation

procedure TForm1.FormCreate(Sender: TObject);
begin
  with NotifyIconData do begin
    hIcon := Icon.Handle;
    StrPCopy(szTip, Application.Title);
    Wnd := Handle;
    uCallbackMessage := WM_ICONTRAY;
    uID := 1;
    uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
    cbSize := sizeof(TNotifyIconData);
  end;
  Shell_NotifyIcon(NIM_ADD, @NotifyIconData);
end;

Handling icon messages

Form1 will receive WM_ICONTRAY messages from the icon. To capture and handle these messages we have to declare a new method in our form. For example:

type
  TForm1 = class(TForm)
    ...
  private
    { Private declarations  }
    ...
    procedure Icontray(var Msg: TMessage); message WM_ICONTRAY;
  public
    { Public declarations  }
    ...
  end;

In the implementation of this method we can for example display a pop-up menu when the user right-clicks on the icon. Assuming you have created a pop-up menu named PopupMenu1, the following code will do the trick:

procedure TForm1.Icontray(var Msg: TMessage);
var
  CursorPos : TPoint;
begin
  if Msg.lParam = WM_RBUTTONDOWN then begin
    GetCursorPos(CursorPos);
    SetForegroundWindow(Handle);        // suggested by Berend Radstaat
    PopupMenu1.Popup(CursorPos.x, CursorPos.y);
    PostMessage(Handle, WM_NULL, 0, 0); // suggested by Berend Radstaat
  end else
    inherited;
end;

Thanks to Berend Radstaat for the additions to this article.

Showing and hiding the form

Normally you will include a menu item in the pop-up menu to show the form, so all you have to do is write an event handler to call the Show method of the form and optionally remove the icon from the system tray:

procedure TForm1.mnuShowClick(Sender: TObject);
begin
  Show;
  // Shell_NotifyIcon(NIM_DELETE, @NotifyIconData);
end;

When the user closes the form, you can for example hide it instead of closing it and optionally show the icon again in the system tray if you have removed it when you made the form visible. For example:

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caNone;
  Hide;
  // Shell_NotifyIcon(NIM_ADD, @NotifyIconData);
end;

Finishing the application

You can have a menu item in the pop-up menu to exit the application. In this case you have to write an event handler for its click event to remove the icon and finish the application:

procedure TForm1.mnuExitClick(Sender: TObject);
begin
  Shell_NotifyIcon(NIM_DELETE, @NotifyIconData);
  Application.ProcessMessages;
  Application.Terminate;
end;
JfControls Library - for Delphi and C++ Builder
Copyright © 2000/2006 Ernesto De Spirito.   All rights reserved.