Discussion:
Xp and a systray balloontip icon problem - how to set one different from the systray icon.
(too old to reply)
R.Wieser
2017-09-20 10:55:54 UTC
Permalink
Hello all,

I've added a systray icon to a program of mine, and am now adding balloon
tips. With icons. With which I now have a problem.

The MSDN documentation to the NIIF_USER option states that the balloon tips
icon needs to be supplied in the 'hIcon' field (of the NOTIFYICON)
structure.

https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352%28v%3Dvs.85%29.aspx

But no matter what I try, I can, apart from the predefined ones, only get
the current icon already in the systray to display. Or change both the
systray and the balloon tips icon at the same time.

Has anyone an idea what goes wrong here / the docs have forgotten to mention
?

By the way, XPsp3

Regards,
Rudy Wieser
Christian Astor
2017-09-20 11:57:03 UTC
Permalink
I've added a systray icon to a program of mine, and am now adding balloon tips. With icons. With which I now have a problem.
//...
This works for me, but on Windows 10, not sure for XP (from the doc,
NOTIFYICON_VERSION_4 should be replaced by 0) =>

HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALL));
TrayMessage(hWnd, NULL, hIcon, NIM_ADD, NIIF_USER, L"Test Message",
L"Message", 10 * 1000);

BOOL TrayMessage(HWND hWnd, LPWSTR sMessage, HICON hIcon, DWORD
nMessage, DWORD dwInfoFlags, LPWSTR sInfo, LPWSTR sTitle, int nTimeOut)
{
NOTIFYICONDATA nid = { 0 };
DLLVERSIONINFO verInfo = { 0 };
typedef HRESULT(__stdcall *DllGetVersion) (DLLVERSIONINFO *pverInfo);
HMODULE hShell32 = LoadLibrary(L"Shell32.dll");
if (hShell32)
{
DllGetVersion pDllGetVersion = (DllGetVersion)GetProcAddress(hShell32,
"DllGetVersion");
verInfo.cbSize = sizeof(DLLVERSIONINFO);
pDllGetVersion(&verInfo);
FreeLibrary(hShell32);
}
if (verInfo.dwMajorVersion == 6 && verInfo.dwMinorVersion > 0)
nid.cbSize = sizeof(NOTIFYICONDATA);
else if (verInfo.dwMajorVersion >= 6)
nid.cbSize = NOTIFYICONDATA_V3_SIZE;
else if (verInfo.dwMajorVersion == 5)
nid.cbSize = NOTIFYICONDATA_V2_SIZE;
else
nid.cbSize = NOTIFYICONDATA_V1_SIZE;
nid.uID = 1;
nid.hWnd = hWnd;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
nid.uCallbackMessage = WM_TRAYNOTIFY;
if (lstrcmp(sMessage, L"") != 0 && NULL != sMessage)
wcsncpy(nid.szTip, sMessage, 128);
nid.hIcon = hIcon;
if (dwInfoFlags & NIIF_USER)
{
nid.hBalloonIcon = hIcon;
}
nid.dwInfoFlags = dwInfoFlags;
nid.uTimeout = nTimeOut;
if (dwInfoFlags != 0 && NULL != sInfo && NULL != sTitle)
{
wcsncpy(nid.szInfo, sInfo, 256);
wcsncpy(nid.szInfoTitle, sTitle, 64);
}
else
{
nid.szInfoTitle[0] = _TEXT('\0');
nid.szInfo[0] = _TEXT('\0');
}
BOOL bRet;
nid.uVersion = NOTIFYICON_VERSION_4;
if (nMessage == NIM_ADD)
Shell_NotifyIcon(NIM_SETVERSION, &nid);
bRet = Shell_NotifyIcon(nMessage, &nid);
return bRet;
}
R.Wieser
2017-09-20 12:06:19 UTC
Permalink
Christian,
This works for me, but on Windows 10 not sure for XP.
Alas, it wont. The XP version of the structure does not have 'hBalloonIcon'
field (I wish it would). That is what makes it "interresting" :-)

