Archive for February, 2009


So here I was, happily programming my little stopwatch, I had already created my system tray icon and embedded some version info into. Now I was ready to implement to heart of my application, A popup menu to control the stopwatch. I looked up msdn, searched the net and came up with my code to create the popup menu.

From what I understood, it was a three step process create a handle to a menu, append items to the menu and display the menu using ‘TrackPopupMenu’. To start of with, I decided to implement just two commands under the menu. Just to test out the code and how it works. Following is the code that I implemented.

HMENU hPopup = CreateMenu();
AppendMenu(hPopup, MF_STRING, ID_START, L"Start");
AppendMenu(hPopup, MF_STRING, ID, L"Stop");

POINT pt;
GetCursorPos(&pt);

TrackPopupMenuEx(hPopup, TPM_RIGHTALIGN  | TPM_LEFTBUTTON, pt.x, pt.y, hWnd, NULL);

DestroyMenu(hPopup);

I compiled my code and ran my program. I rightclick on my icon and Bam, A menu as thin as angel hair spagehti, with no strings displayed. Check out the screenshot.

Menu over my system tray icon

Tray Icon Menu

Menu over the application Window

Menu over the application Window

As you can see in the two screen shots, the menu has the required number of rows, i.e. 3 as per my description and it even sends out the appropriate messages when one of them is clicked, It just doesn’t display anything. This little discrepancy took me a while to figure out. From what I found out, this problem is faced by people new to win32. This is one of those little Idiosyncrasy of win32 API. The way to resolve this problem is a bit peculiar.

To get the menu displaying properly, first we need to append our menu to a temporary menu as a POPUP to it, then we have to extract the menu back using GetSubMenu function and use that handle in TrackPopupMenuEx function. The code below would explain it much better.

HMENU hPopup = CreateMenu();
HMENU hTemp = CreateMenu();

AppendMenu(hPopup, MF_STRING, ID_START, L"Start");
AppendMenu(hPopup, MF_STRING, ID_STOP, L"Stop");

AppendMenu(hTemp, MF_POPUP, (UINT_PTR) hPopup, L"Dummy");
hPopup = GetSubMenu(hTemp, 0);

POINT pt;
GetCursorPos(&pt);
TrackPopupMenuEx(hPopup, TPM_RIGHTALIGN | TPM_LEFTBUTTON, pt.x, pt.y, hWnd, NULL);

DestroyMenu(hTemp);
DestroyMenu(hPopup);

And with that, my popup menu gives up its diet and displays perfectly.

Menu after it stopped Dieting

Menu after it stopped Dieting

I hope this helps out people who are just starting out with win32 and ran into this problem, as I had to spend a lot of time trying to figure out this problem.

What if the menu is defined as a resource

Let me define the orginal menu as a resource, remember this will show up as a thin bar.

First the resource.rc file

MENUDEMO MENU DISCARDABLE
BEGIN
    MENUITEM "Start"  ID_START
    MENUITEM "Stop"   ID_STOP
END

To fix this description, we have to add a fake POPUP block to the description as follows.

MENUDEMO MENU DISCARDABLE
BEGIN
     POPUP "Dummy"
     BEGIN
          MENUITEM "Start" ID_START
          MENUITEM "Stop"  ID_STOP
     END
END

Now as before, we would extract the submenu using the GetSubMenu function and then display the submenu using TrackPopupMenuEx function.

I hope this helps out everyone, as it was very frustrating to figure this problem out. Do drop by and let me know if there is a better way of solving this problem, I would love to hear about it.

In windows xp, whenever we right click on an executable file, we can see a Version info tab.

Tab displays additional information of the executable

Tab displays additional information of the executable

To include this information in our application, we need to create a VERSIONINFO resource in our application. This would generally be in your .rc file.

For example the resource file for the above executable is as follows.

#DEFINE VER_FILEVERSION          1,0,0,0
#DEFINE VER_FILEVERSION_STR      "1.0"
#DEFINE VER_PRODUCTVERSION       1,0,0,0
#DEFINE VER_PRODUCTVERSION_STR   "1.0"

VS_VERSION_INFO        VERSIONINFO
FILEVERSION            VER_FILEVERSION
PRODUCTVERSION         VER_PRODUCTVERSION
FILEOS                 VOS_NT_WINDOWS32
FILETYPE               VFT_APP
FILESUBTYPE            VFT2_UNKNOWN
BEGIN
     BLOCK "StringFileInfo"
     BEGIN
         BLOCK "040904E4"
         BEGIN
             VALUE "CompanyName"          "Testing Times"
             VALUE "FileDescription"      "Testing My Version Info"
             VALUE "LegalCopyright"       "Copyright 2009 (c) PJ. All rights reserved."
             VALUE "ProductName"          "Test Ahoy!!"
             VALUE "ProductVersion"       VER_PRODUCTVERSION_STR
             VALUE "FileVersion"          VER_FILEVERSION_STR
         END
     END
END

We can also define custom parameters in the StringFileInfo block, such asĀ  support information, contact information etc.

The msdn article on VERSIONINFO is quiet detailed, so I am just going to point to it for further reference.

VERSIONINFO – Click here to goto to MSDN.

I took up a project to create a simple Stopwatch. The aim of the project was to keep a track of the time I spend on various projects. I wanted a very simple application which was able to Start Pause and Stop a Stopwatch.

The best approach that I thought up was through a System Tray application. This would give me easy access to the controls and display, without interfering with my open windows. As I am trying to have a go at C++ and win32, I decided to implement it using Visual C++ 2008 express edition and win32 API.

