Win32 application. HBITMAP LoadImage fails to load anything - c++

I'm writing a function that quickly draws an image of a menu for a game I'm making. I'm able to draw the background and text blocks just fine but I'm having trouble creating a bitmap image on the screen
bool menu::drawMenu(PAINTSTRUCT ps)
{
HWND hWnd = GetActiveWindow();
HDC hdc = GetDC(hWnd), hdcMem;
//Draw a new background
HPEN blackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
SelectObject(hdc, blackPen);
SelectObject(hdc, blackBrush);
Rectangle(hdc, 0, 0, 1080, 720);
//insert selection text
TextOut(hdc, 30, 0, L"New Game", 8);
TextOut(hdc, 30, 30, L"Exit Game", 9);
//draw arrow sprite
HBITMAP arrow = (HBITMAP)LoadImage(NULL, L"C:\\Users\\Tim\documents\\visual studio 2013\\Projects\\BoulderBisque\\BoulderBisque\\arrow.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
DWORD lastError = GetLastError();
if (arrow == NULL)
{
TextOut(hdc, 0, 60, L"Image Load Failed", 17);
return false;
}
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem == NULL)
{
TextOut(hdc, 0, 90, L"Memory Creation Failed", 22);
return false;
}
SelectObject(hdcMem, arrow);
BitBlt(hdc, 0, choice * 30, 16, 16, hdcMem, 0, 0, SRCCOPY);
//cleanup
ReleaseDC(hWnd, hdc);
DeleteDC(hdcMem);
return true;
}
As of now arrow is NULL and I get the Load Image Failed textbox.
I am using the relative path of arrow.bmp I also tried using a full path, that didn't work either.
You may have noticed that this function is outside the WndProc. Everything else draws fine.
I tried running it in there too everything but the arrow.bmp loads.
What am I doing wrong to cause arrow.bmp to be NULL? I have other methods I plan to run in similar ways so getting this function to run would really be a big help.
EDIT* Whenever I give the full path name it still fails to load.
Also is this not the appropriate code for SO? This is my first question...
EDIT** The aditional '/'s haven't fixed the issue.
EDIT*** Using GetLastError, I found the error code to be 2, ERROR_FILE_NOT_FOUND

Your early versions of the question checked the return value of LoadImage but then did nothing more. The documentation says this:
If the function fails, the return value is NULL. To get extended error information, call GetLastError.
So, if the function fails, call GetLastError to find out why. When you do so, you obtain the error code ERROR_FILE_NOT_FOUND. Which is pretty conclusive. The filename that you specified does not exist.
Do note that the code in the latest update to the question calls GetLastError unconditionally. That is a mistake, one that is seen all too frequently here on Stack Overflow. The documentation only tells you to call GetLastError when the call to LoadImage fails. If the call to LoadImage succeeds, then the value return by GetLastError is meaningless. Error handling in Win32 is largely handled in the same way as LoadImage does it, but not always. So you have to read the documentation very carefully.
Perhaps instead of
C:\\Users\\Tim\documents\\...
you meant
C:\\Users\\Tim\\documents\\...
OK, now you've got the path right. The call to LoadImage returns NULL, but GetLastError is no longer helpful and returns ERROR_SUCCESS. Which is weird in itself.
I believe that the problem is that your image uses a format that LoadImage does not understand. I took your .bmp file, loaded it in Paint.net and then re-saved it. Once I did that, the re-saved image was loaded successfully.
Rather than trying to load this from a file it would make far more sense to link the image as a resource and load it that way.

I found through experimenting with Gimp, that your .bmp file must have the following attributes in order for it to work:
depth:24bit
"Do not show write color space information" box checked: Gimp export options
If that still doesn't work then try to "unblock" it: File options.

Related

The GDI text display problem (I just use GDI and not use Unity or DirectX)

