我正在尝试使用SHGetFileInfo
来获取文件和文件夹的图标。我注意到它在一种情况下不起作用:我的用户配置文件夹中的OneDrive文件夹。在这种情况下,对SHGetFileInfo的调用成功,但我得到了可执行文件的默认图标:
以下是我如何调用该函数:
HIMAGELIST imageList;
SHFILEINFO shfi;
// Get the path to the OneDrive folder
LPTSTR src = _T("%USERPROFILE%\\OneDrive");
TCHAR dest[MAX_PATH];
ExpandEnvironmentStrings(src, dest, MAX_PATH);
// Load the image from the OneDrive folder
ZeroMemory(&shfi, sizeof(shfi));
imageList = (HIMAGELIST)SHGetFileInfo(
dest,
FILE_ATTRIBUTE_NORMAL,
&shfi,
sizeof(shfi),
SHGFI_ICON | SHGFI_SYSICONINDEX);
以下是我绘制图标的方式:
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
ImageList_Draw(imageList, shfi.iIcon, hdc, 0, 0, ILD_NORMAL);
EndPaint(hwnd, &ps);
}
break;
我在pastebin上为应用做了一个简短的自包含示例:http://pastebin.com/bdTvEQT5
在这个简短的自包含示例中,为简洁起见省略了任何错误检查代码。此外,出于示例的目的,我已经对文件夹的位置进行了硬编码。在我的真实应用程序中,我在枚举文件系统中的文件夹,这就是我如何获取OneDrive文件夹的位置。图标提取代码需要使用枚举的任何文件夹。
我做错了什么?
答案 0 :(得分:0)
您的代码在Windows 10(15031)上适用于我。您永远不会使用shfi.hIcon
,因此您不需要SHGFI_ICON
,但它不会阻止它在我的情况下工作,但您正在泄漏图标。
%USERPROFILE%\OneDrive
可能不是OneDrive文件夹的位置。当有可以告诉你路径的shell函数时,永远不要使用环境变量!
您不能假设首先存在OneDrive文件夹。如果未使用OneDrive,则Windows 8.1上不存在该文件夹,因此您应该处理来自SHGetFileInfo
的失败!
我建议您将代码更改为以下内容:
PIDLIST_ABSOLUTE pidl;
HRESULT hr = SHGetKnownFolderIDList(FOLDERID_SkyDrive, 0, NULL, &pidl); // Note: Change the flags if you want to create the folder if it does not exist
if (SUCCEEDED(hr))
{
imageList = (HIMAGELIST) SHGetFileInfo((LPTSTR) pidl, 0, &shfi, sizeof(shfi), SHGFI_PIDL | SHGFI_SYSICONINDEX);
ILFree(pidl);
}
if (!imageList)
{
// Fall back to a plain folder icon
imageList = (HIMAGELIST) SHGetFileInfo(TEXT("DoesNotMatter"), FILE_ATTRIBUTE_DIRECTORY, &shfi, sizeof(shfi), SHGFI_USEFILEATTRIBUTES | SHGFI_SYSICONINDEX);
}
我无法解释您所看到的结果,缺乏错误检查肯定无济于事。我猜这是其中之一:
CoInitialize
之前,您没有致电OleInitialize
/ SHGetFileInfo
。 MSDN确实说你必须这样,但它似乎不太可能返回正确的图像列表但是错误的图标索引。