The New TTrayIcon Component in BDS 2006

By: a z

Abstract: Everything you never wanted to know about the new TTrayIcon component

The New TTrayIcon Component in BDS 2006.

When I first encountered tray icons back in the days of Windows 95, I thought they were rather neat, but of limited usefulness. How many applications could really make effective use of this concept? Well, many years later, it turns out that quite a few applications can and do. There are currently no fewer than eight such icons in my system tray right now, and many people have even more.

There have been numerous tray icon components floating around for years from various sources, but with the release of BDS 2006, Borland has finally included their very own TTrayIcon component. The basic operation is straight-forward and you can be up and running within minutes.

Getting started

TTrayIcon is found under the Additional section of the Tool Palette. Add the component to the form, set the visible property to true, run your application, and congratulate yourself on a job well done. This is what we get paid the big bucks for.

Of course, while the tray icon looks nice, we have to put in a little more effort to get it to actually do something. See the sample project for a demo of the tray icon in action.

Peek a boo

A standard function for a tray icon is to allow the user to hide and restore an application. This is a great way to keep utility apps close at hand, yet out of the way.

To hide your application just use the Hide method of each visible form in your application. This will automatically remove your application's icon from the Windows task switcher as well as the task bar. Application.Minimize can optionally be called as well, but note that it will result in an animation of the form being minimized to the task bar rather than to the system tray.

It's important that you hide the forms from the top-most form down to the bottom-most form, and restore the forms in the opposite order. This will ensure that the Z-order is preserved when restoring your application. This is critical when dealing with modal dialog boxes. The simples way to ensure that the correct order is used is to iterate forward through the Screen.Forms array when hiding your application, and iterating backward when restoring. For example, to hide them all:


  var
    k: integer;
  begin
    application.Minimize;
    for k := 0 to Screen.FormCount - 1 do begin
      Screen.Forms[k].Hide;
    end;
  end;

To restore the application, add the following code to the tray icon's OnClick event handler.


  var
    k: integer;
  begin
    for k := Screen.FormCount - 1 downto 0 do begin
      Screen.Forms[k].Show;
    end;
    application.Restore;
    application.BringToFront;
  end;

In the sample project I used a button to hide the application, but it's a much more natural experience if you hide the application in response to the TApplicationEvents component's OnMinimize event. Some applications require a double click to restore an application rather than a single click, but performing a double click within a 16 pixel square area requires a certain dexterity that not everyone has. In fact, you may want to consider using a global hotkey as an additional way of restoring the application. Make sure that the user can customize the shortcut in case of conflicts with other applications.

What's on the menu?

Adding a menu to the tray icon is even easier than hiding and restoring your application. Add a TPopupMenu component to the form and assign it to the tray icon's PopupMenu property. Add the relevant menu items and their associated event handlers and away you go. I was worried that there might be problems trying to close the application when a modal child form was displayed, but this seems to work just fine.

Note that in BDS 2006 Update 1 the TTrayIcon does not correctly set it's PopupMenu property to nil when the associated component is deleted. To avoid access violations and other general weirdness, be sure to clear the PopupMenu property before deleting the TPopupMenu component.

Pretty pictures

By default the tray icon will use the application's icon, but this can overridden by either loading an icon into the Icon property, or by assigning a TImageList instance to the Icons property and setting an appropriate value for the IconIndex property.

If you're using an ImageList you can animate the icons by setting the Animate property to true. This will cause each icon in the image list to be displayed in turn. How rapidly it changes is controlled by the AnimateInterval property.

Hints

Hints are easy. Assign some text to the Hint property and that text will appear when the user pauses the mouse over the tray icon. If the Hint property is empty then the application's Title as set in Project - Options - Application - Title will be displayed. Windows limits the length of the hint to 127 characters. If you have some text assigned to the Hint property, and then assign a blank string to it, you may find that Window still displays the old text. This appears to be a issue with Windows rather than with Delphi.

99 red balloons

Sorry, you'll have to settle for yellow balloons. A balloon hint is best used to alert the user to a non-critical event.

Multiple applications can display balloon hints and Windows will ensure each will get displayed one at a time for a minimum length of time. Once a balloon is visible a user can click on it to make it disappear. If a user doesn't click on it the balloon will disappear automatically after it times out - assuming that a user is active on the system. If the computer is idle, then the balloon will remain visible until the user starts using the computer again. The timeout can be set by the application but Windows enforces minimum and maximum values which are typically set to 10 and 30 seconds.

If multiple applications display balloons then Windows will leave about a two second gap between displaying balloons. If a single application displays two balloon in rapid succession, the first hint will immediately be replaced by the second hint.

Of course, your balloons might not be displayed at all if the user has disabled them in the registry by setting the EnableBalloonTips value to 0 in:

  HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionExplorerAdvanced
    

With these things in mind, let's get down to displaying a balloon. The relevant properties are BalloonFlags, BalloonHint, BalloonTimeout, and BalloonTitle.

BalloonFlags shows the usual icons that you see in message boxes - Error, Info, and Warning. BalloonHint contains the actual text within the balloon and BalloonTitle is used for the caption of the balloon. The BalloonHint is limited to 255 characters and the BalloonTitle is limited to 63 characters. The BalloonTimeout tells Windows how long to wait (in milliseconds) before hiding the balloon automatically. As mentioned earlier the acceptable range is usually 10 to 30 seconds. Call the ShowBalloonHint procedure to actually display the balloon.

If you wish to manually hide a balloon hint rather than letting it time out, change the BalloonHint to an empty string and call ShowBalloonHint.

The appearance of balloon hints can vary from system to system. For example, here's a balloon hint from the demo program running under Windows 2000:

Windows 2000 - without a close button

and under Windows 2003:

Windows 2003 - with a close button

Conclusion

A tray icon is a great tool, but don't get carried away with it. Always give users the option of disabling the tray icon and in particular the balloon hints.

See the sample project for a demonstration of the TTrayIcon in action.

Server Response from: ETNASC04