Delphi资源文件的应用(转)
生活随笔
收集整理的這篇文章主要介紹了
Delphi资源文件的应用(转)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
| (一)初級應(yīng)用篇: 資源文件一般為擴(kuò)展名為res的文件.在VC中資源文件用得非常普遍,但Delphi在其聯(lián)機(jī)幫助中對資源文件沒作什么介紹,其實利用其自帶的資源編譯工具BRCC32.EXE(一般位于\Delphi\BIN目錄下),我們完全可以做出跟VC一樣效果的文件來。 資源文件最大的好處是能將一些在必要時才調(diào)用的文件跟可執(zhí)行文件一起編譯,生成一個文件.這樣做最大的好處就是使外部文件免遭破壞.例如在一條程序中你要臨時調(diào)用一幅圖片,一般作法是把圖片放在某一路徑下(通常是主程序所在路徑),但如果用戶路徑誤刪你的圖片文件,則可能使程序找不到相應(yīng)文件而出錯崩潰.另外,如果你想自己的程序界面美觀,想用一些自定義光標(biāo),也要用到資源文件。 資源文件的使用步驟為: 1.編寫rc腳本文本 用記事本或其它文本編輯器編寫一個擴(kuò)展名為rc的文件。例如: mycur cursor move.cur //加入光標(biāo) mypic Bitmap Water.BMP //加入位圖 mywav WAVE happy.wav //加入聲音 myAVI AVI EPOEN.AVI //加入視頻 myIco ICON CJT.ICO //加入圖標(biāo) 格式分別為在資源文件中的名稱->類型->實際文件名稱,例如上面第一行定義一個名為mycur的光標(biāo),實際名稱為加入光標(biāo)move.cur. 2.將rc文件編譯成res資源文件 將腳本文件和實際文件拷到Brcc32.EXE所在目錄,執(zhí)行DOS命令。格式為:Brcc32 腳本文件(回車),例如有一名為myfirst.rc的腳本文件,則執(zhí)行 Brcc32 myfirst.rc(回車)即可。如果你是懶人,也可新建一批處理文件,內(nèi)容只有一行:Brcc32 mufist.rc.(因為Delphi安裝后一般會在自動批處理文件中指明搜索路徑的。)如果編譯成功,則會生成一個結(jié)尾為res的文件,這個文件就是我們需要的資源文件。 3.在Delphi單元中加入資源文件 將生成的res資源文件拷貝到你所編程序的路徑下,在單元文件{$R *DFM}后加上一句{$R mufirst.res},則將res文件加入去,編譯后資 源文件即已包含在可執(zhí)行文件中了。若你有多個資源文件,也按上法依次加入。 4.在Delphi程序中調(diào)用資源文件 資源文件在Delphi中的關(guān)鍵字為hinstance.下面給出具體用法. <1>光標(biāo)的調(diào)用 首先在程序中定義一個值大于0的常量,因為Delphi本身用0-負(fù)16來索引默認(rèn)的光標(biāo),所以我們制定的光標(biāo)應(yīng)從表面上1開始索引。然后在窗口的Oncreat事件中添加以下代碼: screen.cursor[35]:=Loadcursor (hinstance,'mycur'); 其中35為大于1的常量,mycur為光標(biāo)在資源文件中的名字。如果希望在其他控件上使用定制光標(biāo),例如Panel控件,只需在程序的適當(dāng)處加入以下代碼: Panel1.cursor:=35; <2>位圖的調(diào)用 新建一項工程,添加一Timage控件,在需要顯示的地方寫以下代碼: Var mymap:Hbitmap; begin mymap:=LoadBitmap(hinstance,'mypic'); Image1.picture.Bitmap.Handle:=mymap; end; 其中"mypic"為位圖資源文件中的名稱。 〈3〉A(chǔ)VI文件的調(diào)用 新建一工程,添加一Animate控件,在需要的地方加入: animater1.resname:='myAVI'; animater1.Active:=true; 其中myAVI為視頻文件在資源文件中的名稱。 〈4〉調(diào)用WAV文件 在uses中加入mmsystm單元,以便在程序中播放WAV文件。播放時Playsound(pchar('mywav'),hinstance,sndsync or snd_resource);其中mywav為聲音文件在資源中的名稱。 〈5〉加入光標(biāo) 加入光標(biāo)比較容易,只要將res文件加入單元文件中即可。但需注意,名稱最好取"W"."WW"等,使第一個字母盡量靠后,以免與主程序的圖標(biāo)順序顛倒。這樣一來,別人在使用你的程序時如果想選擇其它圖標(biāo)就有很多選擇了。 補充: 1.資源類型除上述類型外,還可以字體文件,字符串文件等。 2.資源文件不但可以在標(biāo)準(zhǔn)圖形界面下使用還可在控制臺下使用。 下面我們來試驗一下: 新建一工程,將唯一的一個Form刪除,然后修改工程文件。增加一句{$Apptype console},在uses子句中加入mmsystem,并將其它引用單元刪掉。將Begin和end之間語句刪掉。至此,我們就可和Turbo PASCAL下編程序一樣,且還可以調(diào)用windows的API和資源。將資源文件----{$R myfist.res}加入。在Begin和end之間寫下: writeln('演示程序,按任意鍵開始!'); readln; playsound(pchar('mywav'),hinstance,snd_sync or snd_resource); writeln('演示結(jié)束!'); 運行程序,將彈出一個標(biāo)準(zhǔn)DOS窗口,按任意鍵播放聲音文件。是不是很COOL呢!我曾下載過一個播放器,在其安裝目錄下我發(fā)現(xiàn)有一"DOS程序",用鼠標(biāo)雙擊它便彈出一個DOS窗口,顯示DOS時代特有的畫圖,并有背景音樂!可能就是用這個方法做的。 3.Delphi本身自帶了一個叫Image Editor的工具,同樣可以編輯資源文本,但和本文的方法比較,可得出下表: ************************************** Image Editor Brcc32 BMP 只支持16位色 任意色 光標(biāo) 黑白兩色 任意色 ICO 只支持16位色 任意色 AVI 不支持 支持 WAV 不支持 支持 字體 字符串 不支持 支持 其他 **************************************** 上面說的是直接在程序本身的調(diào)用。其實資源文件還有其它用法。比如說在你的程序攜帶其它文件,要用的時候釋放出來。 例如: myexe exefile 'ha1.exe'//腳本文件 下面是自定義釋放函數(shù)ExtractRes,本例中使用如下: ExtractRes('exefile','myexe','c:\new.exe'); 就把ha1.exe以new.exe為名字保存到C盤根目錄下了. function TForm1.ExtractRes(ResType, ResName, ResNewName: string): boolean; var Res: TResourceStream; begin try Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType)); try Res.SavetoFile(ResNewName); Result := true; finally Res.Free; end; except Result := false; end; ---------------------------------------------------------------------- (二)中級應(yīng)用篇: 上面我們已經(jīng)知道如何把一副BMP圖像從資源文件里面讀出來,但是BMP文件太大了,JPG文件應(yīng)用的相對較多.那么如何把JPG圖像讀出來呢?用資源文件加流方式即可。具體方法如下: (1)MyJpg JPEG My.JPG (2)Var Stream:TStream; MyJpg:TJpegImage; Begin Stream:=TResourceStream.Cceat(HINSTANCE,'MyJpg','JPEG'); Try MyJpg:=TJpegImage.Create; Try MyJpg.LoadfromStream(Stream); Image1.Picture.Assignc(MyJpg); Finally MyJpg.Free; end; Finally Stream.Free; end; end; 讀取其它圖片文件也是一樣的.比如說gif動畫文件,當(dāng)然前提是你有一個gif.pas,這個單元很多站點都有的,可以自己去找找。實際應(yīng)用中我還發(fā)現(xiàn)用上面的代碼可以直接顯示資源文件中的ICON和BMP. 說到圖形處理,實際上還可以用Delphi創(chuàng)建、調(diào)用純圖標(biāo)資源的DLL.比如說你可以看看超級解霸目錄下的Dll,很多就是純圖標(biāo)資源而已。具體方法如下: (1):創(chuàng)建一個Hicon.RES文件,這里不再重復(fù). (2):新建一文本文件Icon.dpr,內(nèi)容如下: library Icon; {$R Icon.RES} begin end. 用Delphi打開編譯即可得到Icon.dll. (3):實際調(diào)用方法如下: ...... Private Hinst:THANDLE; ...... Var Hicon:THANDLE; begin Hinst:=Loadlibrary('Icon.dll'); If Hinst=0 Then Exit; Hicon:=Loadicon(Hinst,Pchar(Edit1.Text)); If Hicon<>0 Then Image1.Picture.Icon.Handle:=Hicon; FreeLibrary(Hinst); end; 如果你的程序想在國際上供使用不同語言的人使用的話,用Dll來存放字符資源將是一個好方法.因為Dll不象ini文件那樣可以被人隨便修改,特別是有時侯如果想保存一些版權(quán)信息的話用Dll就再好不過了。比如說你準(zhǔn)備開發(fā)一個"漢字簡繁體翻譯器"軟件,準(zhǔn)備提供Gb32,Big5碼和英文三種語言菜單給用戶,那么你可以試試用Dll來保存字符資源. 我們需要建立三個Dll.第一步當(dāng)然是寫Rc文件,舉Gb32碼為例,內(nèi)容如下: /*MySc.rc*/ #define IDS_MainForm_Caption 1 #define IDS_BtnOpen_Caption 2 #define IDS_BtnSave_Caption 3 #define IDS_BtnBig5_Caption 4 #define IDS_BtnGb32_Caption 5 #define IDS_BtnHelp_Caption 6 #define IDS_Help_Shelp 7 Stringtable { IDS_MainForm_Caption,"漢字簡繁體翻譯器" IDS_BtnOpen_Caption,"打開文件" IDS_BtnSave_Caption,"保存文件" IDS_BtnBig5_Caption,"轉(zhuǎn)換成Big5" IDS_BtnGb32_Caption,"轉(zhuǎn)換成Gb32" IDS_BtnHelp_Caption,"幫助" IDS_Help_Shelp,"輸入文字或打開文件后按需要點擊按鈕即可轉(zhuǎn)換!" } 第二步是Brcc32編譯為Res文件后用上面的方法得到Dll文件,另外兩個Dll用同樣的方法生成.下面來應(yīng)用一下: 新建一個工程,放上五個Button:BtnOpen,BtnSave,BtnBig5,BtnGb32和BtnHelp.還有一個TComboBox:CbSelect用來選擇語言種類的. 具體代碼如下: unit Unit1; interface ...... private SHelp: string; function SearchLanguagePack: TStrings; procedure SetActiveLanguage(LanguageName: string); { Private declarations } ...... implementation procedure TForm1.CbSelectChange(Sender: TObject); begin SetActiveLanguage(CbSelect.Text);//調(diào)用相應(yīng)Dll文件讀取相應(yīng)字符. end; procedure TForm1.FormCreate(Sender: TObject); begin CbSelect.Items.AddStrings(SearchLanguagePack);//搜索當(dāng)前目錄下所有的Dll文件名稱 end; function TForm1.SearchLanguagePack: TStrings; var ResultStrings: TStrings; DosError: integer; SearchRec: TsearchRec; begin ResultStrings := TStringList.Create; DosError := FindFirst(ExtractFilePath(ParamStr(0)) + '*.dll', faAnyFile, SearchRec); while DosError = 0 do begin ResultStrings.Add(ChangeFileExt(SearchRec.Name, '')); DosError := FindNext(SearchRec); end; FindClose(SearchRec); Result := ResultStrings; end; procedure TForm1.SetActiveLanguage(LanguageName: string); var Hdll: Hmodule; MyChar: array[0..254] of char; DllFileName: string; begin DllFileName := ExtractFilePath(ParamStr(0)) + LanguageName + '.dll'; if not FileExists(DllFileName) then Exit; Hdll := loadlibrary(Pchar(DllFileName)); Loadstring(hdll, 1, MyChar, 254); Self.Caption := MyChar; //讀取字符資源,1表示資源文件中定義的1 Loadstring(hdll, 1, MyChar, 254); Self.Caption := MyChar; Loadstring(hdll, 2, MyChar, 254); BtnOpen.Caption := MyChar; Loadstring(hdll, 3, MyChar, 254); BtnSave.Caption := MyChar; Loadstring(hdll, 4, MyChar, 254); BtnBig5.Caption := MyChar; Loadstring(hdll, 5, MyChar, 254); BtnGb32.Caption := MyChar; Loadstring(hdll, 6, MyChar, 254); BtnHelp.Caption := MyChar; Loadstring(hdll, 7, MyChar, 254); SHelp := MyChar; Freelibrary(hdll); Application.Title := Self.Caption; //------------------------ BtnOpen.Visible := True; BtnSave.Visible := True; BtnBig5.Visible := True; BtnGb32.Visible := True; BtnHelp.Visible := True; //------------------------ end; procedure TForm1.BtnHelpClick(Sender: TObject); begin Application.MessageBox(Pchar(SHelp), 'Http://lovejingtao.126.com', MB_ICONINFORMATION); end; end. 可能你會說,這種方法還不如我自己在程序中直接定義三種具體的值來的方便.甚至我自己自定義一個結(jié)構(gòu)好了,用不著用DLL那么麻煩的。但是如果你的程序要用的字符很多呢?比如說Windows操作系統(tǒng),本身就有簡體中文,繁體中文,英文等等版本,用Dll的話只要直接替換DLL即可,而不用每發(fā)行一個版本就打開代碼來修改一次。這樣一來可以大大減少工作量和出錯的機(jī)會.說到這里,再多說一句:Windows系統(tǒng)本身很多Dll帶有了圖片等資源,我們可以在程序中直接調(diào)用,這樣一來我們的EXE也可以減少不少!當(dāng)然最小的方法是實時生成技術(shù).老外曾經(jīng)寫了一個67KB的程序就是利用了這個方法.感興趣的朋友可以到http://go4.163.com/lovejingtao/ha1.exe下載. ---------------------------------------------------------------------- (三)高級應(yīng)用篇: Delphi是個很有效率的開發(fā)工具,但是它有一個缺點就是生成的EXE文件太大.一個程序就算只有一個空窗口體積也有286KB.如果直接用API來寫的話程序體積是小了,但是又太繁瑣,無法立即看到界面效果,根本談不上是可視化開發(fā).其實并非"魚與熊掌不可兼得",利用資源文件我們就可以輕松達(dá)到這個目的. 在開始之前,我們需要一個可以編輯資源文件的工具.這類工具很多,比如說Resource WorkShop就是非常好的一個.如果一時找不到,利用VC的編輯器來也是可以的.下面我們就以VC的為例示范如何創(chuàng)建一個窗口資源文件.運行VC,打開菜單File-->New,將出現(xiàn)一個多項選擇頁.我們選擇Files-->ResourceTemplate,在右邊的File填上Demo,Location選擇保存路徑,然后點擊按鈕OK返回VC開發(fā)環(huán)境. 選擇菜單Insert-->Resource,將出現(xiàn)一個資源類型選擇框.我們把鼠標(biāo)移到Dialog上面.不用展開,點擊右邊的New即可,這時候返回VC開發(fā)環(huán)境并出現(xiàn)一個只有關(guān)閉按鈕和兩個Button的窗體.將鼠標(biāo)選定窗體,擊右鍵選擇最后一項Properties,將出現(xiàn)一個設(shè)置窗口,將ID改為"MAINFORM"(注意:跟下面添加的其它控件的屬性設(shè)置方法不同,主窗口的ID必須把雙引號寫上去,而且名稱必須為大寫.否則程序?qū)⒄也坏劫Y源.程序會一運行就退出了.)Caption改為"安裝程序",這時候可以立刻看到窗口的標(biāo)題變成了"安裝程序",把Styles的Minimize box選上,More Styles的Center勾上使程序運行時的位置居中.當(dāng)然你也可以設(shè)置它的坐標(biāo).其它保留默認(rèn)值即可.回到開發(fā)環(huán)境,在控件框里面分別選擇一個Static Text,一個Edit Box,一個Button和一個Group Box添加到窗體上面.把它們按照自己的愛好排列整齊.然后逐個修改它們的屬性.方法就是按照上面說的選定控件后擊右鍵選擇最后一項Properties,在出現(xiàn)的屬性框里面修改.其中屬性如下:Group Box的Caption屬性清空,Static Text的Caption屬性改為"請選擇安裝目錄:",Edit Box的ID改為10001.第一個Button的ID為10002,Caption屬性為"選擇",第二個Button的ID為10003,Caption屬性為"安裝",第三個Button的ID為10004,Caption屬性為"退出".為了使程序更加完美,我們?yōu)樗偬砑右粋€菜單IDR_MENU1.選擇Insert-->Resource-->Menu,我們這里只簡單添加一項"文件-->退出",其中"退出"的ID為10005.然后在主窗口的屬性Menu設(shè)定為IDR_MENU1即可. 為了使程序更加美觀,我們再添加一個小圖標(biāo),同時這也將是我們程序的圖標(biāo).選擇Insert-->Resource-->Icon-->Import,選擇一個圖標(biāo)文件.并將它的ID設(shè)置為"MAINICON"(注意:必須把雙引號寫上而且字母為大寫),為窗口添加一個Picture控件并設(shè)置它的屬性Type:Icon,Image下拉選擇剛才的圖標(biāo)MainIcon即可. 如果你想為程序在鼠標(biāo)添加一些信息也是可以的.選擇Insert-->Resource-->Version即可. 到這里我們已經(jīng)完成了一個簡單的"安裝程序"的窗體設(shè)計.實際上我們現(xiàn)在就可以在Delphi中調(diào)用它了.我們先把"勞動成果"保存起來.選擇File-->Save As,在文件類型里選擇"32-bit Resource File(.res)"保存為"Demo.res",文件大小大約為2.65KB. 新建一個擴(kuò)展名為dpr的文本文件MyDemo.Dpr,鍵入如下代碼: Uses Windows,Messages; {$R Demo.Res} function MainDialogProc(DlgWin:hWnd;DlgMessage:UINT;DlgWParam:WPARAM;DlgLParam:LPARAM):integer;stdcall; begin Result := 0; case DlgMessage of WM_Close: begin PostQuitMessage(0); Exit; end; end; end; begin DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc); end. 用Delphi打開它編譯一次即可產(chǎn)生一個大小為19KB的EXE.是不是很小!實際上,你甚至只用一行代碼就把它Show出來,不過程序無法關(guān)閉而已. Uses Windows; {$R Demo.Res} function MainDialogProc: integer; begin Result := 0; end; begin DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc); end. 上面的程序只不過是一個空窗口而已,現(xiàn)在我們來寫代碼響應(yīng)按下相應(yīng)按鈕響應(yīng)的事件.完整代碼如下: program MyDemo; uses Windows, Messages, shlobj; const ID_Edit = 10001; ID_Selet = 10002; ID_Setup = 10003; ID_Quit = 10004; ID_Exit = 10005; {$R Demo.Res} var MainWin: HWND; function My_Gettext: string; var Textlength: Integer; Text: PChar; s: string; begin TextLength := GetWindowTextLength(GetDlgItem(MainWin, ID_Edit)); GetMem(Text, TextLength + 1); GetWindowText(GetDlgItem(MainWin, ID_Edit), Text, TextLength + 1); s := text; FreeMem(Text, TextLength + 1); Result := s; end; function Getmyname: string; var i, j: integer; begin J := 3; for i := 1 to length(ParamStr(0)) do if ParamStr(0)[i] = '\' then J := I; Result := copy(ParamStr(0), J + 1, length(ParamStr(0)) - J); end; function SelectDirectory(handle: hwnd; const Caption: string; const Root:WideString;outDirectory:string): Boolean; var lpbi: _browseinfo; buf: array[0..MAX_PATH] of char; id: ishellfolder; eaten, att: cardinal; rt: pitemidlist; initdir: pwidechar; begin result := false; lpbi.hwndOwner := handle; lpbi.lpfn := nil; lpbi.lpszTitle := pchar(caption); lpbi.ulFlags := BIF_RETURNONLYFSDIRS + BIF_EDITBOX; SHGetDesktopFolder(id); initdir := pwchar(root); id.ParseDisplayName(0, nil, initdir, eaten, rt, att); lpbi.pidlRoot := rt; getmem(lpbi.pszDisplayName, MAX_PATH); try result := shgetpathfromidlist(shbrowseforfolder(lpbi), buf); except freemem(lpbi.pszDisplayName); end; if result then begin directory := buf; if length(directory) <> 3 then directory := directory + '\'; end; end; function MainDialogProc( DlgWin: hWnd; DlgMessage: UINT; DlgWParam: WPARAM; DlgLParam: LPARAM ) : integer; stdcall; var MyIcon: HICON; Sdir: string; begin Result := 0; case DlgMessage of WM_INITDIALOG: begin MyIcon := LoadIcon(hInstance, 'MainIcon'); SetClassLONG(DlgWin, GCL_HICON, MyIcon); MainWin := DlgWin; end; WM_Close: begin PostQuitMessage(0); Exit; end; WM_COMMAND: case LOWORD(DlgWParam) of ID_Selet: begin if SelectDirectory(DlgWin, '請選擇安裝目錄', '', Sdir) then SendMessage(GetDlgItem(DlgWin, ID_Edit), WM_SETTEXT, 0, lParam(pChar(Sdir))); end; ID_Setup: begin if My_Gettext = '' then begin MessageBox(DlgWin, '請先選擇安裝文件夾!', '信息', MB_ICONINFORMATION + MB_OK); Exit; end; CopyFile(pchar(ParamStr(0)), pchar(My_Gettext + Getmyname), false); MessageBox(DlgWin, '安裝完畢!', '信息', MB_ICONINFORMATION + MB_OK); PostQuitMessage(0); Exit; end; ID_Quit: begin PostQuitMessage(0); EXIT; end; ID_Exit: begin if MessageBox(DlgWin, '你點擊了菜單“退出”,你確定退出程序嗎?', '信息', MB_ICONQUESTION + MB_OKCANCEL) = IDOK then PostQuitMessage(0); Exit; end; end; end; end; begin DialogBox(hInstance, 'MAINFORM', 0, @MainDialogProc); end. 其中SelectDirectory函數(shù)的作用是返回一個選擇的文件路徑.然后把自己拷貝到選擇的目錄下,當(dāng)然很多處理沒有寫,讀者可以自行添加.文件編譯后大小為22KB,如果直接用Delphi的VCL來寫的話,將為338KB!完整代碼可以在我的主頁上下載:http://go4.163.com/lovejingtao/setup2.zip.代碼中的消息處理相信大家看的懂.如果不用資源文件而直接用API來寫將對它更加理解深刻,.限于篇幅這里不做詳細(xì)介紹,感興趣的讀者可以自行下載代碼來看:http://go4.163.com/lovejingtao/setup1.zip. 全部代碼在Delphi+Pwin2000下通過. |
轉(zhuǎn)載于:https://www.cnblogs.com/GeneralXU/archive/2008/11/25/1340989.html
總結(jié)
以上是生活随笔為你收集整理的Delphi资源文件的应用(转)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ubuntu根目录文件作用分析
- 下一篇: WinCE开发初探——开发环境