ExtractIconEx:有效但偶尔会崩溃
ExtractIconEx: works but occasionally crashes
我正在从文件中提取图标并在对话框中显示它们
const LPCWSTR path = L"c:\path\to\file";
const UINT nIconsCheck = ExtractIconEx(path, -1, nullptr, nullptr, 0);
if(nIconsCheck > 0)
{
HICON *iconHandles=new HICON;
const UINT nIcons = ExtractIconEx(path, 0, iconHandles, nullptr, nIconsCheck);
if(nIcons == nIconsCheck && nIcons != unsigned(-1))
{
IconSelect iconSelect(this); //dialog
for(UINT i=0; i<nIcons; i++)
{
qDebug() << i;
iconSelect.addIcon(QtWin::fromHICON(iconHandles[i])); //fromHICON returns QPixmap
DestroyIcon(iconHandles[i]);
}
iconSelect.exec();
}
}
图标在对话框中正确加载,但有时会意外导致应用程序崩溃。
知道发生了什么吗?
Documentation on ExtractIconEx
编辑:感谢您快速而有用的回答。以下是我使用 atm 的完整工作代码:
// In my case I have a QString `filePath`
// `QString::toWCharArray` retrieves a non-0-terminated string,
// so append a 0 to `path`
std::vector<WCHAR> path(unsigned(filePath.length())+1);
filePath.toWCharArray(path.data());
path.at(path.size()-1) = 0;
// Get number of icons in selected file
UINT nIcons = ExtractIconEx(path.data(), -1, nullptr, nullptr, 0);
if(nIcons == 0)
{
// Try to find associated file that contains icon(s)
// If found, `path` is replaced with the new path
WORD index=0;
DestroyIcon(ExtractAssociatedIcon(GetModuleHandle(nullptr), path.data(), &index));
// Get number of icons in associated file
nIcons = ExtractIconEx(path.data(), -1, nullptr, nullptr, 0);
}
if(nIcons > 0)
{
// Get array of HICONs
std::vector<HICON> iconHandles(nIcons);
nIcons = ExtractIconEx(path.data(), 0, iconHandles.data(), nullptr, nIcons);
for(UINT i=0; i<nIcons; i++) // Using iconHandles.size() is possibly safer,
// but AFAIK nIcons always carries the correct value
{
// Use iconHandles[i]
// In Qt you can use QtWin::fromHICON(iconHandles[i]) to generate a QPixmap
DestroyIcon(iconHandles[i]);
}
}
HICON *iconHandles=new HICON;
这里您只分配了一个 HICON
对象。如果给定文件中有多个图标,则对 ExtractIconEx()
的下一次调用会通过写入分配的内存来创建缓冲区溢出。您已进入未定义行为的黑暗世界。
要解决此问题,您可以使用这样的 std::vector
:
std::vector<HICON> iconHandles(nIconsCheck);
const UINT nIcons = ExtractIconEx(path, 0, iconHandles.data(), nullptr, iconHandles.size());
iconHandles.resize(nIcons); // Resize to the actual number of icons.
// Instead of: if(nIcons == nIconsCheck && nIcons != unsigned(-1))
if(!iconHandles.empty())
{
// Use icons
}
这比手动分配有优势,您不需要 delete
分配的内存。 vector
析构函数将在范围结束时自动执行此操作。尽管您仍然需要为每个图标句柄调用 DestroyIcon()
。
来自您链接到的文档:
Pointer to an array of icon handles that receives handles to the large icons extracted from the file. If this parameter is NULL, no large icons are extracted from the file.
你只给它一个指向一个图标句柄的指针。
分配一个与函数预期一样大的数组;从外观上看,这意味着 nIconsCheck
个元素。正如 zett42 所说,矢量对此很有用。
我正在从文件中提取图标并在对话框中显示它们
const LPCWSTR path = L"c:\path\to\file";
const UINT nIconsCheck = ExtractIconEx(path, -1, nullptr, nullptr, 0);
if(nIconsCheck > 0)
{
HICON *iconHandles=new HICON;
const UINT nIcons = ExtractIconEx(path, 0, iconHandles, nullptr, nIconsCheck);
if(nIcons == nIconsCheck && nIcons != unsigned(-1))
{
IconSelect iconSelect(this); //dialog
for(UINT i=0; i<nIcons; i++)
{
qDebug() << i;
iconSelect.addIcon(QtWin::fromHICON(iconHandles[i])); //fromHICON returns QPixmap
DestroyIcon(iconHandles[i]);
}
iconSelect.exec();
}
}
图标在对话框中正确加载,但有时会意外导致应用程序崩溃。
知道发生了什么吗?
Documentation on ExtractIconEx
编辑:感谢您快速而有用的回答。以下是我使用 atm 的完整工作代码:
// In my case I have a QString `filePath`
// `QString::toWCharArray` retrieves a non-0-terminated string,
// so append a 0 to `path`
std::vector<WCHAR> path(unsigned(filePath.length())+1);
filePath.toWCharArray(path.data());
path.at(path.size()-1) = 0;
// Get number of icons in selected file
UINT nIcons = ExtractIconEx(path.data(), -1, nullptr, nullptr, 0);
if(nIcons == 0)
{
// Try to find associated file that contains icon(s)
// If found, `path` is replaced with the new path
WORD index=0;
DestroyIcon(ExtractAssociatedIcon(GetModuleHandle(nullptr), path.data(), &index));
// Get number of icons in associated file
nIcons = ExtractIconEx(path.data(), -1, nullptr, nullptr, 0);
}
if(nIcons > 0)
{
// Get array of HICONs
std::vector<HICON> iconHandles(nIcons);
nIcons = ExtractIconEx(path.data(), 0, iconHandles.data(), nullptr, nIcons);
for(UINT i=0; i<nIcons; i++) // Using iconHandles.size() is possibly safer,
// but AFAIK nIcons always carries the correct value
{
// Use iconHandles[i]
// In Qt you can use QtWin::fromHICON(iconHandles[i]) to generate a QPixmap
DestroyIcon(iconHandles[i]);
}
}
HICON *iconHandles=new HICON;
这里您只分配了一个 HICON
对象。如果给定文件中有多个图标,则对 ExtractIconEx()
的下一次调用会通过写入分配的内存来创建缓冲区溢出。您已进入未定义行为的黑暗世界。
要解决此问题,您可以使用这样的 std::vector
:
std::vector<HICON> iconHandles(nIconsCheck);
const UINT nIcons = ExtractIconEx(path, 0, iconHandles.data(), nullptr, iconHandles.size());
iconHandles.resize(nIcons); // Resize to the actual number of icons.
// Instead of: if(nIcons == nIconsCheck && nIcons != unsigned(-1))
if(!iconHandles.empty())
{
// Use icons
}
这比手动分配有优势,您不需要 delete
分配的内存。 vector
析构函数将在范围结束时自动执行此操作。尽管您仍然需要为每个图标句柄调用 DestroyIcon()
。
来自您链接到的文档:
Pointer to an array of icon handles that receives handles to the large icons extracted from the file. If this parameter is NULL, no large icons are extracted from the file.
你只给它一个指向一个图标句柄的指针。
分配一个与函数预期一样大的数组;从外观上看,这意味着 nIconsCheck
个元素。正如 zett42 所说,矢量对此很有用。