C++ Builder创建和调用dll中的资源
生活随笔
收集整理的這篇文章主要介紹了
C++ Builder创建和调用dll中的资源
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
程序開發中經常會用到一些圖標、圖片、光標、聲音等,我們稱它們為資源(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,如下圖:
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'); 結論:這篇文章是網上的。我照著做了一遍,遇到以下問題: 1、創建DLL Wizard 的程序,編譯時報錯:invalid bitmap format 2、即便Remove 掉 rc資源,編譯程序無錯,但是沒有dll 和 lib? 文件生成 ,只有obj文件 3、測試dll 程序 編譯報錯:nonportable pointer comparsion 期待網友幫忙,非常感謝!
下面介紹如何將資源裝入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'); 結論:這篇文章是網上的。我照著做了一遍,遇到以下問題: 1、創建DLL Wizard 的程序,編譯時報錯:invalid bitmap format 2、即便Remove 掉 rc資源,編譯程序無錯,但是沒有dll 和 lib? 文件生成 ,只有obj文件 3、測試dll 程序 編譯報錯:nonportable pointer comparsion 期待網友幫忙,非常感謝!
轉載于:https://www.cnblogs.com/azbane/p/7693419.html
總結
以上是生活随笔為你收集整理的C++ Builder创建和调用dll中的资源的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 依赖属性优先级
- 下一篇: 洛谷—— P1714 切蛋糕