VCpp将资源文件编译进程序并在运行时释放到文件

⌚Time: 2023-10-13 00:38:33

👨‍💻Author: Jack Ge

使用VS将资源编译进程序,在运行时释放。

通过VS导入资源

切换到资源视图,右键项目,添加,资源,点击导入,选择要添加的资源,如一个文本a.txt

自己写一个资源类型名,定义了一个txt类型

资源添加到分类"txt"

FindResource确定指定模块中具有指定类型和名称的资源的位置。


HRSRC FindResourceA(

  [in, optional] HMODULE hModule,

  [in]           LPCSTR  lpName,

  [in]           LPCSTR  lpType

);

参数

[in, optional] hModule

类型: HMODULE

模块的句柄,其可移植可执行文件或随附的 MUI 文件包含资源。 如果此参数为 NULL,则该函数将搜索用于创建当前进程的模块。

[in] lpName

类型: LPCTSTR

资源的名称。 或者,此参数可以是 MAKEINTRESOURCE (ID) ,其中 ID 是资源的整数标识符,而不是指针。 有关详细信息,请参阅下面的“备注”部分。

[in] lpType

类型: LPCTSTR

资源类型。 或者,此参数可以是 MAKEINTRESOURCE (ID) ,其中 ID 是给定资源类型的整数标识符,而不是指针。 有关标准资源类型,请参阅 资源类型。 有关详细信息,请参阅下面的“备注”部分。

返回值

类型: HRSRC

如果函数成功,则返回值是指定资源的信息块的句柄。 若要获取资源的句柄,请将此句柄传递给 LoadResource 函数。

如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

获取资源


HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(101), L"txt");

FindResource第二个参数,MAKEINTRESOURCE(101),是导入的txt资源IDR_TXT1定义的无符号整数值,可以在resource.h中看到它的定义


#define IDR_TXT1                        101

#define IDB_BITMAP1                     102

或者,可以在代码中直接包含resource.h,填写资源ID


#include "resource.h"

...

HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(IDR_TXT1), L"txt");

FindResource的第三个参数,是自定义的分类名称,前面定义的"txt"类型。如果是vs中的资源类型,前面要加RT_,具体如下:


#define RT_CURSOR           MAKEINTRESOURCE(1)

#define RT_BITMAP           MAKEINTRESOURCE(2)

#define RT_ICON             MAKEINTRESOURCE(3)

#define RT_MENU             MAKEINTRESOURCE(4)

#define RT_DIALOG           MAKEINTRESOURCE(5)

#define RT_STRING           MAKEINTRESOURCE(6)

#define RT_FONTDIR          MAKEINTRESOURCE(7)

#define RT_FONT             MAKEINTRESOURCE(8)

#define RT_ACCELERATOR      MAKEINTRESOURCE(9)

#define RT_RCDATA           MAKEINTRESOURCE(10)

#define RT_MESSAGETABLE     MAKEINTRESOURCE(11)

SizeofResource检索指定资源的大小(以字节为单位)。


DWORD SizeofResource(

  [in, optional] HMODULE hModule,

  [in]           HRSRC   hResInfo

);

LoadResource 函数 (libloaderapi.h)

检索可用于获取指向内存中指定资源第一个字节的指针的句柄。


HGLOBAL LoadResource(

  [in, optional] HMODULE hModule,

  [in]           HRSRC   hResInfo

);

parameters

[in, optional] hModule

类型: HMODULE

其可执行文件包含资源的模块的句柄。 如果 hModule 为 NULL,则系统从用于创建当前进程的模块加载资源。

[in] hResInfo

类型: HRSRC

要加载的资源的句柄。 此句柄由 FindResource 或 FindResourceEx 函数返回。

返回值

类型: HGLOBAL

如果函数成功,则返回值是与资源关联的数据的句柄。

如果函数失败,则返回值为 NULL。 要获得更多的错误信息,请调用 GetLastError。

