Some applications, such as games, are unlikely to continue processing while deactivated because they are user-input intensive. Other applications, however, can continue executing in the background and don't need to halt processing. When background applications have something of note to tell the user, such as when they have loaded or an activity has completed, they can use several notification techniques ranging from noninvasive to urgent, depending on how soon user intervention is required. Flashing NotificationThe simplest and least invasive notification technique is to call the form's Activate method: [6]
void timer_Tick(object sender, EventArgs e) { // Long-running task has completed ... this.Activate(); } In modern versions of Windows, Activate causes an inactive form's border and task bar button to flash three times in an attempt to grab a user's attention. [7] This is a useful technique if urgent user intervention isn't required. When the application requires more urgent user intervention, such as responding to an MSN Messenger chat request, notifications need to be more persistent, perhaps flashing continuously until the user reactivates a form. In these cases, you lean on P/Invoke to call FlashWindowEx from the User32 Windows API. [8]
System Tray NotificationFlashing is a great way to capture a user's attention, particularly if intervention is required. However, some activities can run in the background without requiring user intervention. One such application is Microsoft Outlook, which can be configured to periodically check for new messages, notifying users by placing an icon in the system tray, as shown in Figure 2.7. Figure 2.7. Microsoft Outlook New Mail Notification
This icon disappears when users read their new mail. You can support the same scenario in Windows Forms by using the NotifyIcon component, shown in Figure 2.8. Figure 2.8. NotifyIcon Component
NotifyIcon offers several properties for this purpose, including Icon (to specify the system tray icon) and Text (to set the tool tip that appears when the mouse hovers over the icon). From a notification point of view, you should hide the icon until something happens; to do this, you initially set its Visible property to false at design-time. When you need to notify users, you set NotifyIcon.Visible to true: // MainForm.cs partial class MainForm : Form { ... void mailWatcher_NewMail(object sender, EventArgs e) { // Show the system tray icon to provide latent access to // notification message this.newMailNotifyIcon.Visible = true; } } The result is shown in Figure 2.9. Figure 2.9. NotifyIcon and Tooltip in the System Tray
Further, if an application is currently inactive, you can allow users to reactivate it by double-clicking the system tray icon. To do this, you handle NotifyIcon's DoubleClick event and call Activate on the main form: // MainForm.cs partial class MainForm : Form { ... void newMailNotifyIcon_MouseDoubleClick( object sender, MouseEventArgs e) { this.newMailNotifyIcon.Visible = false; this.Activate(); NewMail(); } } If you want to stuff more functionality into a system tray icon, such as opening or closing new mail, you can do so by assigning a context menu to the system tray icon itself. One advantage of this technique is that it allows users to go directly to the desired task. To add a context menu, drag a context menu strip control onto the form, add the appropriate tool strip menu items, and associate it with the system tray icon. You do the latter by setting the NotifyIcon's ContextMenuStrip property to it, as shown in Figure 2.10. Figure 2.10. NotifyIcon and Context Menu at Design-Time
Figure 2.11 shows what this looks like at run-time Figure 2.11. NotifyIcon and Context Menu Strip at Run-Time
System Tray-Only ApplicationsAlthough the use of NotifyIcon as a notification device is transient, applications like MSN Messenger and various Windows services are accessible from the system tray for their entire lifetime. Unlike standard Windows Forms applicationswhich are minimized to and restored from the task barapplications like MSN Messenger minimize to and restore from the system tray. Adding this support to an application is similar to setting up a transient notification icon. First, you drag a NotifyIcon control onto your form, this time configuring the Icon property with the application icon. Next, you add a context menu strip to your form to expose the various commands you'd like users to be able to execute from the system tray icon, such as Open to reopen the application, Close to stop application execution, and any shortcut commands you need. [9] Finally, you implement the code that minimizes an application to the system tray. This depends on detecting when a form's WindowState changes to Minimized, after which the form should be hidden and the system tray icon shown:
// MainForm.cs partial class MainForm : Form { ... void MainForm_Resize(object sender, EventArgs e) { // Minimize to system tray if( FormWindowState.Minimized == WindowState ) { Hide(); this.appNotifyIcon.Visible = true; } } ... } Figure 2.12 shows the application's NotifyIcon and Open context menu. Figure 2.12. NotifyIcon and Open Context Menu
As Figure 2.12 shows, you select the Open command to restore the application. To make this the default command, you can handle NotifyIcon's DoubleClick event. Both are shown here: // MainForm.cs partial class MainForm : Form { ... void appNotifyIcon_DoubleClick(object sender, EventArgs e) { Open(); } void openToolStripMenuItem_Click(object sender, EventArgs e) { Open(); } void Open() { // Restore from system tray this.appNotifyIcon.Visible = false; this.Show(); WindowState = FormWindowState.Normal; } ... } As you can see, restoring from the system tray involves both hiding the system tray icon and showing the form with a Normal WindowState. [10]
On the other hand, if the application is the kind that receives a notification that doesn't necessitate form reactivation (such as a new mail message), you still need to notify the user visually. Because the main application icon is always visible, you can make it blink using a timer; or you can show another system tray icon, use a pop-up window like Outlook 2003, [11] or use NotifyIcon's balloon tip support, which is designed for this purpose. Balloon tips on system tray icons, such as the one in Figure 2.13, usually pop up for a brief period to let users know something has happened, without interfering with their current activity.
Figure 2.13. NotifyIcon Balloon Tip
The simplest way to create a balloon tip is to set NotifyIcon.Text with the balloon tip message before invoking NotifyIcon.ShowBalloonTip to display the balloon tip: // MainForm.cs partial class MainForm : Form { ... void NewMailArrived() { // If notify icon is visible, notify user of new mail if( !this.appNotifyIcon.Visible ) return; this.appNotifyIcon.BalloonTipText = "New mail has arrived!"; this.appNotifyIcon.ShowBalloonTip(3); } } ShowBalloonTip accepts an integer value that specifies the number of seconds the balloon tip will be visible. NotifyIcon provides several other balloon tip members for more interesting uses: namespace System.Windows.Forms { sealed class NotifyIcon : Component { ... // Properties public ToolTipIcon BalloonTipIcon { get; set; } public string BalloonTipText { get; set; } public string BalloonTipTitle { get; set; } // Methods public void ShowBalloonTip(int timeout); public void ShowBalloonTip( int timeout, string tipTitle, string tipText, ToolTipIcon tipIcon); // Events public event EventHandler BalloonTipClicked; public event EventHandler BalloonTipClosed; public event EventHandler BalloonTipShown; } } BalloonTipIcon, BalloonTipText, and BalloonTipTitle allow you to configure the various elements of a balloon tip you'd like displayed when ShowBalloonTip is called. ShowBalloonTip has an overload that accepts arguments that allow you to specify these properties if their values change from call to call. Additionally, NotifyIcon provides three events you can handle during the life cycle of a balloon tip. |