Regards,
Rudy Wieser
Post by R.Wieser
I've added a systray icon to a program of mine, and am now adding balloon
tips. With icons. With which I now have a problem.
//...
This works for me, but on Windows 10, not sure for XP (from the doc,
NOTIFYICON_VERSION_4 should be replaced by 0) =>
HICON hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_SMALL));
TrayMessage(hWnd, NULL, hIcon, NIM_ADD, NIIF_USER, L"Test Message",
L"Message", 10 * 1000);
BOOL TrayMessage(HWND hWnd, LPWSTR sMessage, HICON hIcon, DWORD nMessage,
DWORD dwInfoFlags, LPWSTR sInfo, LPWSTR sTitle, int nTimeOut)
{
NOTIFYICONDATA nid = { 0 };
DLLVERSIONINFO verInfo = { 0 };
typedef HRESULT(__stdcall *DllGetVersion) (DLLVERSIONINFO *pverInfo);
HMODULE hShell32 = LoadLibrary(L"Shell32.dll");
if (hShell32)
{
DllGetVersion pDllGetVersion = (DllGetVersion)GetProcAddress(hShell32,
"DllGetVersion");
verInfo.cbSize = sizeof(DLLVERSIONINFO);
pDllGetVersion(&verInfo);
FreeLibrary(hShell32);
}
if (verInfo.dwMajorVersion == 6 && verInfo.dwMinorVersion > 0)
nid.cbSize = sizeof(NOTIFYICONDATA);
else if (verInfo.dwMajorVersion >= 6)
nid.cbSize = NOTIFYICONDATA_V3_SIZE;
else if (verInfo.dwMajorVersion == 5)
nid.cbSize = NOTIFYICONDATA_V2_SIZE;
else
nid.cbSize = NOTIFYICONDATA_V1_SIZE;
nid.uID = 1;
nid.hWnd = hWnd;
nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_INFO;
nid.uCallbackMessage = WM_TRAYNOTIFY;
if (lstrcmp(sMessage, L"") != 0 && NULL != sMessage)
wcsncpy(nid.szTip, sMessage, 128);
nid.hIcon = hIcon;
if (dwInfoFlags & NIIF_USER)
{
nid.hBalloonIcon = hIcon;
}
nid.dwInfoFlags = dwInfoFlags;
nid.uTimeout = nTimeOut;
if (dwInfoFlags != 0 && NULL != sInfo && NULL != sTitle)
{
wcsncpy(nid.szInfo, sInfo, 256);
wcsncpy(nid.szInfoTitle, sTitle, 64);
}
else
{
nid.szInfoTitle[0] = _TEXT('\0');
nid.szInfo[0] = _TEXT('\0');
}
BOOL bRet;
nid.uVersion = NOTIFYICON_VERSION_4;
if (nMessage == NIM_ADD)
Shell_NotifyIcon(NIM_SETVERSION, &nid);
bRet = Shell_NotifyIcon(nMessage, &nid);
return bRet;
}
Kaz Kylheku
2017-09-20 18:33:38 UTC
Permalink
Post by R.Wieser
Hello all,
I've added a systray icon to a program of mine, and am now adding balloon
tips. With icons. With which I now have a problem.
The MSDN documentation to the NIIF_USER option states that the balloon tips
icon needs to be supplied in the 'hIcon' field (of the NOTIFYICON)
structure.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352%28v%3Dvs.85%29.aspx
But no matter what I try, I can, apart from the predefined ones, only get
the current icon already in the systray to display. Or change both the
systray and the balloon tips icon at the same time.
Has anyone an idea what goes wrong here / the docs have forgotten to mention
?
The tray stuff has been changing quite a bit. I'm guessing the problem
is this, right from the above documentation page:

NIIF_USER (0x00000004)

0x00000004. Windows XP SP2 and later.

Windows XP: Use the icon identified in hIcon as the
notification balloon's title icon.

Windows Vista and later: Use the icon identified in
hBalloonIcon as the notification balloon's title
icon.

I suspect that this hBalloonIcon structure member might have not
actually existed in XP and was added later (note: at the end of the
structure) in order to support the separtion of the balloon icon and
notification area icon.

That is to say, if you could set the icons separately using just
hIcon, why would they have added hBalloonIcon ... right?

This seems to be further corroborated by this:

hBalloonIcon

Type: HICON

Windows Vista and later. The handle of a customized notification
icon provided by the application that should be used
independently of the notification area icon. If this member is
non-NULL and the NIIF_USER flag is set in the dwInfoFlags
member, this icon is used as the notification icon. If this
member is NULL, the legacy behavior is carried out.


"legacy behavior" here almost certainly refers to: "same damn icon".
R.Wieser
2017-09-21 07:54:27 UTC
Permalink
Kaz,
Post by Kaz Kylheku
The tray stuff has been changing quite a bit. I'm guessing the problem
NIIF_USER (0x00000004)
0x00000004. Windows XP SP2 and later.
Windows XP: Use the icon identified in hIcon as the
notification balloon's title icon.
I fail to see the problem: Set NIIF_USER, put the balloon icon into the
hIcon field, and all should be well. Yes ?

Well, no. And I have no idea why. Do you ? :-)
Post by Kaz Kylheku
I suspect that this hBalloonIcon structure member might \
have not actually existed in XP and was added later
Correct. Into version 6 of the structure.
Post by Kaz Kylheku
"legacy behavior" here almost certainly refers to: "same damn icon".
That is what currently happens, yes. The problem is that the description of
that NIIF_USER setting seems to suggest something else (and makes no
explicit nor vague mentioning of that "legacy behaviour"). Hence my
question: did I miss anything ? Is there maybe some secret handshake
involved I'm not (yet) privy of ? Anything else I could have forgotten ?

