如何将资源嵌入静态库






4.95/5 (16投票s)
静态库如何嵌入资源和其他数据,以便任何应用程序(甚至是基于控制台的应用程序)都可以使用它们。
另请参阅我的 GitHub 仓库。
引言
起初我需要发布一个静态库作为产品,并在其中包含一些资源。 这通常是不可能的,因为使用此类静态库的程序将使用自己的资源。 我发布了一个问题(在找到这个解决方案后我回答了)。 我意识到这个解决方案值得一篇带有源代码的文章。 我还在Stack Overflow上提出了关于这种可能性的问题。
在另一种情况下,我希望我的静态库嵌入另一种任何类型的文件(可以是可执行文件、DLL、照片、文档等),并在运行时提取它。几个代码示例
该源包含一个静态库项目("MH_EmbedDataLib
")和一个测试控制台应用程序("ConsoleApp
")。 当然,如果它适用于无 GUI 的控制台应用程序,它也将适用于任何其他类型,即 Win32、MFC 等。
MH_EmbedDataLib 库
MH_EmbedDataLib
库有 2 个主要功能
获取图标
HICON GetIcon()
{
DWORD dwTmp;
int offset;
HANDLE hFile;
HICON hIcon = NULL;
offset = LookupIconIdFromDirectoryEx(s_byIconData, TRUE, 0, 0, LR_DEFAULTCOLOR);
if (offset != 0)
{
hIcon = CreateIconFromResourceEx
(s_byIconData + offset, 0, TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
}
return hIcon;
}
假设您已将要使用的图标转换为BYTE
的静态数组并将其命名为s_byIconData
,则GetIcon
从该静态数据(s_byIconData
)加载该图标。
LookupIconIdFromDirectoryEx函数用于搜索图标或光标数据,以找到最适合当前显示设备的图标或光标。
然后,CreateIconFromResourceEx用于从描述它的资源位创建图标,该资源位由Bin2C
生成。
DisplayMessageWithIcon
void DisplayMessageWithIcon(LPWSTR message)
{
XMSGBOXPARAMS xmb;
//xmb.hInstanceIcon = (HINSTANCE)GetIcon();
xmb.dwOptions |= XMSGBOXPARAMS::RightJustifyButtons;
xmb.crBackground = RGB(255, 255, 255);
xmb.crText = RGB(10, 135, 180);
xmb.nIdIcon = 101;
xmb.nTimeoutSeconds = 5;
XMessageBox(NULL,
message,
L"Code Project article by Michael Haephrati",
MB_YESNO, &xmb);
}
此函数显示一个MessageBox
,其中显示封装在s_byIconData
中的图标。
流程
选择您希望使用的照片或图像。 一个名为ICO Convert的网站提供了将大多数图像类型转换为.ico文件的服务。 拥有.ico文件后,打开它以查看转换是否顺利。 然后使用Bin2C将其转换为BYTE
的数组 。 确保您为静态数组使用了正确的名称。 (在本例中,我们使用了s_byIconData
)。 然后,MessageBox
将显示它。 为了本文的目的,我使用了尼亚加拉瀑布(当然是加拿大一侧……)的照片,如下所示。
结果不是很好,但证明了这个概念。
XMessageBox
本文代码中使用的精美消息框由Hans Dietrich开发。
从数组创建临时文件
服务于本文目的的另一个示例是使用 Bin2C 创建的同一个数组,用于在运行时临时生成文件。bool Array2TempFile(char *arr, size_t len,WCHAR *file)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE, // open for writing
FILE_SHARE_WRITE, // share for writing
NULL, // default security
CREATE_ALWAYS, // create new file only
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
// normal file archive and impersonate client
NULL); // no attr. template
DWORD bytes;
if (hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, &arr[0], len, &bytes, NULL);
CloseHandle(hFile);
return true;
}
return false;
}
我使用此函数从静态库中提取和安装内核驱动程序。 这是一个此类用法的示例。
INF_PATH和
SYS_PATH是预定义的。
int len; // Extract .inf file for x86 Win 10 len = (int)sizeof(sgdrv86_10_inf); Array2TempFile((char *)&sgdrv64_10_inf[0], len, INF_PATH); // Extract .sys file for x86 Win 10 len = (int)sizeof(sgdrv86_10_sys); Array2TempFile((char *)&sgdrv86_10_sys[0], len, SYS_PATH);