我的译作《系统图像列表》中提到过这么一句:永远不要修改或删除系统图像列表,这是由于系统图像列表是被 Shell 维护的,Shell 除了维护图像本身之外,还会维护一些有关缓存和哈希的信息以供快速存取。因此,如果直接通过 ImageList_* 相关函数贸然进行修改的话,将会导致不可预知的错误。
但是,我的确遇到了需要向这个列表中添加图标的情况,那么该怎么办呢?我固然可以对 Shell 中所维护的缓存进行直接操作,不过这样做的隐患很多,兼容性没有任何的保证。所以,我还是希望能有个更加通用的办法。在查阅了 MSDN 文档之后,我将目光聚焦在如下的函数上:
1 2 3 4 5 | int SHMapPIDLToSystemImageListIndex( IShellFolder *psf, PCUITEMID_CHILD pidl, int *piIndex ); |
这个函数的作用是,根据给定的 IShellFolder 接口和一个 PIDL,获取该 PIDL 在 Shell 图像列表中的图标索引。
经过逆向分析,发现这个函数的调用过程大致如下:
- 调用 IShellFolder::GetUIObjectOf,获取 IExtractIcon 接口指针;
- 调用 IExtractIcon::GetIconLocation,获取图标的位置信息;
- 调用 IExtractIcon::Extract 提取图标。
那么,我们相应的解决方案如下:
- 编写一个类,使其继承自 IShellFolder 和 IExtractIcon;
- 将所有不感兴趣的方法直接返回 E_NOTIMPL;
- 实现 IShellFolder::GetUIObjectOf,当接口请求为 IID_IExtractIcon 时返回 this;
- 实现 IExtractIcon::GetIconLocation,返回要提取的图标路径及索引;
- 实现 IExtractIcon::Extract,自行提取图标,或返回 S_FALSE 以使 Shell 自行提取图标。
由于无用代码太占篇幅了,因此略去。
沙发,备案没?
主机不在天朝。
前一段时间怎么那个titilima.cn的域名不能访问了?
现在能访问,这就够了。