WPF/XAML NotifyIcon and Taskbar (System Tray) Popup Window






4.90/5 (77 votes)
Integrating WPF and XAML with the Windows forms NotifyIcon control to produce a slick, styled popup window when the mouse is moved over the NotifyIcon
Table of Contents
- Introduction
- Background
- Prerequisites
- Running the Demo
- Using the Code
- Points of Interest
- Known Issues
- History
Introduction
I wanted to produce a WPF application that "sits" in the Windows system tray and displays a popup window that fades in and out when the mouse moves over the taskbar icon. In addition, I wanted the user experience to be slick and smooth. I had seen the Live Mesh taskbar client and really liked the way it worked and I thought something similar would be perfect for the application I had in mind.
I have shared this sample to give others a head start on projects with similar requirements.
Background
Producing this popup window proved more difficult than expected as there was a lot of fiddly work involved. The look and feel did not quite display what I wanted and the window animations were initially very clunky. In hindsight, I would have sketched the design and a storyboard out on paper or in Visio before diving in. When using the designers in WPF, XAML can bloat rapidly and one really needs to be careful how you compose your UI elements and animations in order to retain maintainability and flexibility.
A number of unexpected challenges also surfaced and initially the overall goal of a slick and smooth interface seemed very far away. After an initial investigation and some exploratory code, I found that:
- WPF does not natively support a taskbar / system tray icon and the Windows Forms implementation would have to be leveraged
- The standard
NotifyIcon control
does not support a mouse leave event - Animating a WPF window to fade in and out seamlessly and handle interruptions proved difficult
Prerequisites
- .NET Framework 3.0 or higher
- Windows XP, 2003, Vista, 2008
Running the Demo
Extract the demo from the archive and run WpfXamlPopup.exe. The following diagram and corresponding points will walk you through the features and user interface:
![]() |
Moving the mouse over the taskbar icon will result in the popup window displaying. |
![]() |
Moving the mouse off of the taskbar icon will delay a fraction of a second and then fade the popup window out of view. The short delay allows the mouse to seamlessly move over the desktop and over the popup window. This allows time for the fade out to be cancelled and the user can interact further with the popup window. |
![]() |
The "PIN" button pins the popup window open regardless of where the mouse pointer is on the desktop. |
![]() |
The "CLOSE" button unloads the popup window and taskbar icon and closes the application. |
![]() |
Sample buttons that could be used in an application - I wanted to create an effect where the buttons appear to pop in to focus. |
![]() |
This radio button group provides a demonstration of how easily the taskbar icon can be changed. |
Using the Code
When opening the solution files (source code) for the first time, build the solution so that the project references resolve correctly and the popup window can be viewed in the designer. The code is verbosely commented, so I will not go into much detail, however, I will explain the general architecture and project structure to ramp up your understanding of the solution.
The solution supplied, WPF XAML Notify Icon and Popup.sln
, contains two projects:
ExtendedWindowsControls
: A class library that exposes the Windows FormsNofityIcon
control and decorates it with additional methods to cater to the interaction required by this project. It would have been ideal to inherit form the Windows FormsNotifyIcon
class, but unfortunately it is a sealed class, which prevents inheritance.WpfXamlPopup
: The primary project and should be set to the start-up project if you wish to run the application directly from Visual Studio. The project houses the popup window, fade in and out animations and visual style resources.
I will discuss the code file by file, numbered per project below.
Project: ExtendedWindowsControls - This project provides a container for extensions to Windows Forms controls. |
|
![]() |
ExtendedNotifyIcon.cs :
|
Project: WpfXamlPopup - This is the primary project and contains the WPF popup window. |
|
![]() |
The Images folder contains all images used in the project. This includes different coloured orbs for changing the appearance of the icon in the taskbar and button images for the pin and un-pin actions. |
![]() |
App.xaml: contains references to various re-usable XAML components stored in resource dictionaries. These include: SlickButtonRD.xaml, MainGridStyleRD.xaml and StealthButtonRD.xaml - discussed below. |
![]() |
HorizontalSeparatorRD.xaml: A simple user control that uses a combination of rectangles to produce a separator line with an "engraved" effect. |
![]() |
MainGridStyleRD.xaml: is a resource dictionary that holds the style for the main grid. The main grid forms the basis of the popup window and defines:
|
![]() |
MainNotifyWindow.xaml: is the XAML for the main form. Thanks to the resource dictionary files and user controls, this main window XAML is simple, uncluttered and elegant and easy to comprehend. During this little foray into WPF, I found that XAML files can quickly become cumbersome and unmanageable. If you use Blend, this becomes even more troublesome as it is easy to generate a lot of irrelevant artifacts which are unused / orphaned and these can become tiresome to clean up.
|
![]() |
MainNotifyWindow.cs:
|
![]() |
SlickButtonControl.cs: The SlickToggleButton control extends the standard toggle button by adding additional properties to it. These properties are used by the style defined in SlickButtonRD.xaml. By extending the ToggleButton , I have removed the need for multiple styles when requiring some subtle changes to the button, for example, having different background colours and different corner radius profiles. |
![]() |
SlickButtonRD.xaml: This resource dictionary contains the style for the toggle buttons in the control box and is used for the Close and Pin buttons. I will not go into extensive detail, but these buttons are complex and are constructed through a control template consisting of 3 border elements to create the background, the border style and then the content target for the button content to be presented in. The Triggers exposed handle the MouseOver and Checked properties to create visually appealing button controls. |
![]() |
StealthButtonRD.xaml: This resource dictionary contains the style for the buttons across the bottom of the popup window. The buttons are unobtrusive to look at on the popup window, but when you move the mouse over them they "pop in to life". This is achieved by using a "dormant/normal" style and a "mouse over" style. A storyboard with a ThicknessAnimation and manipulation of the button margins provides the "popping" effect. |
Points of Interest
- Overall, I am satisfied with how this little application works. The animations are slick, the taskbar icon is responsive and the user experience has a quality feel to it.
- In the future, I will sketch concepts out on a whiteboard before beginning a WPF or Silverlight project. I found that trying to lay out items on the canvas and then shift them around and change the styling to be time consuming, messy and fiddly. I found it much easier to outline a concept with some other canvas (or paper) and generate a WPF design from this.
- WPF memory consumption with maximised forms can be quite aggressive. That said, the memory manager does a good job of freeing resources when the window is hidden or minimized.
- A slick WPF design with smoothed edges and reliable animation looks great - but comes at a price. I spent far longer putting this together than I expected and I can't help but think a lot of WPF projects will get delayed due to underestimation of user interface requirements.
- Integrating the Windows Forms NotifyIcon with WPF was simple and works effectively.
- I found that the Blend designer really helped me get going in the start, but later it bogged me down when trying to do more technical items and it also produced superfluous code. I effectively started in Blend and then refactored and finished off in Visual Studio as Blend was just proving too messy and I did not feel I had good control over separation of components and the trickier styling work in Blend.
Known Issues
- Memory usage can be high when the window is visible and in use - I have not found a decent way to manage this better.
- Occasionally the form (when pinned open) can lose its topmost position and become obscured by another window. I am not sure if this is my issue or an issue in the .NET Framework. Please let me know if you experience the same issue or have previously seen this.
History
- V1.0 - Initial release
- V1.1 - Taskbar integration will be shipped in .NET 4 and should allow this solution to lose its WinForms dependency. See the presentation at http://mschannel9.vo.msecnd.net/o9/mix/09/pptx/t39f.pptx or check out the video at MIX http://videos.visitmix.com/MIX09/T39F for some further information on WPF 4.0 features.
- V1.2 (4 August 2010) - I have tested upgrading the project to Visual Studio 2010 and targeting the .NET 4.0 framework (you must set this on the project properties). The upgrade was a quick and simple process and the application still appears to work perfectly on .NET 4. Result!
- V1.3 (04 November 2015) - I have tested, once again, upgrading the project to Visual Studio 2015 and targeting the .Net 4.6 framework. The upgrade was a quick and simple process and the application still appears to work perfectly on .Net 4.6. Result!
I hope you enjoyed this article and sample. Suggestions, questions and comments are very welcome as well as your vote on how you rate the article and code.