HBITMAP hbm=LoadImage function returns NULL - c++

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();

Related

Loading a bmp from resource

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.

ImageList_LoadImage doesn't find bitmap

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);

SelectObject returns NULL with hbitmap created in constructor

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);

Win32 LoadImage() from File Error

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.

Windows 7 and ScreenShot.cpp GDI+ PNG problemo

was using XP without issue for a long time. switched to 7 and trying to capture screenshots with my previously functioning code no longer works. simple concept and relatively generic code...just find the window that i call and save it as a .png. any ideas what might make this bad boy run again? can't debug with my current setup, but it makes it all the way and spits out the error message after bmp->save(...) ...couldn't save image file. edit: also a file does get created/saved, but it is blank and not written to. perhaps the bitmap encoding or GDI is screwed up?
bool CScreenShot::Snap(CString wintitle, CString file, CString& ermsg)
{
ermsg = ""; // no error message
// create screen shot bitmap
EnumWinProcStruct prm = {0, (LPSTR)(LPCTSTR)wintitle, 0};
// Find the descriptor of the window with the caption wintitle
EnumDesktopWindows(0, EnumWindowsProc, (LPARAM)&prm);
if(!prm.hwnd)
{
ermsg.Format("couldn't find window \"%s\"", wintitle);
return false;
}
// Make the window the topmost window
SetWindowPos(prm.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
Sleep(300);
// Get device context for the top-level window and client rect
HDC hDC = GetDC(prm.hwnd);
RECT rc;
GetClientRect(prm.hwnd, &rc);
HDC memDC = CreateCompatibleDC(hDC);
// Set the size and color depth for the screen shot image
BITMAPINFO bmpInfo;
memset(&bmpInfo, 0, sizeof(bmpInfo));
bmpInfo.bmiHeader.biSize = sizeof(bmpInfo.bmiHeader);
bmpInfo.bmiHeader.biWidth = rc.right - rc.left;
bmpInfo.bmiHeader.biHeight = rc.bottom - rc.top;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 24;
bmpInfo.bmiHeader.biCompression = BI_RGB;
bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth * bmpInfo.bmiHeader.biHeight * 3;
// Create memory buffer and perform a bit-block transfer of the color data from the window to the memory
LPVOID addr;
HBITMAP memBM = CreateDIBSection(memDC, &bmpInfo, DIB_RGB_COLORS, &addr, 0, 0);
HGDIOBJ stdBM = SelectObject(memDC, memBM);
BOOL OK = BitBlt(memDC, 0, 0, bmpInfo.bmiHeader.biWidth, bmpInfo.bmiHeader.biHeight, hDC, 0, 0, SRCCOPY);
ReleaseDC(prm.hwnd, hDC);
SetWindowPos(prm.hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
if(GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL) != Ok)
{
ermsg.Format("couldn't start GDI+");
return false;
}
// Create a Bitmap object for work with images defined by pixel data from the GDI HBitmap and the GDI HPalette.
Bitmap* bmp = ::new Bitmap(memBM, DIB_RGB_COLORS);
SelectObject(memDC, stdBM);
DeleteObject(memBM);
DeleteDC(memDC);
// Find the encoder for "image/png" mime type
CLSID encoderClsid;
EncoderParameters encoderParameters;
GetEncoderClsid(L"image/png", &encoderClsid);
encoderParameters.Count = 0;
// Convert file name to Unicode (wide-char) string.
WCHAR fn[_MAX_PATH];
MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED, file, file.GetLength() + 1, fn, _MAX_PATH);
// Save the screen shot into the specified file using image encoder with the mime style "image/png"
if(bmp->Save(fn, &encoderClsid, &encoderParameters) != Ok)
{
ermsg.Format("couldn't save image file \"%s\"", file);
return false;
}
::delete bmp;
GdiplusShutdown(gdiplusToken);
return true;
}
The error message implies that you're trying to save the file to a folder that you don't have permission to write to. Many folders such as Program Files are now protected. Since you didn't include the path in your sample code I'm unable to determine if this is the actual problem.
Edit: Another possibility is that the Bitmap is improperly constructed which causes the Save to fail. The second parameter to the constructor is supposed to be a handle to a palette, I think DIB_RGB_COLORS would be invalid here and you should use NULL. Also there are a couple of caveats noted in the Microsoft documentation and perhaps the different OS versions react differently when you break the rules:
You are responsible for deleting the GDI bitmap and the GDI palette. However, you should not delete the GDI bitmap or the GDI palette until after the GDI+ Bitmap::Bitmap object is deleted or goes out of scope.
Do not pass to the GDI+ Bitmap::Bitmap constructor a GDI bitmap or a GDI palette that is currently (or was previously) selected into a device context.
win7 won't accept encoderParameters.Count == 0 for some reason. Set that == 1 and you should be all set.
you probably could also just remove that parameter from Save() (overloaded)