How to use a TrayIcon
English (en) │
- 1 About
- 2 Problems with newer Gnome based Linux
- 3 Issue On the Mac, OSX
- 4 Documentation
- 5 Authors
- 6 License
- 7 Download
- 8 Example 1 - Using TIcon
- 9 Example 2 - Creating the icon with TLazIntfImage
- 10 Subversion
- 11 Help, Bug Reporting and Feature Request
- 12 Change Log
- 13 Technical Details
- 14 External Links
TrayIcon used to be an optional component, but is part of LCL since Lazarus 0.9.23
To start quickly, please read the demonstration program.
Problems with newer Gnome based Linux
There are at least two reasons why a Linux system may fail to display the System Tray Icon, a clash between libappindicator1 and libappindicator3 and, secondly, a distribution's adherence to the Gnome hard line about not displaying System Tray Icons. See next section for the second case.
June 2019 I have submitted a patch related to https://bugs.freepascal.org/view.php?id=33778 but goes a little further. 33778 took a conservative approach and only used the (Unity inspired) libappindicator3 if libappindicator1 was not present. However, several distributions now exist that cannot use libappindicator1 but do work with libappindicator3. Not usually a problem as libappindicator1 is not installed automatically if it not usable. But an OS that has been upgraded from, say U18.04 to U19.04 will have both versions of the appindicator library. LCL will choose the older one and it will not display the System Tray Icon.
Patch https://bugs.freepascal.org/view.php?id=35723 fixes that. Users of Lazarus 2.0.2 or earlier (and fixes until and if patch is accepted) might like to apply that patch themselves.
Gnome 3.28 and later won't display Icon
The Gnome Developers have determined that Gnome should not support the System Tray Icon model at all, apparently to avoid screen clutter. If your end users are willing to risk a little screen clutter to achieve a usable desktop, keep reading.
Distributions such as RedHat and openSUSE will not, out of the box, display the LCL System Tray Icon. Sadly, it fails silently, giving a user no indication of whats happening. Fortunatly, there are a number of Gnome Extensions that can restore normal operation but be aware that each new release of Gnome appears (and maybe only 'appears') to take steps to stop even those extension from working. At the time of writing this, June 2019, a model that does work for Fedora 30 and openSUSE 15 is to install the Gnome Extension TopIcons-plus and a version 3 appindicator library. Note, both steps are required, doing one or the other alone will not be enough !
To install a Gnome Extension, you have to install, into (eg) Firefox an extension that allows you to control your collection of Gnome Extensions. Awkard process but OK if you want to play with the wide range of extensions available. An alternative approach that works at present is to download the extension from github and install it, maybe not a good long term suggestion (?) -
As root -
dnf install make libappindicator-gtk3 gnome-tweak-tool
As yourself -
git clone https://github.com/phocean/TopIcons-plus.git cd TopIcons-plus make install
Logout and back in again.
In the app thats runs, click Extensions, turn TopIcons-plus ON and click close
Note that for OpenSUSE the appindicator library is called libappindicator3-1, its likely other distributions may call it the same thing. Distributions based on Ubuntu will have it installed already.
Issue On the Mac, OSX
In October, 2017 it was noted that on the Mac, Sierra, Carbon, Lazarus 1.8rc4 a small problem existed. Attempts to updates to the caption of a menu item in a popup menu associated with a TrayIcon do not happen as expected. Its not uncommon to want to update the menu text at run time, for example, to display a list of recently opened files. This problem has been logged, https://bugs.freepascal.org/view.php?id=32516 . A workaround that appears reliable is to call TrayIcon1.InternalUpdate; after making changes to the captions.
This problem does not exist on Linux, Windows or OSX using Cocoa Widget Set.
Note that TrayIcon on the Mac, Carbon (ie 32bit) has a memory leak.
Below is a list of all methods, properties and events of the component. They have the same names and work the same way on the visual component and on the non-visual object.
A function works on all target platforms unless written otherwise.
Shows the icon on the system tray.
Removes the icon from the system tray.
function GetPosition: TPoint;
Returns the position of the tray icon on the display. This function is utilized to show message boxes near the icon. Currently it´s only a stub, no implementations are available and TPoint(0, 0) is returned.
property Hint: string;
A Hint will be shown the string isn't empty
property PopUpMenu: TPopUpMenu;
A PopUp menu that appears when the user right-clicks the tray icon.
property OnPaint: TNotifyEvent;
Use this to implement custom drawing to the icon. Draw using the canvas property of the icon.
property OnClick: TNotifyEvent;
property OnDblClick: TNotifyEvent;
property OnMouseDown: TMouseEvent;
property OnMouseUp: TMouseEvent;
property OnMouseMove: TMouseMoveEvent;
Can be located at Lazarus 0.9.22 or inferior at the directory: lazarus/components/trayicon
And on Lazarus 0.9.23 or superior it is automatically installed with LCL
Example 1 - Using TIcon
As of Lazarus 0.9.26 TIcon has been fully implemented and it is no longer necessary to load the icon from a resource file on Windows. The icon can be loaded in the IDE or with usual code.
Go to the Additional tab of components, and add a TTrayIcon to your form. Then change it's Name property to SystrayIcon
Next add a button to the form. Double click the button and add this code to it:
procedure MyForm.Button1Click(Sender: TObject); begin SystrayIcon.Icon.LoadFromFile('/path_to_icon/icon.ico'); SystrayIcon.ShowHint := True; SystrayIcon.Hint := 'my tool tip'; SystrayIcon.PopUpMenu := MyPopUpMenu; SystrayIcon.Show; end;
Example 2 - Creating the icon with TLazIntfImage
You can use TLazIntfImage to draw quickly your icon, as in the example code below:
procedure TForm1.DrawIcon; var TempIntfImg: TLazIntfImage; ImgHandle, ImgMaskHandle: HBitmap; px, py: Integer; TempBitmap: TBitmap; begin try TempIntfImg := TLazIntfImage.Create(16, 16); TempBitmap := TBitmap.Create; TempBitmap.Width := 16; TempBitmap.Height := 16; TempIntfImg.LoadFromBitmap(TempBitmap.Handle, TempBitmap.MaskHandle); // Set the pixels red for py := 0 to TempIntfImg.Height - 1 do for px := 0 to TempIntfImg.Width - 1 do TempIntfImg.Colors[px, py] := colRed; // Copy it to a TBitmap TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle, False); TempBitmap.Handle := ImgHandle; TempBitmap.MaskHandle := ImgMaskHandle; // And copy the TBitmap to your Icon SystrayIcon.Icon.Assign(TempBitmap); SystrayIcon.Show; finally TempIntfImg.Free; TempBitmap.Free; end; end;
Located under components/trayicon/ on the latest subversion Lazarus.
Help, Bug Reporting and Feature Request
Please, post Bug Reports and Feature Requests on the Lazarus Bugtracker.
Help requests can be posted on the Lazarus mailling list or on the Lazarus Forum.
- 17/01/2006 - Available as a preview on the Lazarus subversion. Still under heavy construction, however.
- 24/01/2006 - Stable under win32, gnome and gtk1, but still waiting for gtk2 support. Lazarus 0.9.12 was release with this version.
- 17/02/2006 - Added support for gtk2 on subversion.
- July 2008 - Implments support for Qt 4
- July 2008 - Implements support for Carbon through PasCocoa
A difficulty on the development of this component was the many differences on the system tray implementation on various OSes and even Window Managers on Linux. To solve this, the component tries to implement the minimal set of features common to all target platforms. Below is a list of the features implemented on each platform:
Windows - Multiple system tray icons per application are supported. The image of the icon can be altered using a HICON handle. Events to the icon are sent via a special message on the user reserved space of messages (>= WM_USER) to the Window which owns the Icon. No paint events are sent to the Window.
Linux (Gnome, KDE, IceWM, etc) - Multiple system tray icons per application are supported. The image of the icon is actually a very small Window, and can be painted and receive events just like any other TForm descendant.
Mac OS X - TTrayIcon support is implemented using the menu bar extras. Unfortunatelly the API to use menu bar extras is only available in Cocoa and not in Carbon, so we use the stable PasCocoa bindings in the Carbon interface to support menu bar extras even in older FPC compilers and in the Cocoa interface we will use the more modern Objective Pascal syntax.
To read more about menu bar extras:
With this in mind an approach which supports all Platforms was created:
- Painting is done via a TIcon object. (Required by Windows)
The following extra features are already available or will be, but they won´t work on all platforms.
- OnPaint event and Canvas property to draw the icon freely. Won´t work on Windows.
- http://www.codeproject.com/shell/ctrayiconposition.asp - Code and theory to find the tray icon position under Windows
- http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtkstatusicon.c?rev=1.23&view=markup - Gtk2 code that implements gtkstatusicon
- http://pasmontray.sourceforge.net - Open source program that uses TrayIcon to display CPU and memory utilisation in the system tray.