用到的相关API:
FineResource:查找一个资源。我们是把相关要生成的文件载入,就是用这个函数来确定其资源的位置。
SizeofResource:获得资源的尺寸。
LoadResource:装载资源,装入到内存中。
LockResource:锁定资源,在内存中锁定。
好了,现在在VC的工程中载入这个文件吧。首先,我们把***.exe或者***.mid该成***.bin二进制文件,在资源文件上点击右键,选择Import(导入)。这里我们为自定义资源类型,即Custom Resource Type,Resource type为读者兴趣随便填写,这里用MyRes,资源名称用IDR_MyRes。
好了,现在就可以写一个函数进行文件的生成了:
BOOL Create()
{
HRSRC hResInfo;
HGLOBAL hResData;
DWORD dwSize, dwWritten;
HANDLE hFile;
//开始所需的资源
hResInfo = FineResource(NULL,MAKEINTRESOURCE(IDR_MyRes),"MyRes");
if(hResInfo == NULL)
return FALSE;
//获得资源尺寸
dwSize = SizeofResource(NULL,hResInfo);
//装载
hResData = LoadResource(NULL,hResInfo);
if(hResData == NULL)
return FALSE;
//最重要的地方,写文件
hFile = CreateFile("c:\\MyResG.exe",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if(hFile == NULL)
return FALSE;
WriteFile(hFile,(LPCVOID)LockResource(hResData),dwSize,&dwWritten,NULL);
CloseHandle(hFile);
return TRUE;
}
用这个函数就可以把资源文件的东西拖出来了,哈哈。完工
midiConnect 将指定的MIDI输入设备连接到输出设备
midiDisconnect 断开MIDI输入设备和输出设备的连接
midiInAddBuffer 向指定的音乐仪器数字接口的输入设备增加一个缓冲区
midiInClose 关闭指定的音乐仪器数字接口的输入设备
midiInGetDveCaps 查询指定的音乐仪器数字接口的输入设备,以确定其性能
midiInGetErrorText 检取有关音乐仪器数字接口的输入设备指定错误的文本说明
midiInGetID 获得一个音乐一起数字接口的输入设备的标识符
midiInGetNumDevs 检取系统中音乐仪器数字接口的输入设备的数量
midiInMessage 向指定的音乐仪器数字接口的输入设备驱动器发送一条消息
midiInOpen 打开指定的音乐仪器数字接口的输入设备
midiInPrepareHeader 为音乐仪器数字接口的输入设备准备一个缓冲区
midiInReset 在给定的MIDI输入设备上输入,并将所有挂起的输入缓冲区标记为已执行的
midiInStart 启动在指定的音乐仪器数字接口的输入设备上的输入
midiInStop 停止在给定的音乐仪器数字接口的输入设备上的输入
midiInUnprepareHeader 消除由midiInPrepareHeader函数完成的准备
midiOutCacheDrumPatches 请求内部的一个MIDI合成设备预装指定的基于键的击打音色集
midiOutCachePatches 请求内部的音乐仪器数字接口的合成设备预装指定的音色集
midiOutClose 关闭指定的音乐仪器数字接口的输出设备
midiOutGetDevCaps 查询指定的音乐仪器数字接口的输出设备,以确定其性能
midiOutGetErrorText 检取有关MIDI输出设备指定采取的文本说明
midiOutGetID 检取指定的MIDI输出设备的标识符
midiOutGetNumDevs 检取系统中存在的MIDI输出设备的数量
midiOutGetVolume 返回一个MIDI输出设备的当前卷设置
midiOutLongMsg 向指定的MIDI输出设备发送一条系统专用的MIDI消息
midiOutMessage 向一MIDI输出设备驱动器发送一条消息
midiOutOpen 打开指定的MIDI输出设备进行回放
midiOutPrepareHeader 为MIDI输出设备准备一个缓冲区
midiOutReset 为指定的MIDI输出设备关闭所有MIDI通道上的所有标志
midiOutSetVolume 设置一个MIDI输出设备的卷
midiOutShortMsg 向指定的MIDI输出设备发送一条短MIDI消息
midiOutUnprepareHeader 清除由midiOutPrepareHeader函数完成的准备
midiStreamClose 关闭一个打开的MIDI流
midiStreamOpen 为输出,打开一个MIDI流
midiStreamOut 在MIDI输出设备上播放或排队一个MIDI数据流
midiStreamPause 暂停一个MIDI流的播放
midiStreamPosition 在一个MIDI流中检取当前位置
midiStreamProperty 设置或检取与MIDI输出设备相关MIDI数据流的特性
midiStreamRestart 重新启动一个暂停的MIDI流
midiStreamStop 关掉指定MIDI输出设备的所有MIDI通道
Visual C++ 支持十种资源:加速键、位图、光标、对话框、HTML、图标、菜单、串表、工具条和版本信息。
各种资源就是堆数据而已,最终都会被嵌入到EXE文件里的数据区中。需要的时候就通过函数加载到内存中使用。和数据库一样的。各种资源通过ID来唯一确定,就像数据库用关键字来确定一样。不同的资源由于类型不一样可以使用等值的ID,如同数据库里的每一个表单里的关键字值不唯一,但不同表单的关键字是允许一样的。
资源销毁,指的是让资源根据它的使用周期应该及时从内存中被释放,不要加载到内存后就不管了。否则内存越吃越大。
你可以随时创建任何所需要的资源。只需显示ResourceView(资源视图),右击Resources(资源)文件夹,从上下文菜单中选择Insert(插入)。你会看到一个Insert Resource(插入资源)对话框,如上图所示。请注意,它显示出我们已提到过的所有十种资源。还应该看到,有三种创建资源的方式,即使用对话框上的New(新建),Import(导入)或Custom(自定义)按钮。可以在当前程序中使用来自其它工程的资源。例如,可能想在编写的每一个程序中都使用相同的公司徽标。只需右击Resources(资源)文件夹,从上下文菜单选择Import(导入)而不是Insert(插入)。你会看到Open-type(打开类型)对话框。选择包含了想要导入的资源的文件。正是由于这个原因,你会想到把你的大多数资源与程序分离。可惜的是,这种方法只对图标、光标、声波文件以及Visual
Basic窗体文件有用。有几种使用来自其它工程的其它类型资源的方式,如About(关于)对话框。只需简单地为想要共享的资源创建一个分离的RC文件就行了。这在遇到像About对话框这样的资源时很有用。你只要将RC文件添加到工程中,剩下的由Visual C 来处理。另一种共享资源的方法是,将其复制到剪贴板,再在创建了正确类型的空白资源后,将其粘贴到工程中。自定义资源就是自己设计的资源。实际上,它并不适合Visual C 所提供的预定义类型。创建一个自定义资源项目很容易:只要单击Insert Resource(插入资源)对话框上的Custom(自定义)按钮。你会看到包含单个空白的New
CustomResource(新建自定义资源)对话框。简单地输入自定义资源名。这时,Visual C 会产生一个新的文件夹,它含有你提供的自定义资源名和该文件夹内的一个新资源。还要提供实现这个资源所需的二进制数据。
关键字:VC 自定义资源
一、前言
在VC环境中除了我们所常用的Dialog、Menu和Bitmap等标准资源类型之外,它还支持自定义资源类型(Custom Resource),我们自定义的资源类型能做些什么呢?呵呵,用处多多。
默认的皮肤压缩包或语言包。一些支持换肤的软件特别是一些媒体播放器常常有自定义的皮肤文件(你可以尝试将Media Player或千千静听等软件的Skins目录下的文件的扩展名改为.zip,然后使用WinZip打开看一下),但为了防止Skin文件丢失导致软件无法显示,他们常常会在EXE文件中内置一套Skin作为默认的皮肤文件。同样,一些支持多语言的EXE文件中存在默认语言包也是这个道理(当然也可以使用"String Table"资源类型);
做为一些病毒/木马程序的寄生方式。如果不小心执行了带有病毒/木马的程序,它们会在你运行时释放出病毒/木马文件。当然许多病毒是将自身写入PE文件头来实现;
合并EXE与它所需要的DLL文件。出于某些原因程序作者有时可能需要将DLL文件嵌入到可执行的EXE文件中,这可以通过使用自定义资源来实现;
其它需要在程序中播放一个AVI动画等等,都可以通过将二进制的数据文件作为自定义资源加入到可执行文件中来实现;
二、添加
添加资源时选择自定义,IDE会为你生成一个新的二进制资源,然后你就可以将你已经存在的二进制文件作为自定义的资源类型导入到项目中来了。
三、使用
要使用自定义资源,我们可能要用到的几个API函数有FindResource、LoadResource和LockResource等,这里每一个函数的返回值分别作为下一个函数的参数,我来简要介绍一下。
FindResource用来在一个指定的模块中定位所指定的资源:
HRSRC FindResource(
HMODULE hModule, //包含所需资源的模块句柄,如果是程序本身,可以置为NULL
LPCTSTR lpName, //可以是资源名称或资源ID
LPCTSTR lpType //资源类型,在这里也就是我们自己指定的资源类型
);
LoadResource用来将所指定的资源加载到内存当中;
HGLOBAL LoadResource(
HMODULE hModule, //模块句柄,同上
HRSRC hResInfo //需要加载的资源句柄,这里也就是FindResource的返回值
);
LockResource用来锁定内存中的资源数据块,它的返回值也就是我们要使用的直系指向资源数据的内存指针;
LPVOID LockResource(
HGLOBAL hResData //指向内存中要锁定的资源数据块,这里也就是LoadResource的返回值
);
另外我们还需要用SizeofResource来确定资源的尺寸,我们在操作资源时要用到它。在资源使用完毕后我们不需要使用UnlockResource和FreeResource来手动地释放资源,因为它们都是16位Windows遗留下来的,在Win32中,在使用完毕后系统会自动回收。它们的使用很简单,大致上是这个样子的:
BOOL UseCustomResource()
{
//定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可
HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(ITEMID), TEXT("MyType"));
if (NULL == hRsrc)
return FALSE;
//获取资源的大小
DWORD dwSize = SizeofResource(NULL, hRsrc);
if (0 == dwSize)
return FALSE;
//加载资源
HGLOBAL hGlobal = LoadResource(NULL, hRsrc);
if (NULL == hGlobal)
return FALSE;
//锁定资源
LPVOID pBuffer = LockResource(hGlobal);
if (NULL == pBuffer)
return FALSE;
//我们用刚才得到的pBuffer和dwSize来做一些需要的事情。可以直接在内存中使
//用,也可以写入到硬盘文件。这里我们简单的写入到硬盘文件,如果我们的自定
//义资源是作为嵌入DLL来应用,情况可能要复杂一些。
BOOL bRt = FALSE;
FILE* fp = _tfopen(_T("demo.exe"), _T("wb"));
if (fp != NULL)
{
if (dwSize == fwrite(pBuffer, sizeof(char), dwSize, fp))
bRt = TRUE;
fclose(fp);
}
//FreeResource(hGlobal);
return bRt;
}