LukeN
LukeN

Reputation: 142

Clear notification tray icon, windows shell

Question: Where the notification icon is registered and how to remove it when it was already registered from a different location?

Description: I want to use notification tray icon, so I started a Windows SDKs sample to check how it works.

The problem is that once the icon is registered from one location it can't be used anywhere else. Shell_NotifyIcon(...) fails from a different location. It is even described in the sample's ReadMe:

Please note that notification icons specified with a GUID are protected against spoofing by validating that only a single application registers them. This registration is performed the first time you call Shell_NotifyIcon(NIM_ADD, ...), and the full pathname of the calling application is stored. If you later move your binary to a different location, the system will not allow the icon to be added again.

I tried to Shell_NotifyIcon(NIM_DELETE, ...) at the exit of my application, but it still doesn't work and my application can be started from a different locations. Ofc. I can hack it by changing guid everytime Shell_NotifyIcon(...) fails but I'd prefer to have less brute force method. Moreover I searched the system registry for the guid, couldn't find it.

The guid from the sample is defined like that:

// Use a guid to uniquely identify our icon
class __declspec(uuid("9D0B8B92-4E1C-488e-A1E1-2331AFCE2CB5")) PrinterIcon;

Code that creates the notification icon:

BOOL AddNotificationIcon(HWND hwnd)
{
    NOTIFYICONDATA nid = {sizeof(nid)};
    nid.hWnd = hwnd;
    // add the icon, setting the icon, tooltip, and callback message.
    // the icon will be identified with the GUID
    nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP | NIF_GUID;
    nid.guidItem = __uuidof(PrinterIcon);
    nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK;
    LoadIconMetric(g_hInst, MAKEINTRESOURCE(IDI_NOTIFICATIONICON), LIM_SMALL, &nid.hIcon);
    LoadString(g_hInst, IDS_TOOLTIP, nid.szTip, ARRAYSIZE(nid.szTip));
    Shell_NotifyIcon( NIM_ADD, &nid );

    // NOTIFYICON_VERSION_4 is prefered
    nid.uVersion = NOTIFYICON_VERSION_4;
    return Shell_NotifyIcon(NIM_SETVERSION, &nid);
}

The code is a part of Windows SDK Sample: SDKs/Windows/v7.1/Samples/winui/shell/appshellintegration/NotificationIcon

Upvotes: 3

Views: 1636

Answers (1)

LukeN
LukeN

Reputation: 142

So. The final solution is that I declare NOTIFYICONDATA like this:

#define NOTIFICATIONTRAY_UID 666;
[...]

NOTIFYICONDATA nid = { 0 };

nid.cbSize = sizeof( NOTIFYICONDATA );
nid.hWnd = hWnd;
nid.uID = NOTIFICATIONTRAY_UID;
nid.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_SHOWTIP;
nid.uCallbackMessage = WMAPP_NOTIFYCALLBACK;

LoadIconMetric( hInstance, MAKEINTRESOURCE( IDI_NOTIFICATIONICON ), LIM_SMALL, &nid.hIcon );
lstrcpy( nid.szTip, L"Tooltip text" );
Shell_NotifyIcon( NIM_ADD, &nid );

// NOTIFYICON_VERSION_4 is prefered
nid.uVersion = NOTIFYICON_VERSION_4;
return ( Shell_NotifyIcon( NIM_SETVERSION, &nid ) != 0 );

I don't set NIF_GUID flag and GUID. To use this icon later (destroy, add balloon notification etc.) I have to provide HWND and uID (thanks Remy Lebeau for the suggestion).

Upvotes: 1

Related Questions