Win32: Hide to system tray – Part 1
I used to code in C++ a lot. And I mean, a lot. For instance, at previous gig, I created an application that measures bandwidth between multiple clients and a server. Interesting project. Specially since three quarters down that road, I had to port it from Windows platform to Linux. But that is entirely different story. However, as years went by, there was less and less things I found comfortable doing in C++. Mostly because (and I know this sounds as a heresy) C# has become my favourite language. But that is as well another story.
Lately, though, I decided to rekindle my C++ knowledge. As a result, you will be seeing some of my C++ work up here. My first project, RGB to Hex converter, was presented online about a month ago. Now I decided to go for something Windows based and created an empty Win32 application that can hide to tray and then redisplay again. Part 1 will cover hiding application and displaying icon in system tray.
Step 1 – Idea
Basically, we don’t need much. We need an empty Win32 application that will hide and display an icon in system tray upon user clicking big red X (aka close button) in top right corner. When hidden, a double click on a tray icon should redisplay an application. Additionally, a single click (left or right mouse button) on tray icon should display a popup menu with options to show application or exit application entirely.
Also, File->Exit option should exit the application.
Step 2 – Create an empty Win32 application
This step is easy. Just fire up Visual studio and created a new C++ Win32 application project. Also, leave all settings as they are by default. Now, if you build the project and go into debug, you will be presented with Windows that contains:
- minimize, maximize and close buttons;
- menu containing File->Exit and Help->About options;
- empty content.
You are good to roll.
Step 3 – Create a function that will draw a system tray icon
When you hide an application from users view, you do need to present user some sort of option to redisplay the app. This is where system tray icon comes in handy.
Now, I am used to do definitions in header files, so I created tray.h and tray.cpp, which will contain all functions related to hiding to and displaying from system tray. You don’t have to do them and can easily implement them straight in your myprojectname.cpp file. But I prefer to separate code in smaller blocks. So, this is how they look:
#pragma once #include "resource.h" #include <shellapi.h> #define TRAY_ICONUID 100 extern HINSTANCE hInst; void TrayDrawIcon(HWND hWnd);
#include "stdafx.h" #include "tray.h" // // FUNCTION: TrayDrawIcon(HWND) // // PURPOSE: Draws application icon in a system tray // // void TrayDrawIcon(HWND hWnd) { NOTIFYICONDATA nid; nid.cbSize = sizeof(NOTIFYICONDATA); nid.hWnd = hWnd; nid.uID = TRAY_ICONUID; nid.uVersion = NOTIFYICON_VERSION; nid.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALL)); LoadString(hInst, IDS_APP_TITLE, nid.szTip, 128); nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; Shell_NotifyIcon(NIM_ADD, &nid); }
TrayDrawIcon is where all the groovy stuff happens. Basically, you fill NOTIFYICONDATA struct with data about your window and icon and then call Shell_NotifyIcon function which adds it to the system tray. In this case, I also decided to display application title stored in string table as IDS_APP_TITLE as a text displayed when I hover over the icon with mouse cursor.
Also, TRAY_ICONUID can be a custom value. I like 100, and thus 100 it is.
Step 4 – Hide application on close event
Now, we are ready to implement hiding an application when window closes and display an icon in system tray. Go to myprojectname.cpp and find WndProc function. In it, there is basically a switch statement that handles messages sent to current application. In this switch statement, add the following:
case WM_CLOSE: TrayDrawIcon(hWnd); ShowWindow(hWnd, SW_HIDE); break;
WM_CLOSE is a message fired by default by a red X button in top right corner of applications title bar. As mentioned, function TrayDrawIcon draws a system tray icon. Function ShowWindow actually hides a window providing nCmdShow parameter is set to SW_HIDE.
Do not forget to include tray.h:
#include "stdafx.h" #include "tray.h"
Step 5 – Rebuild and Run
Now you are ready to rebuild your application and run it. I suggest using a debugger so that you can stop it without the need of a Task Manager.
What’s Next
In Part 2, we will implement a way to redisplay an application using double click on system tray icon.
March 28th, 2013 at 08:17
[…] Part 1 of the series, we have seen how we can hide the application and display an icon in system tray. In […]
April 4th, 2013 at 08:10
[…] Part 1 of the series, we have seen how we can hide the application and display an icon in system tray. In […]