## Systray Class

Introduction
Quick Start
Properties
Methods
Icon Events
Balloon Tip Events
Working with Menus

### Introduction

The Systray class, located in the Samples\Solution\Toledo\ folder, provides support for using icons in the Taskbar Notification Area (commonly referred to as the “System Tray”). It supports mouse events and balloon tips. Certain features, such as balloon tips, are only supported if the Operating System supports them. With the support of an external timer object, you can animate the System tray icon.
The Systray class supports Visual FoxPro shortcut menus for your System Tray icon, so you can use all the features of the Visual FoxPro menu designer.
Each icon maintains its own communication pathway with the operating system. This means you can use multiple instances of the Systray class in the same application, without worrying about the multiple icons interfering with each other.
The Systray class cannot be used in a DLL. If the project is to be compiled, it must be compiled as an EXE (or APP) in order for Systray to work correctly.

### Quick Start

The Systray class is based on the VFP Hyperlink class. This allows the Systray class to be dropped on a form, just like any other visual class.
After adding the Systray class to a form, often the only properties you need to set are:

IconFile – provide the full path and filename for an icon file
TipText – the tip text to display when the mouse is moved over the icon
MenuText – A menu definition string or an MPR filename.
MenuTextIsMPR – Set to .T. if MenuText contains the name of an MPR file.
The default behavior is to add the icon to the system tray when the object is instantiated, and to display the menu when the icon is clicked with the left or right mouse button.
The Systray class can also be used without a form, so it can provide your application’s only user interface. For example, the following code adds an icon to the systray, and waits for a user to click on the icon.

    x = NEWOBJECT('systray', 'systray.vcx')
    x.IconFile 	= HOME() + "Graphics\Icons\Misc\Question.ico"
    x.TipText 	= "Taskbar Icon example"
    x.MenuText 	= "Systray_shortcut.mpr"
    x.MenuTextIsMPR = .T.
    x.AddIconToSystray()
    READ EVENTS && Wait for user input.

The above code assumes that at least one menu item, or a separate timer object, will execute a CLEAR EVENTS.
When the Systray object is released, it automatically removes the icon from the System Tray, and releases all icon resources.

### Properties

##### AddIconToSystrayAtInit (Logical, Default is .T.)

If true, and IconFile property points to a valid Icon file, the icon is added to the System Tray when the systray object is instantiated.

##### CurrentIconIndex (Numeric)

Index into the list of icons used for this System tray item. Use AddIconToIconList() method to load several icons. Then CurrentIconIndex can be used to select which of those icons is displayed, or can be read to determine which icon is currently displayed. See also: SwitchIcon() method, AddIconToIconList() method.

##### IconFile (Character – no default value)

Set to the full path and filename of a single icon file to be displayed. The icon file can be included in a compiled EXE or DLL file.

Use the IconFile property for setting only a single icon, or setting an initial icon. If you want to use multiple icons for animation, use the AddIconToIconList() method. Setting the IconFile property after instantiation will trigger the ClearIconList() method, releasing all previously loaded icons.

###### See also: AddIconToIconList(), ClearIconList(), AddIconToSystray(), SwitchIcon()

##### MenuOffsetFromRight (Numeric – Default is 200 pixels)

Number of pixels to shift the menu when the taskbar is docked on the right side of the screen. Only used when the taskbar is docked on the right.

Because Visual FoxPro shortcut menus are not drawn over the top of the taskbar, we need to make sure the menu does not overlap the taskbar when it is docked on the right. Set the MenuOffsetFromRight property to adjust the position of the shortcut menu.

##### MenuText (Character – no default value)

Contains text defining a menu, or contains the path and filename of a Visual FoxPro menu file (.MPR), depending on the value of the MenuTextIsMPR property.

If MenuTextIsMPR = .F. (default), then MenuText should contain numeric ID’s and the item text for each bar of the menu. Items in the MenuText string should be separated by semicolons. For example:

    Systray.MenuText = “1; This is bar one; 2; This is bar two”

By default, when the icon is clicked, the menu defined by the MenuText property is displayed. When the menu is clicked, or cleared by clicking outside the menu, the ProcessMenuEvent() method is called, with one parameter containing the numeric ID of the item that was selected. So with the MenuText sample above, if the user clicked on “This is bar two”, the ProcessMenuEvent() would be called, and the parameter would be the numeric value 2. If the user clears the menu without selecting an item, the ProcessMenuEvent parameter is 0.

