转载:https://www.codeproject.com/Articles/7484/How-to-overlay-an-icon-over-existing-shell-objects
转载:https://blog.csdn.net/u012741077/article/details/50641518
系统默认的: 贴上图标后:
第一步:新建一个ATL项目,输入工程名:TxtInfo,具体如下图:
第二步:点击next
第三步:应用类型选择动态库链接(DLL),同时勾选 允许合并代理/存根代码和支持MFC,最后点击Finish。
第四步:新建一个ATL简单对象(英文版的VS为ATLSimple Object)
单击 Add,在第二页面中, 在Short Name编辑框中输入TxtShlExt,点击 Finish.
第五步:开始我们需要添加IShellIconOverlayIdentifier到CTxtShlExt实现的接口列表中.打开 TxtShlExt.h, 并添加如下代码:
class ATL_NO_VTABLE CTxtShlExt : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CTxtShlExt, &CLSID_TxtShlExt>, public IDispatchImpl<ITxtShlExt, &IID_ITxtShlExt, &LIBID_IconOverlayLib, /*wMajor =*/ 1, /*wMinor =*/ 0>, public IShellIconOverlayIdentifier//添加实现接口 { public: CTxtShlExt() { } DECLARE_REGISTRY_RESOURCEID(IDR_TXTSHLEXT) BEGIN_COM_MAP(CTxtShlExt) COM_INTERFACE_ENTRY(ITxtShlExt) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier)//添加接口入口 END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct() { return S_OK; } void FinalRelease() { } public: //实现接口的三个函数 STDMETHOD(GetPriority(THIS_ _Out_ int * pIPriority)); STDMETHOD(IsMemberOf(THIS_ _In_ PCWSTR pwszPath, DWORD dwAttrib)); STDMETHOD(GetOverlayInfo(THIS_ _Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int * pIndex, _Out_ DWORD * pdwFlags)); }; OBJECT_ENTRY_AUTO(__uuidof(TxtShlExt), CTxtShlExt)
TxtShlExt.cpp
//pwszPath 为当前文件的全路径 STDMETHODIMP CTxtShlExt::IsMemberOf(THIS_ _In_ PCWSTR pwszPath, DWORD dwAttrib) { HRESULT hRef = S_FALSE; wchar_t* fileClass = _wcsdup(wcsrchr(pwszPath, '.')); if (fileClass != NULL) { if (_wcsicmp(fileClass, L".txt") == 0) {//判断是否是txt后缀的文件 hRef = S_OK; } } free(fileClass); //如果是符合要求的文件,就返回S_OK return hRef; } //pwszIconFile 用于设置图标文件的路径,路径长度不能超过cchMax个字符。 //pIndex 用于设置图标覆盖的先后顺序 STDMETHODIMP CTxtShlExt::GetOverlayInfo(THIS_ _Out_writes_(cchMax) PWSTR pwszIconFile, int cchMax, _Out_ int * pIndex, _Out_ DWORD * pdwFlags) { WCHAR *buff = new WCHAR[cchMax]; //获取当前程序的路径,而不是调用该程序的程序的路径,因为调用该程序的是资源管理器(explorer.exe),直接过去路径的话,获取的是资源管理器的路径。 GetModuleFileNameW(_AtlBaseModule.GetModuleInstance(), buff, cchMax); WCHAR *nChar = wcsrchr(buff, L'\'); if (nChar != NULL) {//写入当前程序路径下的图标的名字 wcscpy_s(nChar, cchMax - wcslen(buff), L"\star.ico"); wcscpy_s(pwszIconFile, cchMax, buff); } //设置顺序 *pIndex = 0; //标识所修改过的数据pwszIconFile 与 pIndex *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX; free(buff); //完成返回S_OK return S_OK; } STDMETHODIMP CTxtShlExt::GetPriority(THIS_ _Out_ int * pIPriority) { *pIPriority = 0; return S_OK; }
第六步:注册COM接口
方式一:HKLM内容加入TxtShlExt.rgs中
编辑TxtShlExt.rgs文件
方式二:HKLM内容加入IconOverlay.rgs中
编辑IconOverlay.rgs
这段代码的意思就是将这个程序注册到资源管理器下的注册表项中。
需要注意的是需要区分系统是X86/X64,如果是X64的系统,请生成X64的程序,要不然不起作用的。
然后将程序中标明的图标的名字“star.ico”的图标与生成的程序放在一个目录。
用命令行注册COM :regsvr32 dll的绝对路径
注:必须以管理员运行cmd
卸载COM: regsvr32 /u dll的绝对路径
程序虽然注册成功了,但是还没有真正被使用,需要重启资源管理器,可以手动重启下。或在控制台下输入以下重启命令。
taskkill /f /im explorer.exe & explorer
重启后就可以看到效果了!