代码之家  ›  专栏  ›  技术社区  ›  bur

ExtractIconEx:工作,但偶尔崩溃

  •  3
  • bur  · 技术社区  · 6 年前

    我从文件中提取图标并在对话框中显示它们

    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]);
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  4
  •   zett42    6 年前
    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()

        2
  •  2
  •   Lightness Races in Orbit    6 年前

    指向图标句柄数组的指针,该数组接收从文件中提取的大图标的句柄。如果此参数为NULL,则不会从文件中提取大图标。

    你只给了它一个指向 图标句柄。

    分配一个函数所期望的数组;从表面上看,这意味着 nIconsCheck