本文配套源碼
記得我以前寫過一篇文章是關於如何從一個可執行程序中吸取圖標。本文將討論如何得到與特定的文件類型關聯的文件圖標?
這個問題依賴於你是想要得到一個指定文件的圖標還是只想得到普通文件的圖標。如果你有一個特定的文件,如C:\MyFile\SomeFile.zzp。那你可以調用ExtractAssociatedIcon函數獲得於特定文件關聯 的圖標。但這個函數只適用於磁盤上存在實際的文件(或某處可存取)。
如果你想查找與一般文件類型關聯的圖標,那你就必須讀注冊表。例如,為了查找出.cpp文件使用的 圖標,你就要察看注冊表的HKEY_CLASSES_ROOT\.cpp入口,在我的機器上,其第一行的值是“cppfile”,然後繼續察看HKEY_CLASSES_ROOT\cppfile的DefaultIcon鍵值,在我的機器上 是:
HKEY_CLASSES_ROOT\cppfile\DefaultIcon =
"C:\PROGRA~1\MICROS~4\Common\MSDev98\Bin\msdev.exe,-20209"
所以.cpp文件的圖標在C:\PROGRA~1\MICROS~4\Common\MSDev98\Bin\msdev.exe文件中的圖標資源ID號為20209。一般情況下,HKCR\.foo有一個類似foofile的入口值,並在HKCR \foofile\DefaultIcon中 指定了cpp文件的圖標。
但是,有的時候.foo的入口值不是foofile,而是象“SuperApp.Document.5”,它的意思 是SuperApp文檔的第五個版本,在HKEY_CLASSES_ROOT\ SuperApp.Document.5中沒有DefaultIcon鍵值, 但有鍵值CLSID={又長又丑的十六進制GUID},這就告訴你.foo是COM對象,其類的ID值就是那又長又丑的 十六進制GUID。要得到關聯的圖標,必須到\CLSID\{又長又丑的十六進制GUID}\ DefaultIcon查找。哭 吧!太痛苦了。但是還沒完呢!因為foofile還可能有一個定制的以外殼擴展形式實現的圖標處理器。為 此你還要檢查一下,加載這個圖標處理器,調用IShellIcon或者IExtractIcon 並且繼續哭吧,這真是太 荒唐啦!
所幸的是,有一個更好的方法來避開令人厭惡的注冊表,那就是使用SHGetFileInfo函數,調用這個函數可以獲得所有關於文件的信息。它有一個聰明的選項,SHGFI_USEFILEATTRIBUTES,這個選項允許你 傳遞一個假文件名,如mumble.txt。即便文件不存在,SHGetFileInfo也能獲得你要的信息。
SHFILEINFO shfi;
memset(&shfi,0,sizeof(shfi));
SHGetFileInfo("foo.bmp",
FILE_ATTRIBUTE_NORMAL,
&shfi, sizeof(shfi),
SHGFI_ICON|SHGFI_USEFILEATTRIBUTES);
對話框中有一個編輯框,在這個編輯框中可以輸入任何文件的擴展名如txt、jpg、bmp等來察看與相 應文件關聯的圖標。實現方法很直接:當用戶敲入新的擴展名,Windows發送一個EN_UPDATE通知消息; 然後對話框調用SHGetFileInfo函數獲得圖標,接著將圖標顯示在一個靜態圖標控制上,詳細的實現細節請參考本文附帶的程序。