程序开发中经常会用到一些图标、图片、光标、声音等,我们称它们为资源(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');

结论:这篇文章是网上的。我照着做了一遍,遇到以下问题:
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中的资源相关推荐

  1. 在 C++Builder 工程里调用 DLL 函数

    调用 Visual C++ DLL 给 C++Builder 程序员提出了一些独特的挑战.在我们试图解决 Visual C++ 生成的 DLL 之前,回顾一下如何调用一个 C++Builder 创建的 ...

  2. C#创建和调用DLL

    一.写在前面 C# 语言是一种简单但功能强大的编程语言,用于编写企业应用程序. C# 语言从C和 C++语言演化而来,在语句.表达式和运算符方面使用了许多 C++ 功能. C# 语言在类型安全性.版本 ...

  3. 天马行空W:在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  4. 在C++中调用DLL中的函数

    1.dll的优点 代码复用是提高软件开发效率的重要途径.一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用.比较常见的例子是各种应用程序框架,ATL.MFC等 ...

  5. 在C++中调用DLL中的函数(2)

    本文转自:http://blog.sina.com.cn/s/blog_53004b4901009h3b.html 应用程序使用DLL可以采用两种方式: 一种是隐式链接,另一种是显式链接.在使用DLL ...

  6. 从零开始使用InnoSteup进行程序打打包以及调用dll中的函数

    本示例涉及: 程序的打包和数字签名 InnoSetup的快速上手 以及一个产品从编译到安装的过程演示 首先,我提供一份InnoSteup的脚本文件,小伙伴们可直接使用这个脚本进行打包(不过得修改一下相 ...

  7. C#调用dll中的函数

    C#调用dll中的函数 文章分类:操作系统 文章来源:http://blog.csdn.net/strmagic/archive/2007/11/02/1863462.aspx 大家在实际工作学习C# ...

  8. 通过GetProcAddress函数动态调用dll中地函数,是否必须通过extern C声明导出函数?(转)...

    通过GetProcAddress函数动态调用dll中的函数,是否必须通过extern "C"声明导出函数? [已结贴,结贴人:darongtou] 如题,网上搜了N多资料,一直找不 ...

  9. Qt调用dll中的功能函数

    http://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810239.html 声明: 事先我已经自己动手写了一个简单的dll文件(myDLL.dll ...

最新文章

  1. 云计算登顶之后,亚马逊人工智能走上新征程
  2. 环境变量太大解决方法
  3. RHEL6.3配置文件共享(5) Samba服务之三
  4. iOS下KVO使用过程中的陷阱
  5. Spring整合mybatis中的sqlSession是如何做到线程隔离的?
  6. Oracle 10g RAC 升级(CPU Update)之--升级CRS
  7. 关于Socket通信服务的心跳包(转) -感觉系统
  8. 开环控制的两轮差速驱动小车_汽车的差速器、差速锁有什么不同?很多车主容易把它俩搞混...
  9. 从头搭建drbd+openfiler+corosync (二)
  10. FreeSwitch会议Banner功能调用流程
  11. 奥鹏刷分软件_【中国大学mooc刷课系统和奥鹏在线作业自动答案软件哪个好用】中国大学mooc刷课系统和奥鹏在线作业自动答案软件对比-ZOL下载...
  12. 网络岗7 97用户破解图片
  13. 前端学习之html特殊符号
  14. android调整图片大小,Android图像调整大小并保留EXIF数据(方向,旋转等)
  15. oppo小布机器人_OPPO小布助手2.0强势来袭 三大版块迎来重大升级
  16. 关于FBG、TFBG、LPG、45°TFBG、EX-45°TFBG
  17. 岁月温柔-20 妈妈在省医院第一天
  18. 【特征工程】特征工程技术与方法
  19. 每天都在“刷脸”,真的安全吗?
  20. 12月行业政策丨紧握十四五规划,实现科技创新

热门文章

  1. LBS推荐系统的设计方法
  2. 实战Nginx与PHP(FastCGI)的安装、配置与优化
  3. 优雅地提高 React 的表单页面的开发效率
  4. PHP 使用POST 获取不到部分数据问题
  5. 极简设计如何实现(一)
  6. Android 学习之pull解析Xml
  7. linux服务之nagios
  8. outlook地址薄导入到FOXMAIL
  9. 常用几种数据库连接字符串
  10. 《孙子兵法》十三篇注译(15--结束语)