带有图标处理程序外壳扩展名的文件图标模糊

时间:2019-07-10 09:24:09

标签: winapi shell-extensions

我有一个带图标处理程序的外壳扩展程序,该文件处理程序根据文件内容将文件类型的图标设置为绿色或红色图标。图标看起来可以正常工作,除了使用大图标时它们真的模糊之外,就好像它们是从很小的尺寸放大来的一样。图标.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 :(得分:0)

我从过去的documents看过这类信息。我不能保证现在这些信息都是准确的。

  

nIconSize

     

指示所需的图标大小。高词是   尺寸(高度和宽度,因为它们始终相同)   小图标的,而低位字则包含的尺寸   大图标。一般情况下,小图标尺寸为   16.大图标通常为32或48,具体取决于浏览器所处的视图模式-大图标模式为32,平铺模式为48。

似乎IExtract IconA:: Extract只能提取标准尺寸的图标。

另一方面,请参考Raymond Chen的old thing

  

如果您要求IExtract­Icon :: Extract在特定位置提取图标   大小,函数可以返回S_FALSE。   Extract­Icon­Ex函数不会让您   指定自定义尺寸,   并且Load­Image不适用于图标索引   (仅资源ID)。

因此,如果您需要提取自定义尺寸的图标(即系统“小”和“大”尺寸以外的图标),那么您需要做更多的工作。

调用SHGetImageList函数,这是另一个shell辅助函数,但是可以检索包含图标的shell图像列表。它为您提供了更多的图标大小选项: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;
}

更多详细信息,请参阅:

Difference between ExtractIcon and ExtractAssociatedIcon? Need to extract icon of specific size

Extract high resolution icon or thumbnail for file

已更新:

我偶然发现了这样的post,可能是通过指定宽度/高度来删除了LR_DEFAULTSIZE。另外,您必须在DestroyIcon之后调用DrawIconEx,否则会导致资源泄漏。要么在堆上创建HICON,以使其仅创建一次。