Mik*_*ron 4 winapi mfc visual-studio-2008 visual-c++
我遇到过一种我知道代码的情况
我在Visual Studio 2008中创建了一个MFC应用程序,它生成一个托盘图标和一些通知.我已经阅读过,我可以使用与NOTIFYICONDATA
Windows XP 不同的结构,通过设置cbSize
结构的属性来初始化它.我还读过,我可以LoadIconMetric
在Windows Vista中使用加载我的通知图标,而在Windows XP中,我无法使用该功能,我必须使用LoadIcon
.
在我的应用程序中,我设置了以下内容:
#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
Run Code Online (Sandbox Code Playgroud)
我正在Visual Studio 2008中的Windows 7 x64计算机上编译和链接Windows 7 SDK.我对WindowsVista或更高版本的测试看起来像这样(直接来自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);
}
Run Code Online (Sandbox Code Playgroud)
现在这是有趣的部分.我使用IsWinVistaOrLater来确定是否应该使用LoadIconMetric或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
}
Run Code Online (Sandbox Code Playgroud)
在XP上崩溃与"在ComCtrl32.dll中找不到Ordinal 380".如果我对这个电话进行评论,那么LoadIconMetric
事情就会很开心(即使将所有目标版本设置为Vista).无论运行时代码路径如何,Windows都会尝试导入所有函数调用吗?
小智 10
只是为了帮助那些可能遇到非常类似问题的人.即使在使用Visual Studio C++ 2010 Express WinApi模板应用程序的Windows 7下,我也无法使用LoadIconMetric.将Comctl32.lib添加到dependecies并包括CommCtrl.h之后,它继续说"在ComCtrl32.dll中找不到Ordinal 380".我不太清楚我错过了什么,因为我完全不熟悉这些组件的切换版本.经过相当长的一段时间后,我发现了这一点,这里是这种情况的宝贵来源:
我通过在包含CommCtrl.h之前添加此行来解决了这个问题(请注意,我的应用程序仅针对Windows Vista及更高版本):
// 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='*'\"")
Run Code Online (Sandbox Code Playgroud)
它源自Microsoft示例项目:
如果您为Vista设置了头文件,那么它将允许您构建无法在早期版本的Windows上加载的应用程序.这就是为什么正确设置该文件非常重要的原因.
要解决您的问题:
应该可以在comctl32.dll上使用/ DELAYLOAD开关.没有/ DELAYLOAD Windows将尝试预先导入所有功能(无论代码路径如何)
将目标版本头文件重置为0x0501(XP).如果您尝试使用任何高级功能,Windows现在会自动发出警告.使用LoadLibrary("comctl32.dll")&& GetProcAddress("LoadIconMetric")访问新功能.这种方法的缺点是你可以通过GetProcAddress进行新的调用,但结构(如果它们已经改变)将是旧的结构.
最后,很多comctl32.dll功能都是一个技巧:除非您具有特定的启用视觉样式,否则您的comctl32.dll版本应该始终是版本5版本.(如果在VS2005或VS2008中创建了MFC项目,则应该已自动完成).这意味着可以将WINVER设置为Vista,但随后ComCtl32调用开始失败,因为版本5 ComCtl32无法理解新的更大的结构.
您可以编写一个仅适用于Vista 的延迟加载链接 DLL,其中包含所有仅适用于 Vista 的代码,而您的主项目仍以 XP 为目标,而不是 Chris 所建议的LoadLibrary
。GetProcAddress
然后,您不需要加载仅 Vista 的代码,除非执行通过了 Vista 版本检查并调用从 Vista 代码 DLL 导出的函数。
归档时间: |
|
查看次数: |
1422 次 |
最近记录: |