轉載: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
重啟后就可以看到效果了!