1. 程式人生 > >C++ Builder創建和調用dll中的資源

C++ Builder創建和調用dll中的資源

正常 面板 apt 用戶 .com reel pro trac 引號

程序開發中經常會用到一些圖標、圖片、光標、聲音等,我們稱它們為資源(Resource)。當多個窗口用到同樣的資源時,可以將這些公共的資源放到一個dll文件裏調用,這樣,由於定位資源比在磁盤中定位文件花費時間少,所以應用程序執行會更快。多種資源放在一個文件中,減少了圖標、圖片、光標、聲音等文件數量,從而可以減小應用程序的大小。不用怕用戶在使用過程中的不小心而損壞了資源文件致使程序無法正常運行。當然也可以不編為dll,而和應用程序放一起,用到時再LoadFromFile,但這樣容易丟失,一旦丟失了將影響程序的運行。

下面介紹如何將資源裝入dll文件並在應用程序中調用。

一、創建資源文件

首先將要用到的資源放在同一個文件夾下,新建一記事本,將後綴名改為.rc(此處暫以rc.rc的文件名為例)。註意事項:創建的資源文件名不要和工程名相同,因為bcb創建工程時會自動創建一個和工程名相同的資源文件,並且最好將資源文件保存到和工程文件同一個文件夾中。打開創建的rc.rc文件並按照如下格式寫入資源信息:

資源標識符 關鍵字 資源文件名

格式說明:

① 資源標識符:程序中調用資源時的特定標號,由自己定義。

② 關鍵字:標識資源文件類型;例如:

Wave : 資源文件是聲音文件;

RCDATA: JPEG文件;

AVI : AVI動畫;

ICON : 圖標文件;

BITMAP: 位圖文件;

CURSOR: 光標文件;

RMI : RMI音樂文件;

MIDI : MIDI音樂文件

EXEFILE:可執行文件

JPEG: jpg圖片

EXEFILE: exe可執行文件

③ 資源文件名:加入的資源文件名(要帶擴展名,可以帶路徑名構成全文件名);

④ 舉例:假如有三個圖形:“open.bmp”、“save.bmp”、“ico.ico”,獎在rc.rc文件裏寫下如下信息:

OPEN BITMAP open.bmp

SAVE BITMAP save.bmp

ICO ICON ico.ico

資源文件名可以不加引號,也可以加引號。保存rc.rc。

二、創建dll工程

1、在C++ Builder中新建DLL Wizard,在彈出的對話框上選擇Use VCL,如下圖:

技術分享 點擊“OK”後完成創建,並保存到上述資源文件所在文件夾。

2、點菜單上的“工程”/“添加到工程”(或Shift+F11),選擇上述寫好的rc.rc文件。

3、在Unit1.cpp裏添加以下兩個函數:

//-----------------------------------------------------------------------------

//加載bmp位圖

extern "C" __declspec(dllexport) HBITMAP __stdcall GetBitmap(AnsiString rcName);

HBITMAP __stdcall GetBitmap(AnsiString rcName)

{ return ::LoadBitmap(HInstance, rcName.c_str()); }

//加載ico圖標

extern "C" __declspec(dllexport) HICON __stdcall GetIcon(AnsiString);

HICON __stdcall GetIcon(AnsiString rcName)

{ return ::LoadIcon(HInstance, rcName.c_str());

}

//-----------------------------------------------------------------------

其中rcName為資源標識符。

4、保存工程,編譯(Alt+F9),並生成Project1(Ctrl+F9)。現在便得到了Project1.dll。

三、調用dll中的資源

重新新建一工程(Application),在Form1上加兩個BitBtn,並將其Caption屬性分別設為“打開”和“存儲”,在Form1的OnShow函數下寫下如下代碼:

//---------------------------------------------------------------------------

void __fastcall TForm1::FormShow(TObject *Sender)

{

HBITMAP __stdcall (*GetBitmap)(AnsiString); //定義函數原型

HICON __stdcall (*GetIcon)(AnsiString); //定義函數原型

HINSTANCE Hdl;

Hdl = ::LoadLibrary("Project1.dll"); //載入DLL

if(Hdl != NULL)

{

GetBitmap=(HBITMAP __stdcall (*)(AnsiString))::GetProcAddress(Hdl,"GetBitmap");

//取函數入口地址

if(GetBitmap!= NULL)

{BitBtn1->Glyph->Handle=GetBitmap("OPEN");

BitBtn2->Glyph->Handle=GetBitmap("SAVE");

}

GetIcon=(HICON __stdcall (*)(AnsiString))::GetProcAddress(Hdl,"GetIcon");

//獲取函數入口地址

if(GetIcon!= NULL)

{Icon->Handle= GetIcon("ICO"); }//改變窗體的圖標

::FreeLibrary(Hdl);

}

else {MessageBox(Handle,"不能載入資源Project.dll!","錯誤",48);}

}

