I've come across a situation where I know a code
I've created an MFC app in Visual Studio 2008 that generates a Tray Icon and some notifications. I've read I can use a different NOTIFYICONDATA
structure for Windows Vista than for Windows XP by setting the cbSize
property of the structure to initialize it. I've also read that I can use LoadIconMetric
in Windows Vista to load my icon for the notification, whereas in Windows XP, that function is not available to me and I must use LoadIcon
.
In my application, I've set the following:
#ifndef WINVER
#define WINVER 0x0600 // Vista
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600 // Vista
#end#if
#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0600 // Vista
#endif
#ifndef _WIN32_IE
#define _WIN32_IE 0x0700
#endif
I'm compiling and linking against the Windows 7 SDK on a Windows 7 x64 machine in Visual Studio 2008. My test for WindowsVista or greater looks like this (straight out of MSDN):
static BOOL IsWinVistaOrLater()
{
// Initialize the OSVERSIONINFOEX structure.
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osvi.dwMajorVersion = 6;
osvi.dwMinorVersion = 1;
// Initialize the condition mask.
DWORDLONG dwlConditionMask = 0;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
// Perform the test.
return VerifyVersionInfo(&osvi,
VER_MAJORVERSION | VER_MINORVERSION,
dwlConditionMask);
}
Now here's the interesting part. I use IsWinVistaOrLater to determine if I should use LoadIconMetric or LoadIcon:
if (IsWinVistaOrLater())
{
tnd_Happy.dwInfoFlags = NIIF_LARGE_ICON | tnd_Happy.dwInfoFlags;
LoadIconMetric(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON_HAPPY), LIM_SMALL, &(tnd_Happy.hIcon));
} else {
tnd_Happy.hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE (IDI_ICON_HAPPY)); // ICON RESOURCE ID
}
On XP this crashes with "Ordinal 380 not found in ComCtrl32.dll". If I comment out the call to LoadIconMetric
, things are happy (even with all those target vers set to Vista). Does Windows try to import all the function calls regardless of runtime code path?
Just to help others who may run into very similar problem. I could not get LoadIconMetric working even under Windows 7 with Visual Studio C++ 2010 Express WinApi template application. After adding Comctl32.lib to dependecies and including CommCtrl.h it keep saying "Ordinal 380 not found in ComCtrl32.dll". It was not very clear to me what I missed because I was completely unfamiliar with switching versions of such components. After quite some time I figure that out and here are valuable sources for such situation:
Common Control Versions
I solved the problem by adding this line before inclusion of CommCtrl.h (Note that my application only targeting Windows Vista and above):
// Need CommCtrl v6 for LoadIconMetric()
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
It's originated from Microsoft sample project:
Notification Icon Sample - NotificationIcon.zip
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With