See also my GitHub Repo.
Introduction
It started with a need to release a Static library as a product and include some resources in it. That is usually impossible since a program that uses such Static library will use its own resources. I posted a question (which I answered after finding this solution). I realized that this solution deserves an article with source code. I have also posted a question about that possibility in Stack Overflow.
In another occasion I wanted my Static library to embed another file of any kind (can be an executable, DLL, photo, documents, etc.) and extract it during run-time.
Several Code Examples
The source consists of a Static Library project ("MH_EmbedDataLib
") and a test Console application ("ConsoleApp
"). Of course, if it works with a GUIless Console application, it will work with any other type, i.e., Win32, MFC, etc.
The MH_EmbedDataLib Library
The MH_EmbedDataLib
library has 2 main functions:
Get Icon
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;
}
Provided that you converted an icon you wish to use into a static array of BYTE
and named it s_byIconData
, GetIcon
loads the icon from this static data (s_byIconData
).
The LookupIconIdFromDirectoryEx function is used to search through icon or cursor data for the icon or cursor that best fits the current display device.
Then CreateIconFromResourceEx is used to create the icon from resource bits describing it, generated by Bin2C
.
DisplayMessageWithIcon
void DisplayMessageWithIcon(LPWSTR message)
{
XMSGBOXPARAMS xmb;
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);
}
This function displays a MessageBox
showing the icon encapsulated in s_byIconData
.
The Process
Select a photo you wish to use, or an image. A web site named ICO Convert provides the service of converting most image types into an .ico file. After you have an .ico file, open it to see that the conversion went well. Then convert it into an array of BYTE
using Bin2C. Make sure you use the correct name for the static array. (in this case, we used s_byIconData
). Then the MessageBox
will display it. For the purpose of this article, I used a photo from the Nigara Falls (Canadian side of course...) shown below.
The result isn't great but demonstrate this concept.
XMessageBox
The fancy Message Box used in the code of the article was developed by Hans Dietrich.
Creating Ad-Hoc Files from an Array
Another example that serves the purpose of this article is using the same array created by Bin2C for Ad-Hoc generation of a file during run-time.
bool Array2TempFile(char *arr, size_t len,WCHAR *file)
{
HANDLE hFile = CreateFile(file, GENERIC_WRITE,
FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE | SECURITY_IMPERSONATION,
NULL);
DWORD bytes;
if (hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, &arr[0], len, &bytes, NULL);
CloseHandle(hFile);
return true;
}
return false;
}
I used this function to extract and install Kernel drivers from a Static library. Here is an example of such use.
INF_PATH
and
SYS_PATH
are predefined.
int len;
len = (int)sizeof(sgdrv86_10_inf);
Array2TempFile((char *)&sgdrv64_10_inf[0], len, INF_PATH);
len = (int)sizeof(sgdrv86_10_sys);
Array2TempFile((char *)&sgdrv86_10_sys[0], len, SYS_PATH);