//---------------------------------------------------------------------------

然後運行,則窗體的圖標變為資源中的圖標,兩個BitBtn也加載了圖形。

到此已完成dll中資源的調用功能。

四、其它資源

上述只介紹了位圖和圖標的存取,分別用到LoadIcon和LoadBitmap,對於其它資源的存取如下:

位圖:

mage1->Picture->Bitmap->Handle=LoadBitmap(HInstance,‘資源標識符‘);

或Image1->Picture->Bitmap->LoadFromResourceName(HInstance,‘資源標識符‘);

鼠標:

Screen->Cursors[1]=LoadCursor(HInstance,‘資源標識符‘);

Screen->Cursors[2]=LoadCursor(HInstance,‘資源標識符2‘);

Form1->Cursor=1; //僅用於Form1

Image1->Cursor=2;//僅用於Image1

Screen->Cursor=1;// 整個應用程序上都改變

在這裏定義了兩套鼠標,使用的話需要在rc文件種定義兩次鼠標資源文件。

圖標:

Application->Icon->Handle = LoadIcon(HInstance,‘資源標識符‘);

AVI文件

在工程中添加一TAnimate控件(在Win32控件面板上),在需要的地方加入:

Animate1->ResName="MyAvi" ; //資源標識

Animate1->Active = True ;

實踐中的一點結果:並不是所有的AVI資源都可以用TAnimate組件來播放,編定程序時要測試。遇到不能用TAnimate組件來播放的AVI資源,則可以把它從資源文件裏分離出來,再使用相應的播放組件比如TMediaPlayer來播放。使用完再把分離出來的臨時文件刪除掉。

Wave文件

#Include"MMSystem.h"

char *wav_handle ;

HRSRC h = FindResource(HInstance,"MyWav","WAV");

HGLOBAL h1 = LoadResource(HInstance, h);

wav_handle = (char *)LockResource(h1);

PlaySound(wav_handle,NULL, SND_MEMORY | SND_ASYNC);

FreeResource(h1);

//PlaySound(wav_handle,NULL, SND_MEMORY | SND_ASYNC|SND_LOOP);

//重復播放

JPEG圖片

#include"jpeg.hpp"

TJPEGImage *Fjpg=new TJPEGImage();

TResourceStream *FStream=new TResourceStream((int)HInstance,"MyJpg","JPEG");

Fjpg->LoadFromStream(FStream) ;

Image2->Picture->Bitmap->Assign(Fjpg);

EXE文件

先分離出來,再執行。

SetCurrentDir(path); //設置當前工作目錄

TResourceStream &res = *new TResourceStream( (int)HInstance, AnsiString("process"),"EXEFILE" ) ;

String file=path+"//process.exe";

res.SaveToFile(file);

delete &res;

STARTUPINFO si;

PROCESS_INFORMATION pi;

ZeroMemory(&si,sizeof(si));

si.cb=sizeof(si);

ZeroMemory(&pi,sizeof(pi));

CreateProcess(file3.c_str(),NULL,NULL,NULL,FALSE,CREATE_NO_WINDOW,NULL,NULL,&si,&pi);

註意,這裏CREATE_NO_WINDOW為不顯示窗口,根據需求設置不同的參數,請參照MSDN。

其它資源

可以把資源文件中的源文件分離出來,建立一個臨時的物理文件存在於應用程序路徑下,然後可以用相應類型的組件來或方法來使用該文件。當程序退出時再不忘把該臨時文件刪除掉。

例如:

string tmpDirectory ;

TResourceStream myres ;

tmpDirectory = ExtractFilePath(paramstr(0));

if (FileExists(tmpDirectory + "//Music1.RMI"))

myres = TResourceStream->Create(hinstance,"music1","RMI");

myres->SaveToFile(tmpDirectory + "Music1.RMI");//從資源文件中分離出來

myres->Free;

程序退出的時候刪除:

if(FileExists(tempDirectory + ‘//music1.RMI‘))

DeleteFile(tempDirectory + ‘//music1.RMI‘);

C++ Builder創建和調用dll中的資源