If MenuTextIsMPR = .T., then the MenuText property should contain the full path and filename of a Visual FoxPro shortcut menu (.MPR). The ProcessMenuEvent() method is not called when MenuTextIsMPR = .T.

###### See also: ShowMenu(), ProcessMenuEvent(), IconClickEvent(), IconRightClickEvent(), MenuTextIsMPR, MenuOffsetFromRight

##### MenuTextIsMPR (Logical, default .F.)

Specifies whether the MenuText property describes the path and filename of a Visual FoxPro shortcut menu file (.MPR), or describes the numeric tokens and bar text for a simple menu to be generated on the fly.

###### See also: MenuText, ShowMenu()

##### TipText (Character, no default value)

The text to be displayed when the user moves the mouse pointer over the icon in the System Tray. Limited to 63 characters, with no linefeeds, on Windows 98, Windows NT4, and earlier. Limited to 127 characters, linefeeds allowed, on Windows ME, Windows 2000/XP, and later operating systems.

### Methods

##### AddIconToIconList(cIconFileName)

Loads an icon resource, and adds it to an internal list of icons. If there is no need to change or animate icons, use the IconFile property instead. The cIconFileName parameter should contain the full path and filename of a valid icon file. The icon file can be included in the compiled exe or dll file. After an icon has been added to the icon list, SwitchIcon() and the CurrentIconIndex property can be used to change the icon that is displayed in the System Tray. You can also change the icon just by changing the IconFile property. But if this is to be done often, using the icon list will provide greater performance, because the icon resources only need to be loaded once.

##### AddIconToSystray()

Adds the icon to the System Tray (“Taskbar Notification Area”), and enables all icon events. Occurs automatically when the Systray object is instantiated if the AddIconToSystrayAtInit property is .T. (true) and the IconFile property points to a valid icon file.

##### ClearIconList()

Removes all icons from the icon list, and removes the displayed icon from the System Tray.

##### GetShellVersion()

Returns the numeric version of the Windows Shell. Used internally for determining which features are supported by the operating system.
Returns 4.xx on Windows 98. No balloon tips supported.
Returns 5.0 on Windows 2000. Balloon tips supported, but no balloon events.
Returns 5.5 on Windows ME. Full support for balloon tips.
Returns 6.0 on Windows XP. Full support for balloon tips.

##### GetTaskbarPosition()

Used internally to determine where the menu needs to be displayed.
Returns:
0 = Taskbar docked at bottom of screen.
1 = Taskbar docked on left side.
2 = Taskbar docked at top of screen.
3 = Taskbar docked on right side.

##### IconClickEvent(), IconRightClickEvent(), IconMiddleClickEvent(), IconDblClickEvent()

See discussion of icon events below.

##### ProcessMenuEvent(nMenuItemID)

This “event” is called by Systray after the shortcut menu has been cleared by the user, either by selecting an item from the menu, or by clicking outside the menu. It only occurs if the MenuTextIsMPR property is .F. (False), and no parameters were passed to the ShowMenu() method.

If the user selected an item from the menu, the parameter will be the numeric ID for that menu item, as specified in the MenuText property. If the user cleared the menu by clicking outside the menu or changing focus to another window, the property will be 0 (zero).

###### See also: MenuText, MenuTextIsMPR, ShowMenu()

##### RemoveIconFromSystray()

Removes the icon from the System Tray. Is called automatically when the Systray object is released, so this method is rarely used.

###### See also: AddIconToSystray(), ClearIconList()

##### SetForeGroundWindow([hWnd])

Used internally, but exposed for versatility. The hWnd parameter is the system window handle for the window to be made the foreground window. If hWnd is not supplied, the form containing the Sytray class, if it is on a form, is brought forward.

##### ShowBalloonTip(cBalloonText [, cBalloonTitle [, nStandardIcon [, nTimeOut]]])

Displays a balloon tip near the icon, on supported operating systems. Balloon tips are supported on Windows ME, Windows 2000, Windows XP, and later operating systems. Windows 2000 does not support balloon events, but on Windows ME/XP, you can receive events via the BalloonClickEvent(), BalloonTimeoutEvent(), BalloonShowEvent(), and BalloonHideEvent() methods.

Parameters:

