ExtractIconEx: работает, но иногда вылетает - PullRequest
0 голосов
/ 28 октября 2018

Я извлекаю значки из файла и отображаю их в диалоговом окне

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();
    }
}

Значки загружаются правильно в диалоговом окне, но иногда это непредсказуемо приводит к сбою приложения.

Есть идеи, что происходит?

Документация на 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 ]

0 голосов
/ 28 октября 2018

Из документации, на которую вы ссылаетесь:

Указатель на массив дескрипторов значков, который получает дескрипторы для больших значков, извлеченных из файла.Если этот параметр имеет значение NULL, из файла не извлекаются большие значки.

Вы указали ему только указатель на один дескриптор значка.

Выделите массивстолько, сколько ожидает функция;на первый взгляд, это означает nIconsCheck элементов.Вектор хорош для этого, как говорит zett42.

0 голосов
/ 28 октября 2018
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() для каждого дескриптора значка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...