LockResource 函数 (libloaderapi.h)

检索指向内存中指定资源的指针。


LPVOID LockResource(

  [in] HGLOBAL hResData

);

parameters

[in] hResData

类型: HGLOBAL

要访问的资源的句柄。 LoadResource 函数返回此句柄。 请注意,此参数作为 HGLOBAL 变量列出,只是为了向后兼容。 不要将任何值作为参数传递,而不是 LoadResource 函数的成功返回值。

返回值

类型: LPVOID

如果加载的资源可用,则返回值是指向资源第一个字节的指针;否则为 NULL。

注解

LockResource 返回的指针在卸载包含资源的模块之前有效。 无需解锁资源,因为当创建资源的进程终止时,系统会自动将其删除。

请勿尝试使用 FindResourceA 函数或 FindResourceExA 函数返回的句柄来锁定资源。 此类句柄指向随机数据。

注意

LockResource 实际上不会锁定内存;它仅用于获取指向包含资源数据的内存的指针。 函数的名称来自 Windows XP 之前的版本,当时它用于锁定 LoadResource 分配的全局内存块。

使用c语言的fwrite释放资源到文件


size_t fwrite(

   const void *buffer,

   size_t size,

   size_t count,

   FILE *stream

);

参数

buffer

指向要写入的数据的指针。

size

项大小(以字节为单位)。

count

要写入的项的最大数量。

stream

指向 FILE 结构的指针。

返回值

fwrite 返回函数写入的完整项数,如果发生错误,该数目可能小于 count 。 此外,如果发生错误,则无法确定文件位置指示器。 stream如果 或 buffer 是空指针,或者如果在 Unicode 模式下指定了要写入的奇数字节数,则该函数将调用无效的参数处理程序,如参数验证中所述。 如果允许执行继续,则该函数将 errno 设置为 EINVAL 并返回 0

注解

fwrite 函数最多将 count 个项从 size 写入到输出 buffer,每个项的长度为 stream。 如果存在一个) 与 (关联的 stream 文件指针将按写入字节 fwrite 数递增。 如果在文本模式下打开 stream,则会将每个换行符替换为回车换行符对。 该替换不会影响返回值。

当在 Unicode 转换模式下打开 stream 时(例如,通过调用 stream 并使用包含 fopen、ccs=UNICODE 或 ccs=UTF-16LE 的模式参数打开 ccs=UTF-8 时,或者通过使用 _setmode 和包含 _O_WTEXT、_O_U16TEXT 或 _O_U8TEXT 的模式参数将该模式更改为 Unicode 转换模式时),会将 buffer 解释为指向包含 UTF-16 数据的 wchar_t 数组的指针。 尝试在此模式下写入奇数个字节会导致参数验证错误。

由于此函数锁定调用线程,因此它是线程安全的。 有关非锁定版本,请参阅 _fwrite_nolock。

默认情况下,此函数的全局状态范围限定为应用程序。 若要更改此行为,请参阅 CRT 中的全局状态。

测试代码


#define WIN32_LEAN_AND_MEAN     // 从 Windows 头中排除极少使用的资料

#include <tchar.h>

#include <Windows.h>

#include <stdio.h>



int _tmain(int argc, _TCHAR* argv[])

{

    HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(101), L"txt");//找到资源

    DWORD dwSize = SizeofResource(NULL, hResource);//获取资源大小

    HGLOBAL hGlobal = LoadResource(NULL, hResource);//加载资源

    LPVOID lpVoid = LockResource(hGlobal);//获取资源指针



    FILE *fp = fopen("a.txt","wb");//二进制方式写入文件

    if(fp == NULL){

        puts("error");

        return 0;

    }

    fwrite(lpVoid,1,dwSize,fp);//写入文件

    

    fclose(fp);//关闭文件

    FreeResource(hGlobal);//释放资源

    return 0;

}




程序运行后会释放a.txt到运行目录