cBalloonText (Character, required) Text to display in the balloon, up to 255 characters in length. May contain linefeed characters. Set to an empty string to clear an existing balloon.

cBalloonTitle (Character, optional, default “”) Text to display as the title of the balloon, up to 63 characters in length. Set to an empty string to have no title.

nStandardIcon (Numeric, optional, default 0) Numeric ID of the standard icon to display. 0 = No icon, 1 = Info, 2 = Warning, 3 = Error.

nTimeOut (Numeric, optional, default 0) The length of time, in seconds, to display the balloon. The timeout is subject to operating system minimum and maximum values, typically 10 and 30 seconds, respectively. The timeout is also dependent on user activity. If the mouse and keyboard are idle, the timeout period will be extended.

On Windows XP, calling ShowBalloonTip() will release any existing balloon tip associated with this icon. On previous operating system, the balloons for the same icon would be queued.

Only one balloon tip may be displayed at any time, so the operating system queues requests for balloon tips. If another application is displaying a balloon tip when your application calls the ShowBalloonTip() method, your balloon tip will wait until the previous balloon’s minimum timeout has expired. On operating systems that support balloon events, you can add code the to BalloonShowEvent() method to detect when your balloon has been displayed.

###### See also: BalloonClickEvent(), BalloonTimeoutEvent(), BalloonShowEvent(), BalloonHideEvent()

##### ShowMenu([cMPRFileName [, p1 [, p2 [, p3 [, p4 [, p5 [, p6]]]]]]]) method

Displays a shortcut menu near the System Tray icon. If no parameters are specified, ShowMenu uses the contents of the MenuText and MenuTextIsMPR properties to define the menu to be displayed. Use the ShowMenu() parameters to override the contents of MenuText, and to pass parameters (by reference) to the menu program (.MPR).

Parameters:

cMPRFileName (Character, optional) The name of an MPR file that defines a Visual FoxPro shortcut menu. If this parameter is not supplied, the contents of MenuText and MenuTextIsMPR properties are used to define the menu.

p1 … p6 (Any data type, optional) Parameters to be passed (by reference) to the MPR file specified in cMPRFileName. These parameters are ignored if cMPRFileName is empty or invalid. The menu definition must have a PARAMETERS statement in its Setup code.

##### SwitchIcon()

Displays the next icon in the icon list, and returns the numeric index of the currently displayed icon. For example, if three icons have been loaded using the AddIconToIconList() method, and icon #1 is currently displayed, calling SwitchIcon() will diplay icon #2. If the last icon in the list is currently displayed, calling SwitchIcon() will display icon #1. Read the CurrentIconIndex property to determine which icon is currently displayed.

###### See also: AddIconToIconList(), CurrentIconIndex, IconFile

### Icon Events

The following methods are called by Systray when an Icon event occurs. These methods receive no parameters.

##### IconClickEvent()

Is called when the user clicks on the icon with the left mouse button. Default behavior is to call the ShowMenu() method to display the menu. This behavior can be overridden simply by placing code in the IconClickEvent method of the subclassed systray object.

##### IconRightClickEvent()

Called when the user clicks on the icon with the right mouse button. Default behavior is to call the ShowMenu() method to display the menu. This behavior can be overridden simply by placing code in the IconRightClickEvent method of the subclassed systray object.

##### IconMiddleClickEvent()

Called when the user clicks on the icon with the middle mouse button (or mousewheel). No default behavior.

##### IconDoubleClickEvent()

Called when the user double-clicks on the icon with any mouse button. On Windows ME/XP and later, the system sends the second Click event immediately after sending the Double-click event.
It can be difficult to support behavior on both the click and double-click events, since creating a modal condition (such as displaying a menu) on the Click event can prevent the Double-click from occurring. One commonly used option is to display the menu only on the right-click event.
See the Systray sample form for an example of using an external timer object to provide clean support for both click and double-click behavior.

### Balloon Tip Events

The following methods are called by Systray when it receives a Balloon event.

##### BalloonClickEvent()

Called when the user clicks on a balloon tip, or clicks on the icon while the balloon tip is displayed. Balloon events are supported on Windows ME/XP and later operating systems only.

##### BalloonShowEvent()

Called when the balloon tip is displayed by the operating system. Because balloon tips are queued by the system, this “event” may occur several seconds after the ShowBalloonTip() method is called. Balloon events are supported on Windows ME/XP and later operating systems only.

##### BalloonTimeoutEvent()

