积极答复者
VC获取文件超大图标 256x256

问题
-
#include <shlobj.h> #include <shlguid.h> #include <shellapi.h> #include <commctrl.h> #include <commoncontrols.h> // Get the icon index using SHGetFileInfo SHFILEINFOW sfi = { 0 }; SHGetFileInfo(filePath, -1, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX); // Retrieve the system image list. // To get the 48x48 icons, use SHIL_EXTRALARGE // To get the 256x256 icons (Vista only), use SHIL_JUMBO HIMAGELIST* imageList; HRESULT hResult = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&imageList); if (hResult == S_OK) { // Get the icon we need from the list. Note that the HIMAGELIST we retrieved // earlier needs to be casted to the IImageList interface before use. HICON hIcon; hResult = ((IImageList*)imageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon); if (hResult == S_OK) { // Do something with the icon here. } }
HRESULT hResult = SHGetImageList(SHIL_JUMBO, IID_IImageList, (void**)&imageList);
上面是网上获取256图标的一个方法。将SHIL_EXTRALARGE改成SHIL_JUMBO即可。
该方法好处是提交任何文件都可以。自动寻找关联的图标。
但是如果文件没有256大小的图标,返回的是一个256x256的图像,但是图标部分会缩在左上角。比如256x256文件的左上角有一个48x48的图像,其余空白。
-------
求解:
1、有没有办法修正缩在左上角的图像,将其居中并变回原有大小呢?或者直接放大到256x256?
2、有没有办法在SHGetImageList前,判断文件拥有的图标大小?比如有没有256大小图标呢?这样就可以用其他flag了,比如SHIL_EXTRALARGE。
3、PrivateExtractIcons这个API似乎能很好地工作,即使没有256大小的也会将48或32的放大到256,但是必须是exe、dll等文件。
原本觉得可以配合SHGetFileInfo,用SHGFI_ICONLOCATION来获取图标的位置,可是这个flag似乎不能工作?
---------
4、如果上面的都不能解决,打算用读取注册表的方法配合PrivateExtractIcons。
根据我查找的资料,比如.bat,是在HKEY_CLASSES_ROOT找到.bat,然后获取名称是batfile。在寻找HKEY_CLASSES_ROOT\batfile\DefaultIcon下找到图标文件位置。
——可是有些文件,比如.sln,扩展名上的名称是VisualStudio.Launcher.sln,可是该项没有DefaultIcon,而是在VisualStudio.Launcher._sln下……
——还有似乎DefaultIcon只是默认的图标,而不一定是文件当前显示的图标(若有第三方软件改过关联)
到底注册表中关联图标是怎么一个规则呢??
————谢谢各位~
答案
-
找到解决办法了!判断一下49-256像素是不是都是空白就行……
这里我用的是GDI+,代码大概如下……
bool IsIconOnly48(Bitmap* bmp) { bool is48 = true; Color color, checkColor(255, 0, 0, 0); for (int x = 49; x != 256; ++x) { for (int y = 49; y != 256; ++y) { bmp->GetPixel(x, y, &color); if (color.GetValue() != checkColor.GetValue()) { is48 = false; break; } } if (is48 == false) { break; } } return is48; } void GetIcon() { //……省略 //获取JUMBO后 HICON hIcon; hResult = ((IImageList*)imageList)->GetIcon(SHFI.iIcon, ILD_TRANSPARENT, &hIcon); if (hResult == S_OK) { ICONINFO ii = { 0 }; GetIconInfo(hIcon, &ii); Bitmap bmpIcon(ii.hbmColor, NULL);//GDI+ if (IsIconOnly48(&bmpIcon)) { hResult = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&imageList); //获得48X48 } } }
- 已标记为答案 raiwhiz 2014年4月19日 14:05
全部回复
-
找到解决办法了!判断一下49-256像素是不是都是空白就行……
这里我用的是GDI+,代码大概如下……
bool IsIconOnly48(Bitmap* bmp) { bool is48 = true; Color color, checkColor(255, 0, 0, 0); for (int x = 49; x != 256; ++x) { for (int y = 49; y != 256; ++y) { bmp->GetPixel(x, y, &color); if (color.GetValue() != checkColor.GetValue()) { is48 = false; break; } } if (is48 == false) { break; } } return is48; } void GetIcon() { //……省略 //获取JUMBO后 HICON hIcon; hResult = ((IImageList*)imageList)->GetIcon(SHFI.iIcon, ILD_TRANSPARENT, &hIcon); if (hResult == S_OK) { ICONINFO ii = { 0 }; GetIconInfo(hIcon, &ii); Bitmap bmpIcon(ii.hbmColor, NULL);//GDI+ if (IsIconOnly48(&bmpIcon)) { hResult = SHGetImageList(SHIL_EXTRALARGE, IID_IImageList, (void**)&imageList); //获得48X48 } } }
- 已标记为答案 raiwhiz 2014年4月19日 14:05