65.9K
CodeProject 正在变化。 阅读更多。
Home

如何将资源嵌入静态库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (16投票s)

2019 年 1 月 22 日

CPOL

2分钟阅读

viewsIcon

22406

downloadIcon

559

静态库如何嵌入资源和其他数据,以便任何应用程序(甚至是基于控制台的应用程序)都可以使用它们。

另请参阅我的 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);
© . All rights reserved.