Or maybe a better question: Has anyone ever put up a balloon tip with its
own icon, and "how done they dune it" -- other than the "change both the the
balloon and systray icon, and than change the systray icon back" hack I
mean.

Regards,
Rudy Wieser
Post by Kaz Kylheku
Post by R.Wieser
Hello all,
I've added a systray icon to a program of mine, and am now adding balloon
tips. With icons. With which I now have a problem.
The MSDN documentation to the NIIF_USER option states that the balloon tips
icon needs to be supplied in the 'hIcon' field (of the NOTIFYICON)
structure.
https://msdn.microsoft.com/en-us/library/windows/desktop/bb773352%28v%3Dvs.85%29.aspx
But no matter what I try, I can, apart from the predefined ones, only get
the current icon already in the systray to display. Or change both the
systray and the balloon tips icon at the same time.
Has anyone an idea what goes wrong here / the docs have forgotten to mention
?
The tray stuff has been changing quite a bit. I'm guessing the problem
NIIF_USER (0x00000004)
0x00000004. Windows XP SP2 and later.
Windows XP: Use the icon identified in hIcon as the
notification balloon's title icon.
Windows Vista and later: Use the icon identified in
hBalloonIcon as the notification balloon's title
icon.
I suspect that this hBalloonIcon structure member might have not
actually existed in XP and was added later (note: at the end of the
structure) in order to support the separtion of the balloon icon and
notification area icon.
That is to say, if you could set the icons separately using just
hIcon, why would they have added hBalloonIcon ... right?
hBalloonIcon
Type: HICON
Windows Vista and later. The handle of a customized notification
icon provided by the application that should be used
independently of the notification area icon. If this member is
non-NULL and the NIIF_USER flag is set in the dwInfoFlags
member, this icon is used as the notification icon. If this
member is NULL, the legacy behavior is carried out.
"legacy behavior" here almost certainly refers to: "same damn icon".
JJ
2017-09-21 21:37:24 UTC
Permalink
Post by R.Wieser
Hence my
question: did I miss anything ? Is there maybe some secret handshake
involved I'm not (yet) privy of ? Anything else I could have forgotten ?
I don't think you miss anything. I think MSDN left out one important
information (like they usually do) that in Windows XP, ballon tip can have a
custom icon, but it fails to mention that it must be the same as the one
displayed on the system tray (with the same tray ID).

Take a look at Security Center's baloon tip.

<Loading Image...>

You can see that the balloon tip shows the application icon while displaying
a message relating to antivirus. If balloon tip can actually have different
icon than its tray icon, why didn't Security Center use the relevant icon as
displayed on each section header in its Window? i.e. Firewall, Automatic
Updates, or Virus Protection.

I doubt any application in Windows XP can show a different balloon tip icon
than the one for the system tray using only Shell_NotifyIcon(). I haven't
seen one, at least.

The only way I could think of is to create a separate balloon tip manually.
This is probably the reason why some third party applications choose to roll
their own balloon-style notification windows.
Kaz Kylheku
2017-09-21 22:08:33 UTC
Permalink
Post by JJ
Post by R.Wieser
Hence my
question: did I miss anything ? Is there maybe some secret handshake
involved I'm not (yet) privy of ? Anything else I could have forgotten ?
I don't think you miss anything. I think MSDN left out one important
information (like they usually do) that in Windows XP, ballon tip can have a
custom icon, but it fails to mention that it must be the same as the one
displayed on the system tray (with the same tray ID).
It's not "in-your-face crystal clear" from the MSDN documentation, but
fairly clear.

The structure has a separate member for specifying the separate balloon icon
handle.

The documentation does state that this is Vista or later!

So in Windows versions before Vista, you don't get separate icons.

