修改文件类型图标得方式:
1 使用文件类型指定得图标
.myp
DefaultIcon
(Default) = C:\MyDir\MyProgram.exe,2 //C:\Users\qqq\Desktop\test.ico
2 使用关联程序默认图标
HKEY_CLASSES_ROOT
.myp
(Default) = MyProgram.1
MyProgram.1
DefaultIcon
(Default) = C:\MyDir\MyProgram.exe,2 //C:\Users\qqq\Desktop\test.ico
注意:当同时设置了文件类型得默认图标,又要设置了默认progId(关联程序),且关联程序设置了DefaultIcon,
那么将以关联程序得图表显示,譬如:
.myp
(Default) = MyProgram.1
DefaultIcon
(Default) = C:\MyDir\MyProgram.exe,0 //C:\Users\qqq\Desktop\test.ico
MyProgram.1
DefaultIcon
(Default) = C:\MyDir\MyProgram.exe,2 //C:\Users\qqq\Desktop\test.ico
那么将显示C:\MyDir\MyProgram.exe的第二个图标。
调用SHChangeNotify 以通知shell图标发生改变
参见:https://docs.microsoft.com/zh-cn/windows/win32/shell/how-to-assign-a-custom-icon-to-a-file-type
Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\%s\UserChoice 注册表项也能决定文件类型的图标
譬如:
Software
Microsoft
Windows
CurrentVersion
Explorer
FileExts
.myp
UserChoice
ProgId=MyProgram.1
MyProgram.1
DefaultIcon
(Default) = C:\MyDir\MyProgram.exe,2 //C:\Users\qqq\Desktop\test.ico
或者:
shellex
IconHandler
(default)={xxxxxxxxxxxxxxxxxxxxxxxxxxxx}
修改标准驱动器的图标和标签:
windows 2000下:
修改如下注册表项:
HKEY_CLASSES_ROOT
Applications
Explorer.exe
Drives
譬如:
HKEY_CLASSES_ROOT
Applications
Explorer.exe
Drives
E
DefaultIcon
(Default) = C:\MyDir\MyDrive.exe,3
DefaultLabel
(Default) = MyDrive
其他操作系统:
HKEY_LOCAL_MACHINE
Software
Microsoft
Windows
CurrentVersion
Explorer
DriveIcons
譬如:
HKEY_LOCAL_MACHINE
Software
Microsoft
Windows
CurrentVersion
Explorer
DriveIcons
E
DefaultIcon
(Default) = C:\MyDir\MyDrive.exe,3
DefaultLabel
(Default) = MyDrive
另需调用SHUpdateImage函数
参见:https://docs.microsoft.com/zh-cn/windows/win32/shell/how-to-assign-a-custom-icon-and-label-to-a-drive-letter
图标扩展处理程序
实现2大接口:IPersistFile, IExtractIcon
参考代码:
class ATL_NO_VTABLE Cextension :
public CComObjectRootEx,
public CComCoClass<Cextension, &CLSID_extension>,
public IDispatchImpl<Iextension, &IID_Iextension, &LIBID_ATLProject1Lib, /wMajor =/ 1, /wMinor =/ 0>,
public IPersistFile,
public IExtractIcon
{
public:
Cextension()
{
}
DECLARE_REGISTRY_RESOURCEID(106)
BEGIN_COM_MAP(Cextension)
COM_INTERFACE_ENTRY(Iextension)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IPersistFile)
COM_INTERFACE_ENTRY(IExtractIcon)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
//IPersistFile.IPersist Interface
STDMETHOD(GetClassID)(CLSID pClassID);
//IPersistFile Interface
STDMETHOD(IsDirty)(void);
STDMETHOD(Load)(/ [in] / __RPC__in LPCOLESTR pszFileName,
/ [in] / DWORD dwMode);
STDMETHOD(Save)(/ [unique][in] / __RPC__in_opt LPCOLESTR pszFileName,
/ [in] / BOOL fRemember);
STDMETHOD(SaveCompleted)(/ [unique][in] / __RPC__in_opt LPCOLESTR pszFileName);
STDMETHOD(GetCurFile)(/ [out] */ __RPC__deref_out_opt LPOLESTR *ppszFileName);
//IExtractIcon Interface
STDMETHOD(GetIconLocation)(THIS_
UINT uFlags,
Out_writes(cchMax) PWSTR pszIconFile,
UINT cchMax,
Out int * piIndex,
Out UINT * pwFlags);
STDMETHOD(Extract)(THIS_
In PCWSTR pszFile,
UINT nIconIndex,
Out_opt HICON *phiconLarge,
Out_opt HICON *phiconSmall,
UINT nIconSize);
};
//实现:
// extension.cpp: Cextension 的实现
STDMETHODIMP Cextension::GetClassID(CLSID *pClassID){
if (NULL != pClassID) {
*pClassID = CLSID_extension;
}
return S_OK;
}
STDMETHODIMP Cextension::IsDirty(void){
return E_NOTIMPL;
}
STDMETHODIMP Cextension::Load(__RPC__in LPCOLESTR pszFileName,/* [in] */ DWORD dwMode){
wchar_t tmp[1024] = {};
swprintf_s(tmp,1024,L"cur file:%s\n", pszFileName);
OutputDebugString(tmp);
return S_OK;
}
STDMETHODIMP Cextension::Save(/* [unique][in] / __RPC__in_opt LPCOLESTR pszFileName,
/ [in] / BOOL fRemember){
return E_NOTIMPL;
}
STDMETHODIMP Cextension::SaveCompleted(/ [unique][in] */ __RPC__in_opt LPCOLESTR pszFileName){
return E_NOTIMPL;
}
STDMETHODIMP Cextension::GetCurFile(/* [out] */ __RPC__deref_out_opt LPOLESTR *ppszFileName){
return E_NOTIMPL;
}
STDMETHODIMP Cextension::GetIconLocation(THIS_
UINT uFlags,
Out_writes(cchMax) PWSTR pszIconFile,
UINT cchMax,
Out int * piIndex,
Out UINT * pwFlags){
wchar_t path[MAX_PATH] = {};
SHGetSpecialFolderPath(NULL, path, CSIDL_DESKTOPDIRECTORY, FALSE);
PathCombine(path, path, L"test.ico");
if (!PathFileExists(path))
return S_FALSE;
lstrcpy(pszIconFile, path);
*piIndex = 0;
*pwFlags = 0;
return S_OK;
}
STDMETHODIMP Cextension::Extract(THIS_
In PCWSTR pszFile,
UINT nIconIndex,
Out_opt HICON *phiconLarge,
Out_opt HICON *phiconSmall,
UINT nIconSize){
//释放图标
//由shell 自己释放图标返回false,因为该文件只有一张图片,把该图片整体作为图标。如果GetIconLocation中
//指定了索引,那么就得自己处理返回得大小图标了。
return S_FALSE;
}
注:该代码不完整,只做接口实现参考。
参见:https://docs.microsoft.com/zh-cn/windows/win32/shell/how-to-create-icon-handlers
扩展程序如何起作用(被加载)参考:https://docs.microsoft.com/zh-cn/windows/win32/shell/reg-shell-exts(shell开发指南\实现自定义文件格式\使用shell扩展\注册shell扩展程序)
覆盖图标程序:
实现接口:IShellIconOverlayIdentifier
部分实现代码:
class ATL_NO_VTABLE CImpOverlay :
public CComObjectRootEx,
public CComCoClass<CImpOverlay, &CLSID_ImpOverlay>,
public IDispatchImpl<IImpOverlay, &IID_IImpOverlay, &LIBID_iconoverlayLib, /wMajor =/ 1, /wMinor =/ 0>,
public IShellIconOverlayIdentifier
{
public:
CImpOverlay()
{
}
DECLARE_REGISTRY_RESOURCEID(106)
BEGIN_COM_MAP(CImpOverlay)
COM_INTERFACE_ENTRY(IImpOverlay)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellIconOverlayIdentifier)
END_COM_MAP()
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
public:
//IShellIconOverlayIdentifier Interface
STDMETHOD(IsMemberOf)(__RPC__in_string LPCWSTR pwszPath,
/* [in] / DWORD dwAttrib);
STDMETHOD(GetOverlayInfo)(/ [size_is][string][out] / __RPC__out_ecount_full_string(cchMax) LPWSTR pwszIconFile,
/ [in] / int cchMax,
/ [out] */ __RPC__out int pIndex,
/ [out] */ __RPC__out DWORD *pdwFlags);
STDMETHOD(GetPriority)(__RPC__out int *pPriority);
};
//接口实现
STDMETHODIMP CImpOverlay::IsMemberOf(__RPC__in_string LPCWSTR pwszPath,
/* [in] */ DWORD dwAttrib){
//返回S_OK代表覆盖,S_FALSE代表不覆盖.
//pwszPath 为将要被覆盖的文件全路径。
if (pwszPath != NULL)
{
wchar_t txt[1024] = { 0 };
swprintf_s(txt, L"CImpOverlay cur file:%s", pwszPath);
OutputDebugString(txt);
}
return S_OK;
}
STDMETHODIMP CImpOverlay::GetOverlayInfo(
/* [size_is][string][out] / __RPC__out_ecount_full_string(cchMax) LPWSTR pwszIconFile,
/ [in] / int cchMax,
/ [out] */ __RPC__out int pIndex,
/ [out] */ __RPC__out DWORD *pdwFlags){
//pwszIconFile返回将要使用的覆盖图标的文件,可以是 .exe 或者 .dll 或者.ico
//pIndex 返回该图标在文件中的索引,针对单一文件包含多个图标的情况
//pdwFlags,2种取值。1:ISIOI_ICONFILE 代表返回了图标文件,2:ISIOI_ICONINDEX 代表图标文件的索引
wchar_t path[MAX_PATH] = {};
SHGetSpecialFolderPath(NULL, path, CSIDL_DESKTOPDIRECTORY, FALSE);
PathCombine(path, path, L"test.ico");
lstrcpy(pwszIconFile, path);
*pIndex = 0;
*pdwFlags = ISIOI_ICONFILE;
return S_OK;
}
STDMETHODIMP CImpOverlay::GetPriority(
/* [out] */ __RPC__out int *pPriority){
//pPriority 优先级,当具有多个图标覆盖扩展程序时,设置优先级决定优先权。推荐设置为0.
*pPriority = 0;
return S_OK;
}
可参考:https://www.codeproject.com/Articles/7484/How-to-overlay-an-icon-over-existing-shell-objects