Sign in Join
Wiki copytemporary

How to use a TrayIcon: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11### About
22
3-**[[TTrayIcon]]** is a multiplatform System Tray component. You can find TrayIcon on the [[Additional tab]] of the [[Component Palette]] (0.9.23+).
3+**[[TTrayIcon]]** is a multiplatform System Tray component. You can find TrayIcon on the [[Additional tab]] of the [[Component Palette]] (0.9.23+).
44
5-It works reliably on Windows, MacOS and Linux (and similar) with all desktops except the Gnome Desktop. It can be made work with Gnome but perhaps that's despite the Gnome Developers efforts.
5+It works reliably on Windows, MacOS and Linux (and similar) with all desktops except the Gnome Desktop. It can be made work with Gnome but perhaps that's despite the Gnome Developers efforts.
66
7-In use, drag the TrayIcon onto your form, assign an icon to it, assign a popup menu (with at least one menu item) to it and call its Show method
7+In use, drag the TrayIcon onto your form, assign an icon to it, assign a popup menu (with at least one menu item) to it and call its Show method
88
9-To start quickly, please read [[TrayIcon|the demonstration program]].
9+To start quickly, please read [[TrayIcon|the demonstration program]].
1010
1111### Linux may not display the Icon
1212
13-Some Linux systems will have trouble displaying the GTK TrayIcon, in general this relates to a move away from the System Tray model that Lazarus TrayIcon is based on. This problem is a particular issue with Gnome but some other Desktops may also suffer. There are now two ways the GTK2 SysTray component tries to show its icon, the traditional System Tray and an AppIndicator library.
13+Some Linux systems will have trouble displaying the GTK TrayIcon, in general this relates to a move away from the System Tray model that Lazarus TrayIcon is based on. This problem is a particular issue with Gnome but some other Desktops may also suffer. There are now two ways the GTK2 SysTray component tries to show its icon, the traditional System Tray and an AppIndicator library.
1414
15-Lazarus 2.2 (or fixes, main), now looks for an AppIndicator first and uses that if it it finds one. Only if that fails will it try for a traditional System Tray. This has several consequences -
15+Lazarus 2.2 (or fixes, main), now looks for an AppIndicator first and uses that if it it finds one. Only if that fails will it try for a traditional System Tray. This has several consequences -
1616
17-- The AppIndicator is intentionally a much simpler user interface. One click and it shows up a Popup Menu. **No double click, no drag, no right click, no hint.** If your app depends on one of those secondary responses, and you don't have a Gnome Desktop, you may try to force Lazarus to use the traditional SysTray, see below.
17+ * The AppIndicator is intentionally a much simpler user interface. One click and it shows up a Popup Menu. **No double click, no drag, no right click, no hint.** If your app depends on one of those secondary responses, and you don't have a Gnome Desktop, you may try to force Lazarus to use the traditional SysTray, see below.
1818
19-- An AppIndicator library must be installed, until recently, that was libappindicator3 but now many distros are moving to libayatana. A number of prominent distributions appear to be pre installing a AppIndicator but you cannot assume.
19+ * An AppIndicator library must be installed, until recently, that was libappindicator3 but now many distros are moving to libayatana. A number of prominent distributions appear to be pre installing a AppIndicator but you cannot assume.
2020
21-- On Gnome desktops, an additional item is needed, gnome-shell-extension-appindicator must be installed and **enabled**. See below.
21+ * On Gnome desktops, an additional item is needed, gnome-shell-extension-appindicator must be installed and **enabled**. See below.
2222
23-- Developers of new (Linux) applications are advised to design their program around TrayIcon using only a popUpMenu !
23+ * Developers of new (Linux) applications are advised to design their program around TrayIcon using only a popUpMenu !
2424
25-Mageia Enlightenment also requires an AppIndicator library and enabling System Tray in Settings-\>Modules and then adding that System Tray to a Shelf (all terms familiar to Enlightenment users). Unfortunately, even that gets 'an' icon, not the one you carefully select for your application.
25+Mageia Enlightenment also requires an AppIndicator library and enabling System Tray in Settings->Modules and then adding that System Tray to a Shelf (all terms familiar to Enlightenment users). Unfortunately, even that gets 'an' icon, not the one you carefully select for your application.
2626
2727#### Force traditional SysTray GTK2 ONLY
2828
29-This is a purely GTK2 behavior, not for GTK3, QT5 nor any non Linux widget set.
30-
31-As some systems do still have a functional traditional SysTray and it does offer a richer interface, you may wish to still use it. As of Lazarus 2.0.6, GTK2 LCL apps will look at an environment variable, LAZUSEAPPIND before deciding to use the AppIndicator, if its set to NO then the traditional SysTray will be used but no error is reported (or even detectable) if its not available. If set to INFO (or anything else than NO) it will report, to the console, what it is trying to do. (The YES option became irrelevant with Lazarus 2.2.)
29+This is a purely GTK2 behavior, not for GTK3, QT5 nor any non Linux widget set.
3230
33-``` bash
31+As some systems do still have a functional traditional SysTray and it does offer a richer interface, you may wish to still use it. As of Lazarus 2.0.6, GTK2 LCL apps will look at an environment variable, LAZUSEAPPIND before deciding to use the AppIndicator, if its set to NO then the traditional SysTray will be used but no error is reported (or even detectable) if its not available. If set to INFO (or anything else than NO) it will report, to the console, what it is trying to do. (The YES option became irrelevant with Lazarus 2.2.)
32+```
3433LAZUSEAPPIND=NO myapp <enter>
3534```
3635
3736#### UnityWSCtrls.GlobalUseAppInd GTK2 ONLY
3837
39-Lazarus version 3.0 and later have an additional way to predetermine which of the two TrayIcon models will be used. This has been made necessary because of the growing inconsistency of TrayIcon models in Linux Distributions. For example, at present, apparently, no 32bit Linux will work with AppIndicator model and any Gnome based distro will only work with the AppIndicator. You can set UnityWSCtrls.GlobalUseAppInd depending on some checks about the system or config file setting in the startup code of your app.
40-
41-To use UnityWSCtrls.GlobalUseAppInd you must include 'UnityCtrls' in the uses section of a unit, it can be set to one of the UnityWSCtrls.TUseAppIndInstruction values, (UseAppIndYes, UseAppIndNo, UseAppIndAuto). It MUST be set before your TrayIcon is created, so, put your code in the project's LPR file ahead of Application.CreateForm(TMainForm, MainForm) line, or, if you prefer, manually create your TrayIcon later in the startup process.
38+Lazarus version 3.0 and later have an additional way to predetermine which of the two TrayIcon models will be used. This has been made necessary because of the growing inconsistency of TrayIcon models in Linux Distributions. For example, at present, apparently, no 32bit Linux will work with AppIndicator model and any Gnome based distro will only work with the AppIndicator. You can set UnityWSCtrls.GlobalUseAppInd depending on some checks about the system or config file setting in the startup code of your app.
4239
43-For example, this might appear in your LPR file -
40+To use UnityWSCtrls.GlobalUseAppInd you must include 'UnityCtrls' in the uses section of a unit, it can be set to one of the UnityWSCtrls.TUseAppIndInstruction values, (UseAppIndYes, UseAppIndNo, UseAppIndAuto). It MUST be set before your TrayIcon is created, so, put your code in the project's LPR file ahead of Application.CreateForm(TMainForm, MainForm) line, or, if you prefer, manually create your TrayIcon later in the startup process.
4441
45-``` pascal
42+For example, this might appear in your LPR file -
43+```
4644uses
47- .....
45+ .....
46+ {$ifdef LCLGTK2}
47+ , unitywsctrls
48+ {$endif};
49+
50+ {$R *.res}
51+
52+
53+ // ----------------------------------------------------------------------------
54+ // This about reading the command line and env for instructions re TrayIcon
55+ // It applies to ONLY gtk2 and Lazarus >= 3.0.0 !
56+ // ----------------------------------------------------------------------------
4857 {$ifdef LCLGTK2}
49- , unitywsctrls
50- {$endif};
51-
52-{$R *.res}
53-
54-// ----------------------------------------------------------------------------
55-// This about reading the command line and env for instructions re TrayIcon
56-// It applies to ONLY gtk2 and Lazarus >= 3.0.0 !
57-// ----------------------------------------------------------------------------
58-{$ifdef LCLGTK2}
59- function GetUseAppInd() : UnityWSCtrls.TUseAppIndInstruction;
60- var
61- EnvVar : string;
62- begin
63- Result := UnityWSCtrls.GlobalUseAppInd;
64- if Application.HasOption('useappind') then begin // Command line
65- if Application.GetOptionValue('useappind') = 'yes' then // if not set, leave it alone.
66- Result := UseAppIndYes
67- else if Application.GetOptionValue('useappind') = 'no' then
68- Result := UseAppIndNo; // Anything other than yes or no is ignored
69- end else begin
70- EnvVar := Application.EnvironmentVariable['LAZUSEAPPIND']; // EnvironmentVariable
71- if EnvVar = 'YES' then
72- Result := UseAppIndYes
73- else if EnvVar = 'NO' then
74- Result := UseAppIndNo;
58+ function GetUseAppInd() : UnityWSCtrls.TUseAppIndInstruction;
59+ var
60+ EnvVar : string;
61+ begin
62+ Result := UnityWSCtrls.GlobalUseAppInd;
63+ if Application.HasOption('useappind') then begin // Command line
64+ if Application.GetOptionValue('useappind') = 'yes' then // if not set, leave it alone.
65+ Result := UseAppIndYes
66+ else if Application.GetOptionValue('useappind') = 'no' then
67+ Result := UseAppIndNo; // Anything other than yes or no is ignored
68+ end else begin
69+ EnvVar := Application.EnvironmentVariable['LAZUSEAPPIND']; // EnvironmentVariable
70+ if EnvVar = 'YES' then
71+ Result := UseAppIndYes
72+ else if EnvVar = 'NO' then
73+ Result := UseAppIndNo;
74+ end;
7575 end;
76-end;
77-{$endif}
78-
79-begin
80- Application.Scaled := True;
81- Application.Title := 'tomboy-ng';
82- RequireDerivedFormResource:=True;
83- Application.Initialize;
84- {$ifdef LCLGTK2 }
85- {$ifdef CPUi386} // Note: unless Ayatana fix their problem, no option for Gnome users
86- // https://github.com/AyatanaIndicators/libayatana-appindicator/issues/76
87- UnityWSCtrls.GlobalUseAppInd := UnityWSCtrls.UseAppIndNo; // 32bit must be a 'no'.
88- {$endif}
89- UnityWSCtrls.GlobalUseAppInd := GetUseAppInd(); // Set before creating TrayIcon
9076 {$endif}
91- Application.CreateForm(TMainForm, MainForm);
92- ....
77+
78+ begin
79+ Application.Scaled := True;
80+ Application.Title := 'tomboy-ng';
81+ RequireDerivedFormResource:=True;
82+ Application.Initialize;
83+ {$ifdef LCLGTK2 }
84+ {$ifdef CPUi386} // Note: unless Ayatana fix their problem, no option for Gnome users
85+ // https://github.com/AyatanaIndicators/libayatana-appindicator/issues/76
86+ UnityWSCtrls.GlobalUseAppInd := UnityWSCtrls.UseAppIndNo; // 32bit must be a 'no'.
87+ {$endif}
88+ UnityWSCtrls.GlobalUseAppInd := GetUseAppInd(); // Set before creating TrayIcon
89+ {$endif}
90+ Application.CreateForm(TMainForm, MainForm);
91+ ....
9392```
9493
95-You most certainly do not have to set UnityWSCtrls.GlobalUseAppInd, in many case, its default settings will work. But it may not work for everyone, it does give you, the programmer, some control over the situation.
94+You most certainly do not have to set UnityWSCtrls.GlobalUseAppInd, in many case, its default settings will work. But it may not work for everyone, it does give you, the programmer, some control over the situation.
9695
97-> **Note:** At present, late 2023, every 32bit Linux I tested would generate an Access Violation when calling a GTK2 TrayIcon.Show setup to use the AppIndicator. So, better wrap it with a Try .. Except on E: EAccessViolation do...
96+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** At present, late 2023, every 32bit Linux I tested would generate an Access Violation when calling a GTK2 TrayIcon.Show setup to use the AppIndicator. So, better wrap it with a Try .. Except on E: EAccessViolation do...
9897
9998#### AppIndicator Libraries
10099
101-There are currently two possible AppIndicator libraries, Canonical's LibAppIndicator3-1 or libayatana-appindicator3-1, some systems have both, Bullseye has only the Ayatana one. Lazarus trunk supports Ayatana after 22 May 2021, r65122 and in 2.2.0. See External Links, below about the shift to Ayatana.
100+There are currently two possible AppIndicator libraries, Canonical's LibAppIndicator3-1 or libayatana-appindicator3-1, some systems have both, Bullseye has only the Ayatana one. Lazarus trunk supports Ayatana after 22 May 2021, r65122 and in 2.2.0. See External Links, below about the shift to Ayatana.
102101
103-One or the other library can generally be installed from your distribution's normal package library. However, it is packaged with a number of different names. Sigh ...
102+One or the other library can generally be installed from your distribution's normal package library. However, it is packaged with a number of different names. Sigh ...
104103
105-- libappindicator3 - Slackware, NetBSD
106-- libappindicator3-1 - openSUSE and earlier Debian \[-based\]
107-- libappindicator-gtk3 - Arch, ALT, CentOS and Fedora, RedHat
108-- libappindicator3_1 - all Mandrake/Mandriva derivatives -- Mageia, OpenMandriva, PCLinuxOS, Rosa
109-- libayatana-appindicator3-1 - Debian Bullseye and most other Linuxs that offer Ayatana.
104+ * libappindicator3 - Slackware, NetBSD
105+ * libappindicator3-1 - openSUSE and earlier Debian [-based]
106+ * libappindicator-gtk3 - Arch, ALT, CentOS and Fedora, RedHat
107+ * libappindicator3_1 - all Mandrake/Mandriva derivatives -- Mageia, OpenMandriva, PCLinuxOS, Rosa
108+ * libayatana-appindicator3-1 - Debian Bullseye and most other Linuxs that offer Ayatana.
110109
111110#### gnome-shell-extension-appindicator
112111
113-This plugin is necessary for all current Gnome based systems. It is pre installed on some Gnome Desktops and only works with the an AppIndicator (not traditional SysTray). It is KNSI inspired so no fancy right clicks allowed, just assign it a menu.
114-
115-On Fedora, you can do this (note you don't need gnome-tweaks on Fedora 34) -
112+This plugin is necessary for all current Gnome based systems. It is pre installed on some Gnome Desktops and only works with the an AppIndicator (not traditional SysTray). It is KNSI inspired so no fancy right clicks allowed, just assign it a menu.
116113
117-``` bash
114+On Fedora, you can do this (note you don't need gnome-tweaks on Fedora 34) -
115+```
118116sudo dnf install libappindicator-gtk3 gnome-shell-extension-appindicator gnome-tweaks [enter]
119117```
120118
121-Once installed, you need to restart the Desktop, just logout and back in. Then you must 'enable' the new plugin. On Fedora 33 thats easy, use the gnome-tweaks command, Extensions, enable "Kstatusnotifieritem/appindicator support". On Fedora 34, they have made it a bit harder by removing the Extensions section from Gnome Tweaks (too many happy users I expect). So, with Fedora 34, use the gnome-extensions command, it does not have a gui so issue the following command -
122-
123-``` bash
124- gnome-extensions enable appindicatorsupport@rgcjonas.gmail.com [enter]
119+Once installed, you need to restart the Desktop, just logout and back in. Then you must 'enable' the new plugin. On Fedora 33 thats easy, use the gnome-tweaks command, Extensions, enable "Kstatusnotifieritem/appindicator support". On Fedora 34, they have made it a bit harder by removing the Extensions section from Gnome Tweaks (too many happy users I expect). So, with Fedora 34, use the gnome-extensions command, it does not have a gui so issue the following command -
125120```
121+gnome-extensions enable appindicatorsupport@rgcjonas.gmail.com [enter]
122+```
126123
127-Replace 'enable' with 'info' to get some diagnostic information.
124+Replace 'enable' with 'info' to get some diagnostic information.
128125
129-Note, three steps, install, restart desktop, enable plugin !
126+Note, three steps, install, restart desktop, enable plugin !
130127
131-**Debian Bullseye** appears to arrive with the Ayatana library pre installed but the Gnome version still requires gnome-shell-extension-appindicator, install as above.
128+**Debian Bullseye** appears to arrive with the Ayatana library pre installed but the Gnome version still requires gnome-shell-extension-appindicator, install as above.
132129
133130Your application can enable the extension (after a desktop restart), if you are feeling brave see <https://github.com/tomboy-notes/tomboy-ng/blob/master/source/mainunit.pas>
134131
135-**Note :** *Adding the plugin as a dependency of your application might seem attractive but do not do so ! On desktops other than Gnome, it will pull in, as dependencies, the full Gnome desktop. Your end users will not thank you.*
132+**Note :** _Adding the plugin as a dependency of your application might seem attractive but do not do so ! On desktops other than Gnome, it will pull in, as dependencies, the full Gnome desktop. Your end users will not thank you._
136133
137134#### Checking before invoking TrayIcon
138135
139-Because your app may show the user only its TrayIcon and if that's not visible the user cannot interact, you may like to test to see if its going to work. Sadly a test previously recommend here has now proved to be unreliable (in Ubuntu 21.10) and its been removed from Lazarus.
136+Because your app may show the user only its TrayIcon and if that's not visible the user cannot interact, you may like to test to see if its going to work. Sadly a test previously recommend here has now proved to be unreliable (in Ubuntu 21.10) and its been removed from Lazarus.
140137
141-<https://github.com/tomboy-notes/tomboy-ng/blob/master/source/mainunit.pas> function TMainForm.CheckGnomeExtras() has code that asks the Gnome plugin manager if if the plugin is installed and enabled. And it enables it if necessary. And we really should not have to do things like that !
138+<https://github.com/tomboy-notes/tomboy-ng/blob/master/source/mainunit.pas> function TMainForm.CheckGnomeExtras() has code that asks the Gnome plugin manager if if the plugin is installed and enabled. And it enables it if necessary. And we really should not have to do things like that !
142139
143140#### On GTK3
144141
145-Trunk from October 2019 has a working GTK3 TrayIcon based, again, on the AppIndicator. The advice above relating to installing LibAppindicator3 applies to GTK3 as well. As the only way you can get a TrayIcon under GTK3 is the an AppIndicator, you can only use it to display a popup menu, don't expect to get a working OnClick event.
142+Trunk from October 2019 has a working GTK3 TrayIcon based, again, on the AppIndicator. The advice above relating to installing LibAppindicator3 applies to GTK3 as well. As the only way you can get a TrayIcon under GTK3 is the an AppIndicator, you can only use it to display a popup menu, don't expect to get a working OnClick event.
146143
147144#### QT5 on Linux
148145
149-Some linux systems that won't display the GTK Tray Icon will display the Qt5 version, but only if they use XOrg. Any system using wayland apparently has other has issues with Qt5. Most Gnome desktops and some others use wayland by default but users can choose to use XOrg instead at logon time.
146+Some linux systems that won't display the GTK Tray Icon will display the Qt5 version, but only if they use XOrg. Any system using wayland apparently has other has issues with Qt5. Most Gnome desktops and some others use wayland by default but users can choose to use XOrg instead at logon time.
150147
151148#### Showing the Icon before establishing its Menu
152149
153-It has long been known that the System Tray Icon, on Linux at least, will not show if its .show function is called before it's popup menu has been assigned. No error shown, just no Icon to be seen.
150+It has long been known that the System Tray Icon, on Linux at least, will not show if its .show function is called before it's popup menu has been assigned. No error shown, just no Icon to be seen.
154151
155-However, in 2023 with the release of Ubuntu using Gnome Desktop 44.0, a new aspect appeared. If the popup menu assigned has, itself, no menu items when .show is called, the menu is never shown even after menu items are added. In the case of gtk2, we do get an error message (complete with spelling mistake) but we see no menu. With Qt5, no error message, we get a menu but in the wrong part of the screen, and, after a being displayed a few times, we loose even that. We do not see this issue on any other OS or even any other Linux Desktop. How very Gnome-ish !
152+However, in 2023 with the release of Ubuntu using Gnome Desktop 44.0, a new aspect appeared. If the popup menu assigned has, itself, no menu items when .show is called, the menu is never shown even after menu items are added. In the case of gtk2, we do get an error message (complete with spelling mistake) but we see no menu. With Qt5, no error message, we get a menu but in the wrong part of the screen, and, after a being displayed a few times, we loose even that. We do not see this issue on any other OS or even any other Linux Desktop. How very Gnome-ish !
156153
157-So, in summary, if you are managing menu items dynamically, make sure you have at least one menu item added to the popup menu and that popup menu assigned to the TrayIcon BEFORE calling TrayIcon.show.
154+So, in summary, if you are managing menu items dynamically, make sure you have at least one menu item added to the popup menu and that popup menu assigned to the TrayIcon BEFORE calling TrayIcon.show.
158155
159-note: chapter about 32bit carbon removed as irreverent.
156+note: chapter about 32bit carbon removed as irreverent.
160157
161158### Documentation
162159
163-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.
160+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.
164161
165-A function works on all target platforms unless written otherwise.
162+A function works on all target platforms unless written otherwise.
166163
167164#### Methods
168165
169166**Show**
170167
171-**procedure** Show;
168+**procedure** Show;
172169
173-Shows the icon on the system tray.
170+Shows the icon on the system tray.
174171
175172**Hide**
176173
177-**procedure** Hide;
174+**procedure** Hide;
178175
179-Removes the icon from the system tray.
176+Removes the icon from the system tray.
180177
181178**GetPosition**
182179
183-**function** GetPosition: TPoint;
180+**function** GetPosition: TPoint;
184181
185-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.
182+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.
186183
187184#### Properties
188185
189186**Hint**
190187
191-**property** Hint: string;
188+**property** Hint: string;
192189
193-A Hint will be shown the string isn't empty
190+A Hint will be shown the string isn't empty
194191
195192**PopUpMenu**
196193
197-**property** PopUpMenu: TPopUpMenu;
194+**property** PopUpMenu: TPopUpMenu;
198195
199-A PopUp menu that appears when the user right-clicks the tray icon.
196+A PopUp menu that appears when the user right-clicks the tray icon.
200197
201198#### Events
202199
203200**OnPaint**
204201
205-**property** OnPaint: TNotifyEvent;
202+**property** OnPaint: TNotifyEvent;
206203
207-Use this to implement custom drawing to the icon. Draw using the canvas property of the icon.
204+Use this to implement custom drawing to the icon. Draw using the canvas property of the icon.
208205
209-> **Note:** Does not work on win32.
206+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** Does not work on win32.
210207
211-> **Note:** Following events not available on Linux if using the LibAppIndicator3 model, its menu only.
208+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** Following events not available on Linux if using the LibAppIndicator3 model, its menu only.
212209
213210**OnClick**
214211
215-**property** OnClick: TNotifyEvent;
212+**property** OnClick: TNotifyEvent;
216213
217214**OnDblClick**
218215
219-**property** OnDblClick: TNotifyEvent;
216+**property** OnDblClick: TNotifyEvent;
220217
221218**OnMouseDown**
222219
223-**property** OnMouseDown: TMouseEvent;
220+**property** OnMouseDown: TMouseEvent;
224221
222+
225223**OnMouseUp**
226224
227-**property** OnMouseUp: TMouseEvent;
225+**property** OnMouseUp: TMouseEvent;
228226
229227**OnMouseMove**
230228
231-**property** OnMouseMove: TMouseMoveEvent;
229+**property** OnMouseMove: TMouseMoveEvent;
232230
233231### Authors
234232
235-- Felipe Monteiro de Carvalho
236-- Andrew Haines
233+ * [Felipe Monteiro de Carvalho](</User:Sekelsenmat> "User:Sekelsenmat")
234+ * [Andrew Haines](</User:AndrewH> "User:AndrewH")
237235
238-> **Note:** Windows: Ozz Nixon
236+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** Windows: [Ozz Nixon](</User:Ozznixon> "User:Ozznixon")
239237
240238### License
241239
242-Modified LGPL.
240+Modified LGPL.
243241
244242### Download
245243
246-Status: Stable
244+Status: Stable
247245
248-Can be located at Lazarus 0.9.22 or inferior at the directory: lazarus/components/trayicon
246+Can be located at Lazarus 0.9.22 or inferior at the directory: lazarus/components/trayicon
249247
250-And on Lazarus 0.9.23 or superior it is automatically installed with LCL
248+And on Lazarus 0.9.23 or superior it is automatically installed with LCL
251249
252250### Example 1 - Using TIcon
253251
254-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.
255-
256-Go to the Additional tab of components, and add a TTrayIcon to your form. Then change its **Name** property to SystrayIcon
252+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.
257253
258-Next add a button to the form. Double click the button and add this code to it:
254+Go to the Additional tab of components, and add a TTrayIcon to your form. Then change its **Name** property to SystrayIcon
259255
260-``` pascal
256+Next add a button to the form. Double click the button and add this code to it:
257+```
261258procedure MyForm.Button1Click(Sender: TObject);
262-begin
263- SystrayIcon.Icon.LoadFromFile('/path_to_icon/icon.ico');
264- SystrayIcon.ShowHint := True;
265- SystrayIcon.Hint := 'my tool tip';
266-
267- SystrayIcon.PopUpMenu := MyPopUpMenu;
268-
269- SystrayIcon.Show;
270-end;
259+ begin
260+ SystrayIcon.Icon.LoadFromFile('/path_to_icon/icon.ico');
261+ SystrayIcon.Hint := 'my tool tip';
262+
263+ SystrayIcon.PopUpMenu := MyPopUpMenu;
264+
265+ SystrayIcon.Show;
266+ end;
271267```
272268
273269### Example 2 - Creating the icon with TLazIntfImage
274270
275-You can use TLazIntfImage to draw your icon quickly, as in the example code below:
276-
277-``` pascal
271+You can use TLazIntfImage to draw your icon quickly, as in the example code below:
272+```
278273procedure TForm1.DrawIcon;
279-var
280- TempIntfImg: TLazIntfImage;
281- ImgHandle, ImgMaskHandle: HBitmap;
282- px, py: Integer;
283- TempBitmap: TBitmap;
284-begin
285- try
286- TempIntfImg := TLazIntfImage.Create(16, 16);
287- TempBitmap := TBitmap.Create;
288- TempBitmap.Width := 16;
289- TempBitmap.Height := 16;
290- TempIntfImg.LoadFromBitmap(TempBitmap.Handle, TempBitmap.MaskHandle);
291-
292- // Set the pixels red
293- for py := 0 to TempIntfImg.Height - 1 do
294- for px := 0 to TempIntfImg.Width - 1 do
295- TempIntfImg.Colors[px, py] := colRed;
296-
297- // Copy it to a TBitmap
298- TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle, False);
299- TempBitmap.Handle := ImgHandle;
300- TempBitmap.MaskHandle := ImgMaskHandle;
301-
302- // And copy the TBitmap to your Icon
303- SystrayIcon.Icon.Assign(TempBitmap);
304- SystrayIcon.Show;
305-
306- finally
307- TempIntfImg.Free;
308- TempBitmap.Free;
309- end;
310-end;
274+ var
275+ TempIntfImg: TLazIntfImage;
276+ ImgHandle, ImgMaskHandle: HBitmap;
277+ px, py: Integer;
278+ TempBitmap: TBitmap;
279+ begin
280+ try
281+ TempIntfImg := TLazIntfImage.Create(16, 16);
282+ TempBitmap := TBitmap.Create;
283+ TempBitmap.Width := 16;
284+ TempBitmap.Height := 16;
285+ TempIntfImg.LoadFromBitmap(TempBitmap.Handle, TempBitmap.MaskHandle);
286+
287+ // Set the pixels red
288+ for py := 0 to TempIntfImg.Height - 1 do
289+ for px := 0 to TempIntfImg.Width - 1 do
290+ TempIntfImg.Colors[px, py] := colRed;
291+
292+ // Copy it to a TBitmap
293+ TempIntfImg.CreateBitmaps(ImgHandle,ImgMaskHandle, False);
294+ TempBitmap.Handle := ImgHandle;
295+ TempBitmap.MaskHandle := ImgMaskHandle;
296+
297+ // And copy the TBitmap to your Icon
298+ SystrayIcon.Icon.Assign(TempBitmap);
299+ SystrayIcon.Show;
300+
301+ finally
302+ TempIntfImg.Free;
303+ TempBitmap.Free;
304+ end;
305+ end;
311306```
312307
313308### Subversion
314309
315-Located under components/trayicon/ on the latest subversion Lazarus.
310+Located under components/trayicon/ on the latest subversion Lazarus.
316311
317312### Help, Bug Reporting and Feature Request
318313
319-Please, post Bug Reports and Feature Requests on the [Lazarus Bugtracker](http://bugs.freepascal.org/main_page.php).
314+Please, post Bug Reports and Feature Requests on the [Lazarus Bugtracker](<http://bugs.freepascal.org/main_page.php>).
320315
321-Help requests can be posted on the Lazarus mailing list or on the Lazarus [Forum](http://www.lazarus.freepascal.org/modules.php?op=modload&name=PNphpBB2&file=index).
316+Help requests can be posted on the Lazarus mailing list or on the Lazarus [Forum](<http://www.lazarus.freepascal.org/modules.php?op=modload&name=PNphpBB2&file=index>).
322317
323318### Change Log
324319
325-1. 17/01/2006 - Available as a preview on the Lazarus subversion. Still under heavy construction, however.
326-2. 24/01/2006 - Stable under win32, gnome and gtk1, but still waiting for gtk2 support. Lazarus 0.9.12 was release with this version.
327-3. 17/02/2006 - Added support for gtk2 on subversion.
328-4. July 2008 - Implements support for Qt 4
329-5. July 2008 - Implements support for Carbon through [[PasCocoa]]
320+ 1. 17/01/2006 - Available as a preview on the Lazarus subversion. Still under heavy construction, however.
321+ 2. 24/01/2006 - Stable under win32, gnome and gtk1, but still waiting for gtk2 support. Lazarus 0.9.12 was release with this version.
322+ 3. 17/02/2006 - Added support for gtk2 on subversion.
323+ 4. July 2008 - Implements support for Qt 4
324+ 5. July 2008 - Implements support for Carbon through [[PasCocoa]]
330325
331326### Technical Details
332327
333-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:
328+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:
334329
335-**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.
330+**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.
336331
337-> **Note:** for some odd reason the environment by default does not support WM_USER+ messages, you will need to add "-dPassWin32MessagesToLCL" (without quotations) to support the messaging code. The steps are, click Tools -\> Configure "Build Lazarus"..., and add that compiler option to "Options". If you have any existing options, they are "space" delimited.
332+![Light bulb](https://upload.wikimedia.org/wikipedia/commons/d/d8/Nuvola_apps_ktip.png) **Note:** for some odd reason the environment by default does not support WM_USER+ messages, you will need to add "-dPassWin32MessagesToLCL" (without quotations) to support the messaging code. The steps are, click Tools -> Configure "Build Lazarus"..., and add that compiler option to "Options". If you have any existing options, they are "space" delimited.
338333
339-**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. Note that this does not apply to TrayIcons that are using the OS's AppIndicator interface. Certainly not Gnome, maybe not of desktops as time goes by.
334+**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. Note that this does not apply to TrayIcons that are using the OS's AppIndicator interface. Certainly not Gnome, maybe not of desktops as time goes by.
340335
341-**Linux (WindowMaker, Openbox, etc)** - Does not support system tray icons out-of-the-box. However, There are at least two softwares that provides support for it: [Docker](http://icculus.org/openbox/2/docker/) and [WMSystray](http://freshmeat.net/projects/wmsystray/)
336+**Linux (WindowMaker, Openbox, etc)** \- Does not support system tray icons out-of-the-box. However, There are at least two softwares that provides support for it: [Docker](<http://icculus.org/openbox/2/docker/>) and [WMSystray](<http://freshmeat.net/projects/wmsystray/>)
342337
343-**macOS** - TTrayIcon support is implemented using the menu bar extras. Unfortunately 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.
338+**macOS** \- TTrayIcon support is implemented using the menu bar extras. Unfortunately 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.
344339
345-![](/wiki-images/9/97/Mn_menubaritems.jpg)
340+[![Mn menubaritems.jpg](/wiki-images/9/97/Mn_menubaritems.jpg)](</File:Mn_menubaritems.jpg>)
346341
347-To read more about menu bar extras:
342+To read more about menu bar extras:
348343
349-1. <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/StatusBar/StatusBar.html>
350-2. <https://developer.apple.com/design/human-interface-guidelines/macos/extensions/menu-bar-extras/>
351-3. <https://developer.apple.com/design/human-interface-guidelines/macos/menus/dock-menus/>
352-4. <https://developer.apple.com/design/human-interface-guidelines/macos/system-capabilities/dock/>
353-5. <https://developer.apple.com/design/human-interface-guidelines/macos/menus/menu-anatomy/>
354-6. <http://en.wikipedia.org/wiki/Menu_extra>
344+ 1. <https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/StatusBar/StatusBar.html>
345+ 2. <https://developer.apple.com/design/human-interface-guidelines/macos/extensions/menu-bar-extras/>
346+ 3. <https://developer.apple.com/design/human-interface-guidelines/macos/menus/dock-menus/>
347+ 4. <https://developer.apple.com/design/human-interface-guidelines/macos/system-capabilities/dock/>
348+ 5. <https://developer.apple.com/design/human-interface-guidelines/macos/menus/menu-anatomy/>
349+ 6. <http://en.wikipedia.org/wiki/Menu_extra>
355350
356-With this in mind an approach which supports all Platforms was created:
351+With this in mind an approach which supports all Platforms was created:
357352
358-- Painting is done via a TIcon object. (Required by Windows)
353+ * Painting is done via a TIcon object. (Required by Windows)
359354
360-The following extra features are already available or will be, but they won´t work on all platforms.
355+The following extra features are already available or will be, but they won´t work on all platforms.
361356
362-- OnPaint event and Canvas property to draw the icon freely. Won´t work on Windows.
357+ * OnPaint event and Canvas property to draw the icon freely. Won´t work on Windows.
363358
364359### External Links
365360
366-- <http://www.codeproject.com/shell/ctrayiconposition.asp> - Code and theory to find the tray icon position under Windows
367-- <http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtkstatusicon.c?rev=1.23&view=markup> - Gtk2 code that implements gtkstatusicon
368-- <http://pasmontray.sourceforge.net> - Open source program that uses TrayIcon to display CPU and memory utilisation in the system tray.
369-- [Background to Debian's switch from libappindicator to Ayatana](https://lists.debian.org/debian-devel/2018/03/msg00506.html)
370-- [Ayatana App Indicator](https://github.com/AyatanaIndicators/libayatana-appindicator)
361+ * <http://www.codeproject.com/shell/ctrayiconposition.asp> \- Code and theory to find the tray icon position under Windows
362+ * [http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtkstatusicon.c?rev=1.23&view=markup](<http://cvs.gnome.org/viewcvs/gtk%2B/gtk/gtkstatusicon.c?rev=1.23&view=markup>) \- Gtk2 code that implements gtkstatusicon
363+ * <http://pasmontray.sourceforge.net> \- Open source program that uses TrayIcon to display CPU and memory utilisation in the system tray.
364+ * [Background to Debian's switch from libappindicator to Ayatana](<https://lists.debian.org/debian-devel/2018/03/msg00506.html>)
365+ * [Ayatana App Indicator](<https://github.com/AyatanaIndicators/libayatana-appindicator>)
371366
372367---
373-*From the Free Pascal wiki, page "How to use a TrayIcon", as it stood on 2023-12-09 after a change by Dbannon, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
374-Category: Tutorials
368+*From the Free Pascal wiki, page "How to use a TrayIcon", as the Internet Archive kept it on 2025-07-16, last changed on 2024-09-07. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history