Before Vista, that struct member wasn't there. A program compiled
for XP would specify a dwSize for the structure which doesn't include
that member, and so newer Windows would know that it isn't there,
(and that it shouldn't even access the memory at all).

They also say that if you set that baloon icon handle to NULL you get
legacy behavior. Almost certainly, this is the same behavior as if the
member isn't there at all, as indicated by dwSize.

What this does is help forward-port programs that are recompiled.

Programs which zero-fill structures will automatically fill any new
struct members that they don't know about with zero.

A program written for XP which which zeroes out that structure,
when it is recompiled with newer platform headers that support Vista or
later, will automatically null out that ballon icon handle.

So if a null value of the handle means "legacy behavior" then exactly
the right thing happens; the program behaves the same as it
did on XP.
R.Wieser
2017-09-22 07:34:16 UTC
Permalink
Kaz,
Post by Kaz Kylheku
The structure has a separate member for specifying the separate balloon icon
handle.
No, it does not. That page describes *multiple forms* of that structure,
from ... unknown (win95 ?) upto Win10, and the XP version of it does not
seem to carry that field.
Post by Kaz Kylheku
The documentation does state that this is Vista or later!
So in Windows versions before Vista, you don't get separate icons.
Lol ? No, that is not a conclusion you can draw from it. Just read the
documentation to the NIIF_USER setting:

"Windows XP: Use the icon identified in hIcon as the notification balloon's
title icon." *

I don't know about you, but that does seem to quite firmly state that thats
the way it should work for XPsp3 too (as the next line mentions Windows
Vista, which I assume is than the upper limit).

So no, I cannot say I can agree with conclusion, sorry.

* I must say that although I read that I should set the NIF_ICON flag when
using that hIcon field, I concluded that that is only needed when specifying
the systray icon, and the NIIF_USER setting would have the same function in
regard to the balloon-tip one. Alas, I seem to have been wrong in that
regard.

Odd though: There is nothing described about what should happen when you
specify a NIIF_USER balloon-tip icon, but not set the hIcon field-and-flag
...

But as JJ already mentioned, MS sometimes seem to be a bit ... forgetfull.

Regards,
Rudy Wieser
Post by Kaz Kylheku
Post by JJ
Post by R.Wieser
Hence my
question: did I miss anything ? Is there maybe some secret handshake
involved I'm not (yet) privy of ? Anything else I could have forgotten ?
I don't think you miss anything. I think MSDN left out one important
information (like they usually do) that in Windows XP, ballon tip can have a
custom icon, but it fails to mention that it must be the same as the one
displayed on the system tray (with the same tray ID).
It's not "in-your-face crystal clear" from the MSDN documentation, but
fairly clear.
The structure has a separate member for specifying the separate balloon icon
handle.
The documentation does state that this is Vista or later!
So in Windows versions before Vista, you don't get separate icons.
Before Vista, that struct member wasn't there. A program compiled
for XP would specify a dwSize for the structure which doesn't include
that member, and so newer Windows would know that it isn't there,
(and that it shouldn't even access the memory at all).
They also say that if you set that baloon icon handle to NULL you get
legacy behavior. Almost certainly, this is the same behavior as if the
member isn't there at all, as indicated by dwSize.
What this does is help forward-port programs that are recompiled.
Programs which zero-fill structures will automatically fill any new
struct members that they don't know about with zero.
A program written for XP which which zeroes out that structure,
when it is recompiled with newer platform headers that support Vista or
later, will automatically null out that ballon icon handle.
So if a null value of the handle means "legacy behavior" then exactly
the right thing happens; the program behaves the same as it
did on XP.
R.Wieser
2017-09-22 07:03:57 UTC
Permalink
JJ,
I think MSDN left out one important information (like they usually do)
that in Windows XP, ballon tip can have a custom icon, but it fails to
mention that it must be the same as the one displayed on the system tray
(with the same tray ID).
The problem with that is that both you and I have to do with some empirical
testing, and drawing conclusions from that. It just might be that there is
some other thing that also needs to be done to get the function to behave as
described, but that *that* was forgotten -- or hidden away/obscured for
someone not knowing what to look at ...
Take a look at Security Center's baloon tip.
Thanks for the screenshot. I have to say that I think it looks good there,
with both the systray and the balloon showing the same icon. And as the
saying goes, the absense of proof is not the same as proof of absense. But,
as you say it, it might be an indication..
The only way I could think of is to create a separate balloon tip manually.
Than you now know two ways (with the other, much easier one, being the
"change both, than change the systray back" kludge). :-)

Thanks for the heads-up.

Regards,
Rudy Wieser
Post by R.Wieser
Hence my
question: did I miss anything ? Is there maybe some secret handshake
involved I'm not (yet) privy of ? Anything else I could have forgotten ?
I don't think you miss anything. I think MSDN left out one important
information (like they usually do) that in Windows XP, ballon tip can have a
custom icon, but it fails to mention that it must be the same as the one
displayed on the system tray (with the same tray ID).
Take a look at Security Center's baloon tip.
<https://i.imgur.com/GZSipZk.png>
You can see that the balloon tip shows the application icon while displaying
a message relating to antivirus. If balloon tip can actually have different
icon than its tray icon, why didn't Security Center use the relevant icon as
displayed on each section header in its Window? i.e. Firewall, Automatic
Updates, or Virus Protection.
I doubt any application in Windows XP can show a different balloon tip icon
than the one for the system tray using only Shell_NotifyIcon(). I haven't
seen one, at least.
The only way I could think of is to create a separate balloon tip manually.
This is probably the reason why some third party applications choose to roll
their own balloon-style notification windows.
Loading...