Search code examples
c++winapiwindows-shellsystem-traytrayicon

How to properly update tray notification icon?


Say, I created my icon:

//'ghIcon' of type HICON
ghIcon = LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, nCx, nCy, 0);

and then set it to be displayed on system tray:

NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.hWnd = hMyWnd;
nid.uID = TRAY_ICON_ID1;
nid.uFlags = NIF_ICON;
nid.uCallbackMessage = TRAY_NOTIFICATION_ID1;
nid.hIcon = ghIcon;

Shell_NotifyIcon(NIM_ADD, &nid);

and then at some point I want to replace it with a new icon:

if(ghIcon)
{
    //Delete old icon first
    DestroyIcon(ghIcon);
}

//Load new icon
ghIcon = LoadImage(m_hInstance, MAKEINTRESOURCE(IDI_ICON2), IMAGE_ICON, nCx, nCy, 0);

NOTIFYICONDATA nid;
memset(&nid, 0, sizeof(nid));
nid.cbSize = sizeof(nid);
nid.hWnd = hMyWnd;
nid.uID = TRAY_ICON_ID1;
nid.uFlags = NIF_ICON;
nid.hIcon = ghIcon;

Shell_NotifyIcon(NIM_MODIFY, &nid);

My question is, can I delete the previous icon while it's still selected in system tray, like I showed above? Or, do I need to change it to something else first and then call DestroyIcon on it?

PS. My actual example is obviously not as simple as I showed above. I'm just curious about the concept.


Solution

  • The system tray does not keep the HICON that you give it. It makes a private copy. So you are free to destroy the icon on your side whenever you want. You don't have to keep it around, you could load it just before calling Shell_NotifyIcon(), and then destroy it immediately after Shell_NotifyIcon() exits.

    nid.hIcon = LoadImage(...);
    Shell_NotifyIcon(NIM_ADD, &nid);
    DestroyIcon(nid.hIcon);
    

    nid.hIcon = LoadImage(...);
    Shell_NotifyIcon(NIM_MODIFY, &nid);
    DestroyIcon(nid.hIcon);