2

I have a C++ win32 program, and I'd like to edit the taskbar icon at runtime to display alerts, etc about the program, however I'm not too experienced with the win32 api, and I haven't been able to find anything online. The closest I've found is http://www.windows-tech.info/17/52a5bfc45dac0ade.php which tells how to load the icon off the disc at runtime and change it.

I would like to do what they do in this question: Create an icon in memory with win32 in python but in C++ and without an external library.

Cœur
  • 37,241
  • 25
  • 195
  • 267
zacaj
  • 1,987
  • 1
  • 19
  • 39
  • Possible duplicate: http://stackoverflow.com/q/1014101 – Robert Harvey May 09 '13 at 23:01
  • You might be looking for icon overlays. – chris May 09 '13 at 23:02
  • Your question is very vague. If you're talking about showing icon notifications and progress information the way Windows 7 does in the taskbar, you're looking for the `ITaskBarList`, `ITaskBarList2` and `ITaskBarList3` shell interfaces, which you can find information about on MSDN. – Ken White May 09 '13 at 23:09
  • @RobertHarvey all the answers there deal with loading an icon from the harddrive – zacaj May 09 '13 at 23:11
  • If it is icon overlays you're looking for, this article is a treat: http://blogs.msdn.com/b/oldnewthing/archive/2013/02/11/10392502.aspx – chris May 09 '13 at 23:11
  • @chris icon overlays seem to be limited to 16x16, and I still would have no idea how to generate the icon at runtime instead of loading it from the hard drive – zacaj May 09 '13 at 23:15
  • @KenWhite I do want to show icon notifications, but not necessarily the way windows does it (and also I hoped not to be limited to windows 7+). I'd like to set the whole icon to something different. – zacaj May 09 '13 at 23:17
  • @zacaj, You mean like this? http://msdn.microsoft.com/en-ca/library/windows/desktop/dd183375(v=vs.85).aspx – chris May 09 '13 at 23:26
  • Robert already told you how to set the *whole icon*. Send the window a `WM_SETICON` message, specifying the handle to your icon as the `LPARAM` value. But I recommend doing it the Windows way, since you are of course running on Windows. – Cody Gray - on strike May 09 '13 at 23:27
  • @CodyGray and how do I create an icon at runtime and get a handle to it? I've found CreateBitmap and similar functions, but they make bitmaps, not icons – zacaj May 09 '13 at 23:40
  • 2
    Can you stick to one question at a time? If you have a new question, then open a new question. But your last question already has an answer on SO. You just need to search for it: [How to load a Windows icon using a pixel buffer](http://stackoverflow.com/questions/2356001/how-to-load-a-windows-icon-using-a-pixel-buffer/2359579#2359579). – Raymond Chen May 10 '13 at 00:09
  • not possible (at least not by replacing the entire icon) in case there is a shortcut pointing to your program https://leponceau.org/programming/2022-02-18-win32-setting-program-task-bar-icon-at-runtime-programmatically.html – user1050755 Feb 18 '22 at 16:25

1 Answers1

7

I would like to do what they do in this question: Create an icon in memory with win32 in python but in C++ and without an external library

Since the accepted answer uses the wxWidgets library, which is just a wrapper of the Win32 API, the solution translates pretty nicely.

All you need to do is create a bitmap in memory using the CreateCompatibleBitmap function. Then you can draw into that bitmap using the standard GDI drawing functions. Finally, you create the icon using the CreateIconIndirect function.

The hardest part is keeping track of your resources and making sure that you free them all when you're finished to prevent memory leaks. It's way better if it's all wrapped up in a library that makes use of RAII to ensure the objects are properly freed, but if you're writing C code in C++, it would look like this:

HICON CreateSolidColorIcon(COLORREF iconColor, int width, int height)
{
    // Obtain a handle to the screen device context.
    HDC hdcScreen = GetDC(NULL);

    // Create a memory device context, which we will draw into.
    HDC hdcMem = CreateCompatibleDC(hdcScreen);

    // Create the bitmap, and select it into the device context for drawing.
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, width, height);    
    HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmp);

    // Draw your icon.
    // 
    // For this simple example, we're just drawing a solid color rectangle
    // in the specified color with the specified dimensions.
    HPEN hpen        = CreatePen(PS_SOLID, 1, iconColor);
    HPEN hpenOld     = (HPEN)SelectObject(hdcMem, hpen);
    HBRUSH hbrush    = CreateSolidBrush(iconColor);
    HBRUSH hbrushOld = (HBRUSH)SelectObject(hdcMem, hbrush);
    Rectangle(hdcMem, 0, 0, width, height);
    SelectObject(hdcMem, hbrushOld);
    SelectObject(hdcMem, hpenOld);
    DeleteObject(hbrush);
    DeleteObject(hpen);

    // Create an icon from the bitmap.
    // 
    // Icons require masks to indicate transparent and opaque areas. Since this
    // simple example has no transparent areas, we use a fully opaque mask.
    HBITMAP hbmpMask = CreateCompatibleBitmap(hdcScreen, width, height);
    ICONINFO ii;
    ii.fIcon = TRUE;
    ii.hbmMask = hbmpMask;
    ii.hbmColor = hbmp;
    HICON hIcon = CreateIconIndirect(&ii);
    DeleteObject(hbmpMask);

    // Clean-up.
    SelectObject(hdcMem, hbmpOld);
    DeleteObject(hbmp);
    DeleteDC(hdcMem);
    ReleaseDC(NULL, hdcScreen);

    // Return the icon.
    return hIcon;
}

Adding the error checking and the code to draw something interesting onto the bitmap is left as an exercise for the reader.

As I said in a comment above, once you have created the icon, you can set the icon for a window by sending it a WM_SETICON message and passing the HICON as the LPARAM:

SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);

You can also specify ICON_SMALL in order to set the window's small icon. If you set only a big icon, it will be scaled down to create the small icon automatically. However, if you set only the small icon, the window will continue to use the default icon as its big icon. Big icons typically have a dimension of 32x32, while small icons typically have a dimension of 16x16. This is not, however, guaranteed, so do not hardcode these values. If you need to determine them, call the GetSystemMetrics function with SM_CXICON and SM_CYICON to retrieve the width and height of big icons, or SM_CXSMICON and SM_CYSMICON to retrieve the width and height of small icons.

A fairly good tutorial on drawing in Windows using GDI is available here. I recommend reading it thoroughly if this is your first time doing this and have no prior experience with GDI.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574