Called when the balloon is cleared due to timeout, or is released by the user clicking the close button on the balloon tip. Balloon events are supported on Windows ME/XP and later operating systems only.

##### BalloonHideEvent()

Called when the balloon tip is hidden for other reasons, such as when the icon is removed from the System Tray. Balloon events are supported on Windows ME/XP and later operating systems only.

### Working with Menus

There are three methods of using Menus with the Systray class. Deciding which one is most appropriate for your application requires knowledge of the three options.

##### Option 1: MenuTextIsMPR = .F., and no parameters passed to ShowMenu()

This is the simplest method for using menus with the Systray class. Define a menu using numeric tokens and text, and place that in the MenuText property. After the menu has been cleared by the user, either by selecting an item or clicking outside the menu, Systray calls the ProcessMenuEvent() method, passing it the numeric token for the menu item that the user selected.

    oSystray = CREATEOBJECT("MenuSample1")
    READ EVENTS

    DEFINE CLASS MenuSample1 AS Systray OF Systray.VCX

    	IconFile = HOME() + "Graphics\Icons\Misc\Face02.ico"
    	TipText = "Menu Sample #1"
    	MenuText = "1;Display Status; 2; Exit Application"

    	PROCEDURE ProcessMenuEvent
    		LPARAMETERS nMenuItemID
    		DO CASE
    			CASE nMenuItemID = 0
    				* User cleared the menu. Do nothing.
    			CASE nMenuItemID = 1
    				* Display Status
    				MESSAGEBOX("Status")
    			CASE nMenuItemID = 2
    				* Exit Application
    				THIS.RemoveIconFromSystray()
    				CLEAR EVENTS
    		ENDCASE
    	ENDPROC
    ENDDEFINE

#####
Option 2: MenuTextIsMPR = .T., and no parameters passed to ShowMenu()

If MenuTextIsMPR is True, then the MenuText property should contain the path and filename of a generated Visual FoxPro menu file (.MPR). The Systray object will then execute that MPR instead of generating a menu on the fly. This allows you to use all the features of Visual FoxPro menus, including submenus, icons, disabled items, etc.
The ProcessMenuEvent() method does not get called after an MPR file is run.

    oSystray = CREATEOBJECT("MenuSample2")
    READ EVENTS

    DEFINE CLASS MenuSample2 AS Systray OF Systray.VCX
    	IconFile = HOME() + "Graphics\Icons\Misc\Face03.ico"
    	TipText = "Menu Sample #2"
    	MenuText = "Systray_shortcut.mpr"
    	MenuTextIsMPR = .T.
    	* All work should done in the menu code, so
    	* no further code is needed here.
    	* For this example, make sure at least one
    	* menu item does a CLEAR EVENTS.
    ENDDEFINE

##### Option 3: Pass parameters to the ShowMenu() method.

By passing the name of an MPR file to the ShowMenu() method, you override the contents of the MenuText property. This also allows you to pass parameters (by reference) to the menu, and check the contents of those parameters when the ShowMenu() method returns.
In the previous examples, note that we didn’t have to add any code to display the menu. By default, the menu is displayed whenever the user clicks or right-clicks on the icon. This default behavior can be blocked by overriding the IconClickEvent and IconRightClick, as shown in this example.

    oSystray = CREATEOBJECT("MenuSample3")
    READ EVENTS

    DEFINE CLASS MenuSample3 AS Systray OF Systray.VCX
    	IconFile = HOME() + "Graphics\Icons\Misc\Face03.ico"
    	TipText = "Menu Sample #3"

    	PROCEDURE IconClickEvent
    		LOCAL lcUserChoice
    		lcUserChoice = "Unchanged" && Initialize our variable.

    		THIS.ShowMenu("Systray_Shortcut.mpr", @lcUserChoice)

    		* ShowMenu() has returned, therefore menu has
    		* been clicked or cleared.
    		DO CASE
    			CASE lcUserChoice == "Unchanged"
    				* User cleared the menu without selecting item.
    				* Do nothing.
    			OTHERWISE
    				* Take action on the user choice.
    				WAIT WINDOW lcUserChoice NOWAIT

    		ENDCASE
    	ENDPROC

    	PROCEDURE IconRightClickEvent
    		* Duplicate the above behavior for the right-click event.
    		THIS.IconClickEvent
    	ENDPROC
    ENDDEFINE