So without any further delay, here are the basic steps needed to create an icon in the system tray.

  1. Include the “shellapi.h” header file, and link to “shell32.lib” library (Visual C++ links to it by default.
  2. Define a custom message identifier for our icon. Whenever there is a mouse or keyboard event on our icon, windows will use this identifer to send messages to our message procedure.
  3. Create and initialize the NOTIFYICONDATA structure according to our needs.
  4. Invoke Shell_NotifyIcon() API, with a pointer to NOTIFYICONDATA, to create, modify or delete our icon.

To demonstrate the steps let us consider this example. For our application, we would like to have an icon in the system tray. It should display a message box whenever it is double clicked and ‘Tray Icon’ whenever the mouse hovers on top of it.

To begin with we need to include ‘shellapi.h’ in our application.

#include <shellapi.h>

The next step would be to define a custom message identifier. Whenever a mouse event occurs on our icon, Windows will send this custom message to our message procedure. The lParam variable will have the actual mouse or keyboard event and wParam will contain the iconid.

#define WM_MYMESSAGE (WM_USER + 1)

Now we should create a variable of type NOTIFYICONDATA and populate it as per our icon’s need. I will first show the example, before explaining the structure further.

NOTIFYICONDATA nid;

nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 100;
nid.uVersion = NOTIFYICON_VERSION;
nid.uCallbackMessage = WM_MYMESSAGE;
nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcscpy_s(nid.szTip, L"Tray Icon");
nid.uFlags = NIF_MESSAGE NIF_ICON NIF_TIP;

Shell_NotifyIcon(NIM_ADD, &nid);

cbSize : It indicates the size of our structure.

hWnd : It takes the handle to our window which will process the messages from our icon.

uID : This is a unique Id for our icon. Shell uses hWnd + uID to identify which icon to operate on when Shell_NotifyIcon() is invoked.

uVersion : It defines the behavior of our icon, i.e. whether it should behave like a windows 98 icon, a windows xp icon or windows Vista icon. Based on the value of this variable, certain other variables of the NOTIFYICONDATA become available to us. (refer to MSDN for more info).

uCallBackMessage : This indicates the message to be sent to the message procedure whenever a mouse event occurs on our icon.

hIcon : This stores the handle to the Icon to be used for display in the system tray. Any icon that is available to our application can be used, here I have used the system defined icon.

szTip : Here we can store a null terminated string which will be displayed near the icon, whenever the mouse is on it. The type of variable depends on your language settings, I am using the unicode version in the example.

uFlags : This variable defines whether the variables are uCallbackMessage, hIcon and szTip are valid or not. This is achieved by bit masks NIF_MESSAGE, NIF_ICON, NIF_TIP.

Once we have defined our NOTIFYICONDATA structure, we should invoke Shell_NotifyIcon() as follows.

Shell_NotifyIcon(NIM_ADD, &nid);

This will create and display our icon in system tray. As we can see Shell_NotifyIcon takes two parameters.

  1. dwMessage : This could be NIM_ADD, NIM_MODIFY or NIM_DELETE.
  2. lpdata : A pointer to our NOTIFYICONDATA variable, which defines our icon.

The last thing that we need to do is capture and process the WM_MYMESSAGE message in our message procedure. Consider a typical message handler procedure as follows.

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_CREATE:
         break;
    ....
    ....
    case WM_MYMESSAGE:
         switch(lParam)
         {
         case WM_LBUTTONDBLCLK:
                 MessageBox(NULL, L"Tray icon double clicked!", L"clicked", MB_OK);
                 break;
         default:
                return DefWindowProc(hWnd, msg, wParam, lParam);
         };
         break;
     .....
     .....
     default:
           return DefWindowProc(hWnd, msg, wParam, lParam);
     };
     return 0;
 }

Here you can see that we are trapping our WM_MYMESSAGE and then checking lParam to see what mouse event occured. As described in our example, we wanted to show a messagebox whenever our icon is double clicked. Thus we are processing the WM_LBUTTONDBLCLK message from the lParam variable. We can process other messages also, as per the application’s requirements. For example, we can process WM_LBUTTONUP to do something whenever a user clicks on it etc.

In this way we can create, display and interact with our System Tray Icon.

To delete the icon whenever we are done with it, for example when our program is exiting we should define the NOTIFYDATAICON to point to our icon and call Shell_NotifyIcon with NIM_DELETE message. For example, to delete the icon created above we need to define.

NOTIFYICONDATA nid;
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 100;
Shell_NotifyIcon(NIM_DELETE, &nid);

We don’t have to define any other member of the NOTIFYICONDATA structure.

Similarly to modify the icon we should define the NOTIFYICONDATA and call Shell_NotifyIcon with NIM_MODIFY. For example to modify the icon tip.

NOTIFYICONDATA nid;
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hWnd;
nid.uID = 100;
wcscpy_s(nid.szTip, L"Modified Tip");
nid.uFlags = NIF_TIP;
Shell_NotifyIcon(NIM_MODIFY, &nid);

We can combine NIF_TIP and NIF_ICON to modify the tip and icon together.

Well thats about it regarding the system tray icons and how to use them.

A note regarding WM_MYMESSAGE :
As you can see I defined WM_MYMESSAGE as WM_USER + 1, this is because, all the message numbers below 1024(0x0400) are reserved by Windows. If you checkout WinUser.h file, you will see that WM_USER has been defined as 0x0400 (1024), thus we can base our custom messages starting with this value.

Hello world!

I am planning to use this blog as a place to store my notes and to share the information across the net. By doing it on a blog, I can also get feedback if I have gone wrong somewhere. To start of with, I am planning to create a simple application using Visual C++ and win32 api. So hope everyone enjoys these blogs.