在介绍完了上面的两个概念后,接下来就是如何实现得问题了,当然了,我不会去讲解你应该如何去设计你的程序,这不是我得目的,何况每个人在设计上有有着很大的不同,这就只有考读者自己去设计了。我的程序是用C++ Builder写的,所以我在分析的时候也是用C++的代码举例,如果你不是C++Builder的使用者,那我就对不住了。
桌面图标:
桌面上有几个很特别的图标,那就是我的电脑,我得文档,网上邻居,回收站,如果你是Win98的用户,你是否发现了始终无法删除这几个图标,无论你是选中它再按Delete键,还是直接删除,都会得到无法删除的结果,难道就没有办法了吗?办法当然有,只要在注册表里找到对应的键值就可以轻松搞定,直接将注册表中像对应的键值删除就可以了,但后来的Wndows版本对桌面图标作了一些改变,比如我现在使用的WinXp里除了回收站以外其它图标则可以自由的删除,要搞定回收站也只好子找到注册表里相对应的键值也才能搞定了。
下面就是我整理的的这几个桌面图标在注册表里的位置,如下:
图标名 在注册表里对应的键
我的电脑 20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon
我的文档 CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon
网上邻居 CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon
回收站 CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon
他们存在于注册表里的
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\键值中
知道了他们在注册表里得位置后,如果要更改这些图标的话就变得简单了,以下就是我程序中的一段,它的作用就是将现在FmyIconsReg数组里的图标写进注册表,以此来达到更改注册表的目的
//图标
for (int i=0;i<TMyIcon_Max;i++)
{
iniTheme->WriteString(iconRegPosition+TMyIconReg[i],"",FMyIconsReg[i]);
} iniTheme->WriteString(iconRegPosition+TMyIconReg[TMyIcon_Max],"Full",FMyIconsReg[TMyIcon_Max]);
iniTheme->WriteString(iconRegPosition+TMyIconReg[TMyIcon_Max],"Empty",FMyIconsReg[TMyIcon_Max+1]);
其中TMyIconReg数组对应的值就是上表中列出的注册表的键值,iconRegPosition是以常量值表示桌面图标在注册表里的位置,他们的定义如下:
//图标
enum TMyIcon{
myComputerIcon,myDocumentIcon,
myNetworkIcon,myRecycleIcon,TMyIcon_Max=myRecycleIcon
};
AnsiString TMyIconReg[]={
"CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon", //我的电脑
"CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon", //我的文档
"CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon", //网上邻居
"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon" //回收站
};
AnsiString iconRegPosition="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\";
如果你还不够清楚的话,我这儿还为你准备了一个范例程序,请看:
void __fastcall TForm1::btnChangeIconClick(TObject *Sender)
{
AnsiString="Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon";
AnsiString iconPath=getSystemPath()+"\\shell32.dll,53";
setKeyValue(key,"",iconPath,false);
ReBuildIconCache();
}
怎么样是不是很简单,但你千万不要忘了,我是使用了定义的函数才使问题变得简单的,getSystemPath()的作用使取得系统目录的位置,它的定义如下:
AnsiString getSystemPath()
{
char buffer[256];
GetSystemDirectory(buffer,256);
return AnsiString(buffer);
}
之所以要使用这个函数来取得系统目录的目的在于不同的Windows版本它的系统目录可能不同,避免了因图标路径文件的位置错误而不能达到更个我得电脑图标的目的,还有一个原因是这样代码更简洁。
setKeyValue()函数的作用是设置注册表的键值,它的定义如下:
void setKeyValue(AnsiString RegPath,AnsiString Key,AnsiString Value,bool isAllUsers)
{
//TODO: Add your source code here
TRegistry *Registry = new TRegistry;
if (isAllUsers)
{
Registry->RootKey=HKEY_LOCAL_MACHINE;
}
else
{
Registry->RootKey=HKEY_CURRENT_USER;
}
try
{
Registry->OpenKey(RegPath,true);
Registry->WriteString(Key,Value);
}
__finally
{
delete Registry;
}
}
这样就避免了频繁使用Tregistry对象操作注册表时代码的臃肿,这个函数还有一个参数就是isAllUsers,它的目的时决定我使用的是HKEY_LOCAL_MACHINE目录下键值,还是 HKEY_CURRENT_USER目录下得键值,这两个的区别在于前者是针对所有用户,而后者只针对当前用户。
在那短短的几行代码中我还使用了一个比较重要的函数,setKeyValue函数虽然完成了图标的更改,但需要用户按F5键刷新后才能看到结果,而ReBuildIconCache()这个函数的目的就是完成F5键的功能,它强迫系统重建系统图标缓存以致于使用户马上能够看到改变后的结果。它的定义如下:
void ReBuildIconCache()
{
int IconW;
IconW= GetSystemMetrics(SM_CXICON);
TRegIniFile *Reg = new TRegIniFile("Control Panel\\Desktop");
try
{
//改变系统预设图标缓存的大小
Reg->WriteString("WindowMetrics", "Shell Icon Size", IntToStr(IconW-1));
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);
//将恢复系统预设图标缓存的大小
Reg->WriteString("WindowMetrics", "Shell Icon Size", IntToStr(IconW));
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);
}
__finally
{
delete Reg;
}
}
它的原理是这样的,只要程序改变了系统预设图标缓存的大小,然后在广播WM_SETTINGCHANGE消息,系统就会重建系统图标缓存,我们也就达到了更改后立即看到改变后的结果的目的。你也可以在http://www.zccfamily.com/zqget/ 网站下载该范例程序
本文地址:http://com.8s8s.com/it/it26808.htm