This is one in a series of articles about Time Tortoise, a Universal Windows Platform app for planning and tracking your work schedule. For more on the development of this app and the ideas behind it, see my Time Tortoise category page.
To build a companion app that implements functionality that a UWP app can’t, it’s necessary to pick a non-UWP technology to use. Here are a few options:
- A Windows service: Since the Time Tortoise Companion App only needs to send messages to and receive messages from Time Tortoise, it may not require a user interface. A Windows service allows code to run in the background on Windows, without a UI. I have a couple of concerns with this approach: 1) It’s a bit unfriendly, especially for users unfamiliar with Windows services, to have a mysterious service running in the background; and 2) I may find a need for a companion app UI in the future. This is not in itself a good enough reason to avoid the Windows service approach, but it’s a strike against it.
- A Windows Forms app: This solves both of the concerns with the Windows service. But there’s no reason to use this ancient UI framework for a brand new app, when there are other options available.
- A Windows Presentation Foundation app: WPF isn’t as cutting-edge as UWP, but it uses the same UI markup language (XAML). And since it is widely used, it’s likely to support any functionality that I need. So that’s what I’m going with for the companion app.
The Windows Taskbar Notification Area
The Time Tortoise user interface is almost entirely handled by UWP, so Time Tortoise Companion doesn’t need much in the way of its own UI. However, it’s convenient for the user to be able to see that the companion app is running. This lets them know that they’re getting the extra functionality that it provides, and gives them a convenient way to close it.
The Windows taskbar includes a section where apps can display small icons. This section is officially called the notification area, though many people use the unofficial term system tray. By default, it’s located at the bottom right of the screen, between the clock and the rest of the taskbar. Common icons in that area include ones for the battery level, volume control, and network status.
For some types of apps, like a text editor, it makes sense to have a taskbar button. These are apps that the user frequently interacts with. Time Tortoise Companion just works in the background, so there’s no need for it to take up space in the taskbar. Instead, it belongs in the notification area.
WPF, it turns out, doesn’t have a built-in way to create notification icons. Fortunately, the framework has been around for many years, and components have been created to fill this gap. The best one seems to be Hardcodet WPF NotifyIcon by Philipp Sumi, so that’s what I’m using.
Hardcodet.NotifyIcon.Wpf
To create a notification icon with Hardcodet.NotifyIcon.Wpf, I first created a new WPF project called TimeTortoise.WPF
. The project starts out looking similar to a new UWP project, with App.xaml
and MainPage.xaml
files. Running the project shows a blank window with the familiar debug mode UI controls.
Hardcodet.NotifyIcon.Wpf has a wide range of features, but I’m only using a few of them for now. With the help of the NotifyIcon sample app, I created a Time Tortoise notification icon as follows:
- In
MainWindow.xaml
, add a tag of typeTaskbarIcon
(from theHardcodet.Wpf.TaskbarNotification
namespace). - Create an image file in
.ico
format. I used my handy SVG logo as the source, and converted it to.ico
using one of the many online image conversion tools. - Assign it to the taskbar icon using the
IconSource
property.
I made the main window invisible, since I’m not currently using it for anything.
For now, the notification icon’s only jobs are: 1) To show that Time Tortoise Companion is running, and 2) To allow the user to exit the companion program. Job #1 is accomplished just by creating the icon. For #2, we can use a context (right-click) menu:
- Add a new XAML file called
NotificationIconResource.xaml
containing aResourceDictionary
. In the resource dictionary, add aContextMenu
with a singleMenuItem
called Exit. Have the menu item call aCommand
calledExitCommand
.
The NotifyIcon
sample code has a helper class called CommandBase
that ExitCommand
can inherit from:
- In the
ExitCommand
class, override theCanExecute
method to return true, and theExecute
method to callApplication.Current.Shutdown
. This will exit the program when the user selects the menu item.
With the notification icon in place, it’s easy for the user to see that the companion app is running, and exit it if they want to.