Trying to load a bitmap using ImageList_LoadImage but fails with ErrorCode 1814 - Could not find resource
However these lines preceeding it work
HRSRC myResource = FindResource(NULL, MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
auto imageResDataHandle = LoadResource(NULL, myResource);
TRACE("Error %d", GetLastError()); // All OK
auto hImageList = ::ImageList_LoadImage(NULL, MAKEINTRESOURCE(IDB_BITMAP1), 16, 2, CLR_DEFAULT, IMAGE_BITMAP, 0);
TRACE("Error %d", GetLastError()); // Fail, error code 1814
The file is a 32x16 bmp file saved as "bitmap1.bmp" as a resource created within VS.
As it finds the resource in the first line, I think it's compiled into the binary fine.
I assume that with this call
auto hImageList = ::ImageList_LoadImage(NULL, MAKEINTRESOURCE(IDB_BITMAP1), 16, 2, CLR_DEFAULT, IMAGE_BITMAP, 0);
You're assuming that the NULL value for the HINSTANCE will make the function search through the current module. This is not so for this function, according to the documentation.
To get the HINSTANCE of the current module, you can call GetModuleHandle(NULL). Replace the NULL in your code with that call and it should work.
auto hImageList = ::ImageList_LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_BITMAP1), 16, 2, CLR_DEFAULT, IMAGE_BITMAP, 0);
Related
I'm trying to load a bitmap from resource instead of a file location. I'm using visual stuidos and I have imported the same bitmap into the rc. The LoadImage returns a NULL when I try with the resource version. Is my syntax wrong? or am I missing additional steps? Please point me in the right direction I'm trying to learn. Thanks in advance.
HBITMAP mhbitmap;
// Loading from a file works
mhbitmap = (HBITMAP)LoadImage(NULL, L"sblue.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
mpiccontrol.SetBitmap(mhbitmap);
if (mhbitmap == NULL) {
MessageBox(L"null", L"from file", NULL);
}
The load from file version shows the image, but the resource version does not show the image.
mpiccontrol.SetBitmap(mhbitmap);
// My attempt at loading from resource
mhbitmap = (HBITMAP)LoadImage(NULL, MAKEINTRESOURCE("IDB_BITMAP1"), IMAGE_BITMAP, 0, 0, 0);
if (mhbitmap == NULL) {
MessageBox(L"null", L"from rc", NULL);
}
mpiccontrol.SetBitmap(mhbitmap);
MAKEINTRESOURCE macro accepts integer resource id so it should be MAKEINTRESOURCE(IDB_BITMAP1) where IDB_BITMAP1 is a resource identifier macro (probably from resource.h). You should also call GetLastError to figure out failure reason.
I'm having issues displaying a bitmap on the screen. When I complile and run its not displaying anything so I tried debugging step by step and found that the below code is the issue.
HBITMAP hbm = (HBITMAP)LoadImage(hInstance,
"C:\\Users\\Jemma\\Desktop\\Maze Game\\Assets\\TILE_01.bmp",
IMAGE_BITMAP,
SWidth, SHeight,
LR_LOADFROMFILE | LR_CREATEDIBSECTION);
if (hbm == NULL || m_Surface == NULL)
{
DWORD lastError = GetLastError();
return 1;
}
When I get to this function under autos first it says hbm=0xcccccccc{unused=???} (I'm assuming it's due to not being initialised as this comes up when I get to the line so I haven't stepped into it at this point - Just thought I'd put it in just incase) after I've stepped into this line it says hbm = NULL, and the GetLastError function returns 0 which I've read means function was successful. I've tried passing NULL instead of hInstance, I've tried passing the filename in as LPCSTR szFileName -- I declared it as LPCSTR szFileName("C:\Users\Jemma\Desktop\Maze Game\Assets\TILE_01.bmp").
Absolutely no idea what to try next. Any help on this would be greatly appreciated.
First of all, make sure that your image is real bmp file and can be opened with image viewer. Then try this to load that HBITMAP using LoadImage:
const char* filename = "C:\\Users\\Jemma\\Desktop\\Maze Game\\Assets\\TILE_01.bmp";
HBITMAP bmp = (HBITMAP)LoadImage(NULL, filename,
IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
if (hbm == NULL)
{
DWORD lastError = GetLastError();
return 1;
}
Note, you need to use 0, 0 for sizes when you use LR_DEFAULTSIZE, also, when loading from file you need to use LR_LOADFROMFILE. All of these are mentioned in documentation of LoadImage function.
When stepping through with debugger if you get something unexpected you need to check GetLastError. If you are stepping through with VS debugger, you can simply add #err in watch window and you'll always see the last error without changing your code. You can also add it as #err,hr and it will show you readable description of the error that happened.
const char* filename = "C:\\Users\\Jemma\\Desktop\\Maze Game\\Assets\\TILE_01.bmp";
HBITMAP bmp = (HBITMAP)LoadImage(NULL, filename,
IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
if (bmp== NULL)
{
DWORD lastError = GetLastError();
return 1;
}
I am using the same code as above mentioned but LoadImage() is returning NULL and getting lasterror =2 , even i am sure file is already there from belowcode:
string filePath = "D:\\ACC_car_Ego.bmp";
if (boost::filesystem::exists(filePath)) // does filePath actually exist?
DWORD lastError = GetLastError();
else
DWORD lastError1 = GetLastError();
I have a bitmap class that has a load function for loading the bitmap from either file path or resource ID. This part works fine.
void GtBitmap::Load()
{
LPTSTR szFileName;
szFileName = (LPTSTR)m_strPath.c_str();
// Check for valid .BMP file path
if (m_strPath.size() > 0)
{
// Open .BMP file
m_pFile = fopen(m_strPath.c_str(), ("rb"));
if (m_pFile != NULL)
{
m_hBitmap = (HBITMAP)LoadImage (GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_SHARED | LR_LOADFROMFILE);
GetObject(m_hBitmap, sizeof(m_bmap), &m_bmap);
int i = 1;
}
}
else if (m_intResourceID != 0)
{
m_hBitmap = (HBITMAP)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(m_intResourceID), IMAGE_BITMAP, 0, 0, LR_SHARED);
GetObject(m_hBitmap, sizeof(m_bmap), &m_bmap);
int i = 1;
}
}
However, when I try to render it in my code block, the SelectObject returns null. Here is the code for that section of the painter class.
void GtPainterGDI::GtDrawBitmap(GtRectI & target, GtBitmap & bitmap, bool blnOffset)
{
GtCanvas topCv = m_arrCanvas.back();
HDC hdcMem = CreateCompatibleDC(topCv.m_hdcParent);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.m_hBitmap);
DWORD lastError = GetLastError();
bool success = BitBlt(hdcMem, target.GetLeft(), target.GetTop(),
target.Width(), target.Height(), hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, bitmap.m_hBitmap);
DeleteDC(hdcMem);
};
The SelectObject() returns null and the image is not drawn. I can only get the image to show up if I use a LoadImage() in that paint function. However I don't want to load the image every time I want to paint. I should be able to load the image once in the Load function or constructor of the bitmap, then use the handle in the paint function.
If anyone could please provide an example of loading an image in a constructor and then painting it elsewhere in the codes WM_PAINT or equivalent painting function I would appreciate it. The code is a new version of the GT graphical user interface library. I plan on posting a new version on codeproject in the next few days or so. I have to do some cleanup first...
Thanks in advance.
HINSTANCE parameter in LoadImage should be NULL when loading the image from file. Use GetModuleHandle(NULL) only when loading from resource.
m_hBitmap = (HBITMAP)LoadImage(NULL, m_strPath.c_str(),
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (!m_hBitmap)
{
//report error
}
Also LR_SHARED is not necessary here.
When testing for file's exist, you can use std::ifstream. Example:
#include <fstream>
...
bool test = std::ifstream(m_strPath).good();
This will test for file and close the file handle right away.
Make sure to select hbmOld before deleting hdcMem:
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, bitmap.m_hBitmap);
BitBlt(...)
//SelectObject(hdcMem, bitmap.m_hBitmap); <<= remove this
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
I met this problem when writing a minesweeper game. I used bitmap for numbers, mines and blanks. I think I have registered them correctly in the resource file
IDI_0 BITMAP "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\empty.bmp"
IDI_1 BITMAP "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\1.bmp"
IDI_2 BITMAP "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\2.bmp"
IDI_3 BITMAP "D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\3.bmp"
and the header file
#define IDI_0 200
#define IDI_1 201
#define IDI_2 202
#define IDI_3 203
and I load them like this
h0 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_0), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h1 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_1), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h2 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_2), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
h3 = (HBITMAP)LoadImage(hInst, MAKEINTRESOURCE(IDI_3), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
I also checked the exe file with resourcehacker and found all bitmaps in there.
What I do not understand is that only sometimes (~50%) when I run the game pops either
Error 1812: The specified image file did not contain a resource section.
or
Error 1813: The specified resource type cannot be found.
But if I load them from files like this
h0 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\empty.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h1 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\1.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h2 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\2.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
h3 = (HBITMAP)LoadImage(NULL, L"D:\\User\\Mark\\Documents\\C++\\win32\\MineSweeper\\MineSweeper\\3.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
everything works fine.
Any thoughts or advice would be appreciated. Thanks!
I'd personally consider using GDI+ to load your images. You can still load from a disk-file or from the resources section of your application. It also gives you the advantage of access to all the image formats that windows supports natively (BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF)
To use it, you just have to initialize GDI+ first and then perform a shutdown before program exit.
Here's the function I use for loading from disk-file:
// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImageFile(wchar_t *filename)
{
HBITMAP result = NULL;
Bitmap bitmap(filename, false);
bitmap.GetHBITMAP(0, &result);
return result;
}
If we have a resource-file that contains the following:
IDR_PNG1 RT_PNG ".\\girl.png"
IDR_JPG1 RT_JPG ".\\rssLogo.jpg"
Then we can load each of the images thusly:
HBITMAP png = loadImgResource(IDR_PNG1, L"RT_PNG");
HBITMAP jpg = loadImgResource(IDR_JPG1, L"RT_JPG");
Also the two functions I use to load from a resource. You'll note that I've hardcoded in GetModuleHandle(0) in the 2nd function - change this if you want to read from any module (dll, exe) other than the current one.
// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP loadImgResource(wchar_t *pName, wchar_t *pType, HMODULE hInst)
{
Gdiplus::Bitmap *m_pBitmap;
HBITMAP result=NULL;
HRSRC hResource = FindResource(hInst, pName, pType);
if (!hResource)
return NULL;
DWORD imgSize = SizeofResource(hInst, hResource);
if (!imgSize)
return NULL;
const void *pResourceData = LockResource(LoadResource(hInst, hResource));
if (!pResourceData)
return NULL;
HANDLE m_hBuffer = GlobalAlloc(GMEM_MOVEABLE, imgSize);
if (m_hBuffer)
{
void* pBuffer = GlobalLock(m_hBuffer);
if (pBuffer)
{
CopyMemory(pBuffer, pResourceData, imgSize);
IStream* pStream = NULL;
if (CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK)
{
m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
pStream->Release();
if (m_pBitmap)
{
if (m_pBitmap->GetLastStatus() == Gdiplus::Ok)
{
m_pBitmap->GetHBITMAP(0, &result);
delete m_pBitmap;
}
}
}
GlobalUnlock(m_hBuffer);
}
GlobalFree(m_hBuffer);
}
return result;
}
HBITMAP loadImgResource(WORD resNum, LPWSTR pType)
{
return loadImgResource(MAKEINTRESOURCE(resNum), pType, GetModuleHandle(0));//hInst);
}
Sorry if this is duplicate but I can't find answer elsewhere. I am simply trying to load an image during runtime using the LoadImage() function of WINAPI. I receive the error code(8) which indicates that there is not enough storage space(error codes found here).
the file is relatively small(2.5kb) so I wonder if there is problem with my code:
void OnCreate()
{
...
HBITMAP hbmDeck = (HBITMAP)LoadImage(hInstance, L"standard.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
DWORD err = GetLastError();
HBITMAP hbmT = SelectBitmap(hdc, hbmDeck);
if(!hbmT)
{
MessageBox(NULL, L"Failed to LoadImage - 'hbmDeck'", L"OnCreate()", MB_OK);
PostMessage(hwnd, WM_DESTROY, NULL, NULL);
}
...
}
Yeah, some of the API return error codes are a bit cryptic and don't fit the error.
The file you are trying to load "standard.bmp" is a file on the disk NOT in the resource section right? Well to load a file from the disk, the fist parameter of LoadImage (hInst) has to be NULL and the fuLoad flag needs to include LR_LOADFROMFILE which you correctly have.