I am writing a program game and want to show a text on the game's beginning.
I have checked the syntax of the program to guarantee there is no problem.
But the text can't display on the window.
I declare two global variables HDC:
HDC g_hdc, g_mdc;
The first is used to display, the second is used to buffer.
The text display code:
HFONT hFont = CreateFont(45, 0, 0, 0, 0, 0, 0, 0, GB2312_CHARSET, 0, 0, 0, 0, NULL);
SelectObject(g_hdc, hFont);
SetBkMode(g_hdc, TRANSPARENT);
wchar_t text1[] = L"Begin!";
SetTextColor(g_hdc, RGB(50, 255, 50));
TextOut(g_hdc, 0, 0, text1, wcslen(text1));
This code is included in the function init() so the code will be used when the windows create and just use only once.
When I run this program I just got this :
image
You can see the bitmap show correct but the text is not.
Can anyone tell me why?
I find why it can't display. I change the way of get HDC form PaintBegin() to GetDC() then the text begin to display. The PaintBegin() looks like only using when WM_PAINT message be caught.

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

Beginner level code required to display a frame using vfw?

I want to be able to display a captured frame from my webcam using the vfw.h library. I have code which captures a single frame and saves it to a Bitmap file. However, I do not know how to then display this Bitmap file within a window. I only know how to display the live video feed within a window. Apologies in advance for the likely obviousness of this question but I have very little experience in this type of programming. Can anyone advise me on how to display the captured frame in another window, for further manipulation, i.e. examples of how to use the relevant macros? I am using C++ in Visual Studio.
ShowWindow(camhwnd,SW_SHOW);
SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
SendMessage(camhwnd, WM_CAP_SET_SCALE, true , 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEW, true , 0);
SendMessage(camhwnd, WM_CAP_GRAB_FRAME, 0, 0);
//Grab a Frame
SendMessage(camhwnd, WM_CAP_GRAB_FRAME, 0, 0);
//Copy the frame we have just grabbed to the clipboard
SendMessage(camhwnd, WM_CAP_EDIT_COPY,0,0);
//Copy the clipboard image data to a HBITMAP object called hbm
hdc = BeginPaint(camhwnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
if (hdcMem != NULL)
{
if (OpenClipboard(camhwnd))
{
hbm = (HBITMAP) GetClipboardData(CF_BITMAP);
SelectObject(hdcMem, hbm);
GetClientRect(camhwnd, &rc);
CloseClipboard();
}
}
//Save hbm to a .bmp file called Frame.bmp
PBITMAPINFO pbi = CreateBitmapInfoStruct(hwnd, hbm);
CreateBMPFile(hwnd, "Frame.bmp", pbi, hbm, hdcMem);
SendMessage(camhwnd,WM_CAP_DRIVER_CONNECT,0,0);
SendMessage(camhwnd, WM_CAP_SET_SCALE, true , 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEWRATE, 66, 0);
SendMessage(camhwnd, WM_CAP_SET_PREVIEW, true , 0);
break;
}
}
break;
}
To display a bitmap, you first create a "handled" bitmap object, which results in your holding HBITMAP value which APIs accept for further manipulations, and then you actually display it.
The first step is achieved using CreateBitmap and friends.
On the second, see Displaying HBITMAP.

C++ GDI+ Drawing Image on layered window not working

