Значки файлов размыты при загрузке с расширением оболочки обработчика значков - PullRequest
0 голосов
/ 10 июля 2019

У меня есть расширение оболочки с обработчиком значков, которое устанавливает значки типа файла на зеленый или красный значок в зависимости от содержимого файла. Иконки, кажется, работают должным образом, за исключением того, что они очень размытые при использовании больших значков, как если бы они были увеличены от действительно небольшого размера. Файлы значков .ico содержат изображения всех размеров от 256x256 до 16x16.

Icons are blurry

Я использую очень простой обработчик значков, но, возможно, все еще могут быть проблемы с кэшированием или что-то в этом роде. Как я могу убедиться, что иконки загружены правильно?

HRESULT icon_handler::GetIconLocation(UINT u_flags, PWSTR psz_icon_file, UINT cch_max, int* pi_index, UINT* pw_flags)
{
    *pw_flags = GIL_NOTFILENAME | GIL_DONTCACHE;
    return S_OK;
}

HRESULT icon_handler::Extract(PCWSTR psz_file, UINT n_icon_index, HICON* phicon_large, HICON* phicon_small, UINT n_icon_size)
{
    int icon = ICON_GREEN;
    if (m_icon_color_ == 1) {
        icon = ICON_RED;
    }

    if (phicon_large != nullptr)
    {
        const int large_size = LOWORD(n_icon_size);
        *phicon_large = HICON(LoadImageW(global_h_instance, MAKEINTRESOURCE(icon), IMAGE_ICON, large_size, large_size, 
            LR_DEFAULTCOLOR));
    }
    if (phicon_small != nullptr)
    {
        const int small_size = HIWORD(n_icon_size);
        *phicon_small = HICON(LoadImageW(global_h_instance, MAKEINTRESOURCE(icon), IMAGE_ICON, small_size, small_size,
            LR_DEFAULTCOLOR));
    }

    return S_OK;
}

При входе в DebugView появляется обработчик значков для запроса соответствующих размеров:

[30100] phicon_large size:
[30100] 256
[30100] phicon_small size:
[30100] 16

Редактировать : Что касается @Anders, если я проверяю размер изображения, загруженного с LoadImage, это также кажется правильным:

*phicon_large = HICON(LoadImageW(global_h_instance, MAKEINTRESOURCE(icon), IMAGE_ICON, large_size, large_size, 
            LR_DEFAULTCOLOR));
ICONINFOEXW info = {sizeof(ICONINFOEXW)};
GetIconInfoEx(*phicon_large, &info)
BITMAP bmp;
GetObjectW(info.hbmMask, sizeof(BITMAP), &bmp);
OutputDebugStringW(L"Icon size:");
OutputDebugStringW(std::to_wstring(bmp.bmWidth).c_str());
[12376] phicon_large size:
[12376] 256
[12376] Icon size:
[12376] 256
[12376] phicon_small size:
[12376] 16
[12376] Icon size:
[12376] 16

1 Ответ

0 голосов
/ 11 июля 2019

Я видел такую ​​информацию из прошлых документов . Я не могу гарантировать, что эта информация точна сейчас.

nIconSize

Указываетжелаемые размеры иконок.Старшее слово - это размеры (как высота, так и ширина, поскольку они всегда одинаковы) маленькой иконки, а младшее слово содержит размеры большой иконки.При нормальных обстоятельствах размер маленького значка будет 16. Большой значок обычно будет 32 или 48, в зависимости от того, в каком режиме просмотра находится Explorer - 32 для режима больших значков, 48 для режима листов.

Похоже, что IExtract IconA:: Extract может извлекать значки только стандартных размеров.

С другой стороны, обратитесь к старой вещи Раймонда Чена ,

, если вы спроситеIExtractIcon :: Extract для извлечения значка определенного размера, функция может возвращать S_FALSE. Функции ExtractIcon и ExtractIconEx не позволяют указывать пользовательский размер, а LoadImage не работает с индексами значков (только идентификаторы ресурсов).

Поэтому, если вам нужно извлечь значки нестандартных размеров (то есть что-то отличное от «маленьких» и «больших» размеров системы) , то вам нужно будет сделатьбольше работы.

Вызовите функцию SHGetImageList , которая является другой вспомогательной функцией оболочки, но которая извлекает список изображений оболочки, содержащий значки.Это дает вам гораздо больше возможностей для размеров иконок: SHIL_SMALL (обычно 16x16), SHIL_LARGE (обычно 32x32), SHIL_EXTRALARGE (обычно 48x48) и SHIL_JUMBO (обычно 256x256 - только в Vista и более поздних версиях).Поэтому, если вы попросите SHIL_EXTRALARGE, вы получите нужные вам иконки 48x48.

Вам все равно понадобится функция SHGetFileInfo , но на этот раз она будетбыть, чтобы получить индекс нужного значка в списке изображений оболочки.Получите это с помощью опции SHGFI_SYSICONINDEX.

Полностью непроверенный пример кода, никогда не затрагиваемый компилятором:

HICON ExtractExtraLargeIcon(LPCTSTR pszPath)
{    
    // Determine the index of the desired icon
    // in the system image list.
    SHGETFILEINFO sfi;
    SHGetFileInfo(pszPath, 0, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX);

    // Retrieve the system image list.
    // (To get 256x256 icons, we use `SHIL_JUMBO`.)
    IImageList* piml;
    if (SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&piml) == S_OK)
    {
        HICON hIcon;
        if (piml->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon) == S_OK)
        {
           return hIcon;
        }
    }

    // Oops! We failed.
    return NULL;
}

Подробнее, пожалуйста, обратитесь:

Разница между ExtractIcon и ExtractAssociatedIcon?Необходимо извлечь значок определенного размера

Извлечь значок высокого разрешения или миниатюру для файла

Обновлено:

Я случайно нашел такой пост , вероятно, указав ширину / высоту, удалив LR_DEFAULTSIZE.Кроме того, вы должны позвонить DestroyIcon после DrawIconEx, иначе вы получите утечку ресурсов.Либо так, либо создайте HICON в куче, чтобы он создавался только один раз.

...