Reputation: 142
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
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