----Windows95和NT是被無數計算機用戶所青睐的圖形界面(GUI)操作系統。我們知道,許多Win95或NT下的32位應用程序都帶有圖標(一般來說至少有一個),此外其它一些可執行模塊也常常是圖標的寶庫。這些可執行模塊包括*.EXE(可執行文件),*.DLL(DynamicLinkLibrary,即,動態連接庫),*.CPL(控制面板模塊)等。其中,不少圖標做得非常精致、漂亮,特別惹人喜歡。當然,其中大部分的圖標你可能無法直接看到。因此,不少人也許希望能有一種工具可以把這些精彩的圖標從那些文件中"取"出來。筆者就有過這種想法。後來,筆者自己動手寫了一個程序,使用它,我現在可以隨心所欲地從任何包含圖標資源的文件中提取任何我所喜愛的圖標,更不用說輕松地浏覽文件中的所有圖標了。
----大家知道,包含在可執行模塊中的圖標資源是以二進制數據(或稱,資源)的形式存儲的,因而,我們應該把這些二進制數據轉換成圖標文件的格式,然後再存為圖標文件(*.ICO)。因為有了InpriseCorporation(原BorlandInternational)的Delphi提供的強大的類庫和可視化支持,這項工作已變得相對比較輕松了。Delphi提供了TIcon類,該類中有一個名為SaveToFile的方法,它可方便地把對象所指的二進制數據直接存儲成圖標格式的文件。於是,要從其它可執行模塊中提取圖標,我們只需把其它模塊中的二進制數據"拷"到一個TIcon對象中即可(在下面的程序中使用了一個TImage構件,該構件中包含了一個TIcon對象)。那麼,怎樣把數據拷到TIcon對象中呢?其實,你只需把一個圖標的句柄賦給TIcon對象的句柄屬性,其它細節都由Delphi代我們完成。我們可以通過Windows的API函數ExtractIcon來獲取其它模塊中圖標的句柄。下面的這個程序可以讓你輕松地浏覽文件中所包含的所有圖標,並且可以方便地保存下你喜歡的圖標(如果此文件包含有圖標資源的話)。此外,該程序還可以把位圖文件(*.BMP)或圖元文件(Metafile)縮小成圖標文件。為了讓大家更輕松地閱讀此程序,筆者已經使程序的代碼盡可能的短小,讀者可在本示例的基礎上進行其它的擴充。
----向Form1上加入如下構件:
----(1)從Standard頁上選取3個TButton構件,並把Button1、Button2和Button3的Caption分別改為"向前浏覽"、"向後浏覽"和"保存圖標"。把Button1和Button2的Tag屬性分別改為1和-1(負1)。讓Button2跟Button1共用一個OnClick事件句柄。
----(2)從Standard頁上選取一個TMainMenu構件,把第一個菜單項(缺省名為N1)的Caption改為"文件",再把它下面的菜單項(N2)的Caption改為"打開文件"。
----(3)從Standard頁上選取一個TLabel
----(4)從Additional頁上選取一個TImage
----(5)從Dialogs頁上選取一個TOpenDialog,並把它的Options屬性的ofNoReadOnlyReturn子屬性改為False。
----(6)將Form1的Font改成System字體。
----(7)在Unit1的Interface部分的Uses語句中加入ShellAPI單元(以便使用API函數ExtractIcon)。
unitUnit1;
interface
uses
Windows,Messages,SysUtils,Classes,
Graphics,Controls,Forms,Dialogs,
Menus,StdCtrls,ExtCtrls,ShellAPI;
type
TForm1=class(TForm)
Image1:TImage;
Button1:TButton;
Button2:TButton;
Button3:TButton;
MainMenu1:TMainMenu;
N1:TMenuItem;
N2:TMenuItem;
Label1:TLabel;
OpenDialog1:TOpenDialog;
procedureButton1Click(Sender:TObject);
procedureFormCreate(Sender:TObject);
procedureButton3Click(Sender:TObject);
procedureN2Click(Sender:TObject);
private
{Privatedeclarations}
public
{Publicdeclarations}
end;
var
Form1:TForm1;
Total,//文件中圖標的總數
No:Integer;//當前圖標在原文件中的序號
Path,//程序所在的路徑
ModuleName:String;//從哪個文件提取圖標
implementation
{$R*.DFM}
procedureTForm1.Button1Click(Sender:TObject);
//該事件句柄被Button1和Button2所共享
//Button1和Button2的Caption
分別是"向前浏覽"和"向後浏覽"
//Button1和Button2的Tag分別是1和-1
begin
ifTotal=0ThenExit;
No:=No (SenderasTButton).tag;
ifNo>TotalthenNo:=0;
ifNo<0thenNo:=Total;
Image1.Picture.Icon:=nil;
Image1.Picture.Icon.Handle:
=ExtractIcon(hInstance,PChar(ModuleName),No);
Label1.Caption:='No.' IntToStr(No) 'icon';
//Label1用於指示當前圖標在原文件中的序號
end;
procedureTForm1.FormCreate(Sender:TObject);
begin
Path:=ExtractFilePath(Application.ExeName);
//下面的代碼使程序有處理命令行參數的能力
ifParamCount>0
Thenbegin
ModuleName:=ParamStr(1);
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
Form1.caption:=IntToStr(Total)
'icon(s)foundin' ParamStr(1);
end;
end;
procedureTForm1.Button3Click(Sender:TObject);
//這段代碼保存當前圖標
begin
IfTotal=0ThenExit;
Image1.Picture.Icon.SaveToFile
(Path 'Icon' IntToStr(No) '.ico');
{把圖標文件與該程序存於
同一目錄,文件名為"Icon"加序號的形式}
end;
procedureTForm1.N2Click(Sender:TObject);
//這段代碼從菜單中選擇一個文件
begin
IfOpenDialog1.Execute
thenbegin
ModuleName:=OpenDialog1.FileName;
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
No:=0;Label1.Caption:='';
Form1.Caption:=IntToStr(Total) 'icon(s)foundin' ModuleName;
end;
end;
end.
(調試環境:Delphi4.0,Windows95,WindowsNT4)
----說明:API函數ExtractIcon是在ShellAPI單元中聲明的,所以你必須在Uses語句中加入此單元才能使用該函數。它在Delphi中的原型聲明如下:
----functionExtractIcon(hInst:HINST;lpszExeFileName:PChar;nIconIndex:UINT):HICON;stdcall;
----參數說明:
----hInst:為調用該函數的實例句柄;
----lpszExeFileName:指明從哪個文件提取圖標(不一定非得是EXE文件);
----nIconIndex:該參數為負1時,函數返回指定文件中包含的圖標個數;否則,返回序號為nIconIndex的圖標(如果存在的話)的句柄。在文件中圖標的序號是從0開始的。
----如果函數調用失敗則返回0.->