So I've found a lot of code samples, guides, and answers on SO about drawing an image to a layered window. I've tried using pure HBITMAPS and the WIC libs to draw, and now I'm on to GDI+ to draw (which is much simpler and is seemingly easier to use, and thus far it has solved a lot of errors that were caused by faulty WIC code).
I'm currently stuck on UpdateLayeredWindow. No matter what I try I can't get it to work. Right now, it's returning 87, or ERROR_INVALID_PARAMETER. The question is, which one is incorrect? I'm stumped! The below code seems to be the solution other than the fact that UpdateLayeredWindow is refusing to work.
What am I doing wrong?
Here is the code that sets up the HDC/bitmap information/graphics object.
// Create DC
_oGrphInf.canvasHDC = GetDC(_hwndWindow);
// Create drawing 'canvas'
_oGrphInf.lpBits = NULL;
_oGrphInf.bmpCanvas = CreateDIBSection(_oGrphInf.canvasHDC,
&_oGrphInf.bmpWinInformation, DIB_RGB_COLORS,
&_oGrphInf.lpBits, NULL, 0);
// Create graphics object
_oGrphInf.graphics = new Gdiplus::Graphics(_oGrphInf.canvasHDC);
The above works fine - I step through it and all of the pointers work.
And here is the method that draws the PNG.
void Splash::DrawPNG(PNG* lpPNG, int x, int y)
{
LOGD("Drawing bitmap!");
HDC hdcMem = CreateCompatibleDC(_oGrphInf.canvasHDC);
// Select
HBITMAP bmpOld = (HBITMAP)SelectObject(hdcMem, _oGrphInf.bmpCanvas);
Gdiplus::Color trans(0, 0, 0, 0);
_oGrphInf.graphics->Clear(trans);
_oGrphInf.graphics->DrawImage(lpPNG->GetImage(), x, y);
_oGrphInf.graphics->Flush();
SIZE szSize = {_oGrphInf.bmpWinInformation.bmiHeader.biWidth,
_oGrphInf.bmpWinInformation.bmiHeader.biHeight};
// Setup drawing location
POINT ptLoc = {0, 0};
POINT ptSrc = {0, 0};
// Set up alpha blending
BLENDFUNCTION blend = {0};
blend.BlendOp = AC_SRC_OVER;
blend.SourceConstantAlpha = 255;
blend.AlphaFormat = AC_SRC_ALPHA;
blend.BlendFlags = 0;
// Update
if(UpdateLayeredWindow(_hwndWindow, _oGrphInf.canvasHDC, &ptLoc,
&szSize, hdcMem, &ptSrc,
(COLORREF)RGB(0, 0, 0),
&blend, ULW_ALPHA) == FALSE)
LOGE("Could not update layered window: %u", GetLastError());
// Delete temp objects
SelectObject(hdcMem, bmpOld);
DeleteObject(hdcMem);
DeleteDC(hdcMem);
}
Pulling my hair out! Help?
EDIT: I just decided to re-write the call to UpdateLayeredWindow function, which solved the incorrect parameter issue. Here is what I came up with. However, it still does not work. What am I doing wrong?
UpdateLayeredWindow(_hwndWindow, _oGrphInf.canvasHDC,
NULL, NULL, hdcMem, &ptLoc,
RGB(0, 0, 0), &blend, ULW_ALPHA)
For alpha information to be preserved in drawing operations, you have to make your Graphics object based on a memory-backed Bitmap object, not an HDC, and of course your Bitmap needs to be in a format with an alpha channel.
You'll need to use this Bitmap constructor: http://msdn.microsoft.com/en-us/library/ms536315%28v=vs.85%29.aspx
Just give that a stride of 0, a pointer to your DIB's bits, and PixelFormat32bppPARGB.
Then use Graphics::FromImage to create your Graphics object.
I've never used UpdateLayeredWindow, so I can't verify that that side of it is correct.

Why does BitBlt hang?

I am writing C++ code to automatically take screenshots of my favorite game. Part of my code looks like this:
SelectObject(hCDC, shot);
BitBlt(hCDC, 0, 0, WIDTH, HEIGHT, hDDC, 0, 0, SRCCOPY);
SelectObject(hCDC, oldBitmap);
Bitmap shotBitmap(shot, NULL);
I had previously initialized the relevant variables, like this:
HDC hDDC = GetDC(handle);
HDC hCDC = CreateCompatibleDC(hDDC);
HBITMAP shot = CreateCompatibleBitmap(hDDC, WIDTH, HEIGHT);
HBITMAP oldBitmap = (HBITMAP) SelectObject(hCDC, shot);
For no apparent reason, the code hangs at the BitBlt function until something (but I don't know what) updates. The millisecond I click a button in the game, or click on a window outside the game, BitBlt finishes and the rest of the code executes flawlessly. Mysteriously, I've only run into this problem recently; it never happened before. Even more mysteriously, it only happens on my laptop, not on my friend's. What could be happening?