Reputation: 19207
According to this documentation for LoadFromResource
it states:
Loads an image from a
BITMAP
resource
So, I have this in my code:
rImage.LoadFromResource(AfxFindResourceHandle(), IDB_PNG1);
Doesn't work. I then realised I am using PNG files and not BMP files. I assume this is the reason the resources can't be found.
I have also tried using AfxGetInstanceHandle()
. But that also doesn't work.
Thus, at the moment I am using external PNG files. It works fine. But is there any way to load a PNG from the resources into a CImage
?
The comment provided to me was helpful.
It led me here. So, if I have this method:
IStream* CreateStreamOnResource(LPCTSTR lpName, LPCTSTR lpType)
{
IStream * ipStream = NULL;
HRSRC hrsrc = FindResource(NULL, lpName, lpType);
if (hrsrc == NULL)
goto Return;
DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
if (hglbImage == NULL)
goto Return;
LPVOID pvSourceResourceData = LockResource(hglbImage);
if (pvSourceResourceData == NULL)
goto Return;
HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
if (hgblResourceData == NULL)
goto Return;
LPVOID pvResourceData = GlobalLock(hgblResourceData);
if (pvResourceData == NULL)
goto FreeData;
CopyMemory(pvResourceData, pvSourceResourceData, dwResourceSize);
GlobalUnlock(hgblResourceData);
if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream)))
goto Return;
FreeData:
GlobalFree(hgblResourceData);
Return:
return ipStream;
}
And call it like this:
rImage.Load(CreateStreamOnResource(MAKEINTRESOURCE(IDB_PNG1), _T("PNG")));
Works fine ... Thanks guys.
Based on comment provided. This better now? I see no leaks:
IStream *pStream = CreateStreamOnResource(MAKEINTRESOURCE(uPNGResourceID), _T("PNG"));
if (pStream != nullptr)
{
rImage.Load(pStream);
rImage.SetHasAlphaChannel(true);
pStream->Release();
}
Side note: Do I really need to call SetHasAlphaChannel
if these are my own embedded resources and I know the are transparent 32 bit resources?
Upvotes: 4
Views: 3993
Reputation: 15375
AfxFindResource
LoadResource
GlobalAlloc
CopyMemory
CreateStreamOnHGlobal
CImage::Load(IStream*...)
Or you write your own IStream
implementation that takes a pointer and a size from LoadResource
. Also CSharedFile
is an option.
EDIT: Also the new MFC provides a CPngBitmap
that allows to load a PNG file as a HBITMAP directly from a memory source.
Upvotes: 3
Reputation: 4245
You can load an image from a hardcoded path or from a Stream. To load it from a Stream, use the following code. First, add a function for creating the stream from the resource.
IStream* ZDlg::CreateStreamOnResource(LPCTSTR lpName, LPCTSTR lpType)
{
IStream * ipStream = NULL;
HRSRC hrsrc = FindResource(NULL, lpName, lpType);
if (hrsrc == NULL)
goto Return;
DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
if (hglbImage == NULL)
goto Return;
LPVOID pvSourceResourceData = LockResource(hglbImage);
if (pvSourceResourceData == NULL)
goto Return;
HGLOBAL hgblResourceData = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
if (hgblResourceData == NULL)
goto Return;
LPVOID pvResourceData = GlobalLock(hgblResourceData);
if (pvResourceData == NULL)
goto FreeData;
CopyMemory(pvResourceData, pvSourceResourceData, dwResourceSize);
GlobalUnlock(hgblResourceData);
if (SUCCEEDED(CreateStreamOnHGlobal(hgblResourceData, TRUE, &ipStream)))
goto Return;
FreeData:
GlobalFree(hgblResourceData);
Return:
return ipStream;
}
Then use the function as follow:
pImage = new CImage;
IStream *pStream = CreateStreamOnResource(MAKEINTRESOURCE(IDB_MYIMAGE), _T("PNG"));
if (pStream != nullptr)
{
pImage->Load(pStream);
pImage->SetHasAlphaChannel(true);
pStream->Release();
}
Upvotes: 1