MarthinusSwart.com

System Tray Application

To create a little tray icon application in C++ is not as easy as C# or more specifically .NET, but it is also not too complex. There is basically three main steps involved

  • Load the icon resource
  • Create the window and finally
  • Create the tray icon data
Loading the icon resource is the easiest of the three steps.

// The m_hInstance is the instance of the application
HICON ic = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON1));
if (ic == NULL)
  MessageBox(NULL, "Failed to load icon", "Failed", MB_OK);

// Load the small icon that will appear in the system tray
HICON icsm = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_ICON2));
if (icsm == NULL)
  MessageBox(NULL, "Failed to load icon", "Failed", MB_OK);

After creating the icon instance, the window of this application needs to be created. The creation of the window is the most involved step of all three the steps.

// Create the window
m_wndClass.cbSize = sizeof(m_wndClass);
m_wndClass.style = CS_VREDRAW | CS_HREDRAW;
// The windows procedure that will handle all the incoming messages
m_wndClass.lpfnWndProc = WndProc;
m_wndClass.cbClsExtra = 0;
m_wndClass.cbWndExtra = 0;
// The instance of this application
m_wndClass.hInstance = m_hInstance;
m_wndClass.hIcon = ic;
m_wndClass.hCursor = LoadCursor(m_hInstance, IDC_ARROW);
m_wndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
m_wndClass.lpszMenuName = (const char*) NULL;
m_wndClass.lpszClassName = "CServiceStarter";
m_wndClass.hIconSm = ic;

HRESULT res = S_OK;
// Register this window class
res = RegisterClassEx(&m_wndClass);
if (FAILED(res))
  MessageBox(NULL, "Failed to register class", "Failed", MB_OK);

HWND hwnd = CreateWindow("CServiceStarter", "Dejevu Service Starter", WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU, getDesktopCenterX(), getDesktopCenterY(), m_iWidth, m_iHeight, NULL, NULL, m_hInstance, NULL);

if (m_hwnd == NULL)
  MessageBox(NULL, "Failed to create window", "Failed", MB_OK);

After the window was created all that remains is to create the necessary system tray information.

NOTIFYICONDATA m_nid;
m_nid.cbSize = sizeof(m_nid);
// The window that will be used when the tray icon is clicked
m_nid.hWnd = m_hwnd;
m_nid.uID = IDI_ICON2;
// The system tray icon that will be used
m_nid.hIcon = icsm;
// The flags that will allow the tray icon to display a tooltip and an icon
m_nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
// The custom message that will be raised to initiate a callback
m_nid.uCallbackMessage = WM_TRAYNOTIFY;
// Add a tooltip
addToolTip(m_nid.szTip, "Server Status", 21);

// Add the new system tray notification to the system tray
res = Shell_NotifyIcon(NIM_ADD, &m_nid);
if (FAILED(res))
  MessageBox(NULL, "Failed to register tray icon", "Failed", MB_OK);

This is the core requirements to create a system tray application. Full example source code is available here.