Remember the Process Viewer that we worked on a few months back? I was wondering how to display the applications icons, the way task manager does. A small icon beside the application name gives it a pleasant look. So how do you extract the icon from an executable? Well, there’s an API for that (pun). ExtractIconEx() is the function we use to get a handle to the applications icon. It’s a simple API, just give it the full path to the executable and it returns an HICON (icon handle). So I went back to my Process Viewer and added a static label to display the icon. Here is the code:
HICON hIcon, hIc;
hIcon = ExtractIconEx(filename, 0, NULL, &hIc, 1);
if(!hIcon)
{
hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));
}
SendMessage(g_hStaticIcon, STM_SETIMAGE, IMAGE_ICON, (LPARAM)hIcon);
If the handle returned is NULL (for applications without user interface) then we display a default icon, the terminal. After getting the icon handle, we set it on the label using STM_SETIMAGE message.
Now to the interesting part. An application can contain quite many icons as resources, so how does the system know which icon to return? The answer is that the system chooses the icon whose resource identifier value is the smallest and returns it as the application icon. So if I have three icons in my application whose identifiers are defined as: (in Resourceppc.h)
#define IDI_ICON1 103
#define IDI_ICON2 104
#define IDI_ICON3 105
then the resource IDI_ICON1 will be returned.
Here is another interesting bit, the static label (in the video below) was created using CreateWindow() as follows:
g_hStaticIcon = CreateWindowEx(0, L"STATIC", NULL, WS_CHILD | WS_VISIBLE | SS_ICON |
SS_REALSIZEIMAGE, x, y, 16, 16, hWndParent, 0, g_hInst, NULL);
Now a static image label will expand itself if the image being displayed on it is bigger than the label size. This is what you wouldn’t want, imagine some application icons displayed in 16×16 pixels while others in 32×32. So to prevent this automatic scaling of the label we use the SS_REALSIZEIMAGE flag in the CreateWindow() call. But according to MSDN, SS_REALSIZEIMAGE is listed under "Unsupported static control styles".
If you have seen the video below already, then you’ll notice that the gwes.exe icon appears larger. There could be two reasons, either all other application’s icons are getting scaled down to 16×16 and gwes.exe’s isn’t (wonder why), or there is no scaling happening and all other applications are returning 16×16 icons while gwes is returning a larger 32×32 icon (unlikely). Now if I remove the SS_REALSIZEIMAGE flag while creating the label then all the icons are displayed big (32×32)! This means that scaling down is indeed happening and SS_REALSIZEIMAGE, although listed under ‘Unsupported static control styles‘, still works. I am a little confused as to why this is happening, if you got a clue then do let know.
Here’s the video:
Displaying the icons like I did above is just the proof. Next step would be to display the icons right beside the application name (who needs serial number!), got to look at list views and images. And hopefully the image scaling problem should resolve itself with list_view images.