Windows Bitmap Problem

Started by
5 comments, last by kirkd 19 years, 3 months ago
Below is the code for a simple program I've put together. This is essentially the code Bricks1 from Petzold 5th edition. I also have a BMP file and a resource file referring to the BMP file. All the names for the BMP resource seem to be OK, however, I get an error every time I run this: "The specified resource name cannot be found in the image file." Any ideas?? -Kirk I added the contents of the resource file (Script1.rc). bitmap1.bmp is present in the project's base directory.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
				   PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName [] = TEXT ("TestBMP");
	HWND hwnd;
	MSG	msg;
	WNDCLASS wndclass;

	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc=WndProc;
	wndclass.cbClsExtra=0;
	wndclass.cbWndExtra=0;
	wndclass.hInstance=hInstance;
	wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor=LoadCursor(NULL,IDC_ARROW);
	wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName=NULL;
	wndclass.lpszClassName=szAppName;

	if (!RegisterClass(&wndclass))
	{
		MessageBox(NULL, TEXT("This program requires WinNT!"), szAppName, MB_ICONERROR);
		return 0;
	}
	hwnd=CreateWindow(szAppName, TEXT("Test Bitmap"),
					  WS_OVERLAPPEDWINDOW,
					  CW_USEDEFAULT, CW_USEDEFAULT,
					  CW_USEDEFAULT, CW_USEDEFAULT,
					  NULL, NULL, hInstance, NULL);

	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);
	
	while (GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HBITMAP hBitmap;
	static int cxClient, cyClient, cxSource, cySource;
	BITMAP bitmap;
	HDC hdc, hdcMem;
	HINSTANCE hInstance;
	int x,y;
	PAINTSTRUCT ps;

	LPVOID lpMsgBuf;

	switch(message)
	{
	case WM_CREATE:
		hInstance = ((LPCREATESTRUCT) lParam)->hInstance;
		hBitmap = LoadBitmap(hInstance, TEXT("TestBMP"));
		if (hBitmap == NULL) 
		{
			FormatMessage( 
							FORMAT_MESSAGE_ALLOCATE_BUFFER | 
							FORMAT_MESSAGE_FROM_SYSTEM | 
							FORMAT_MESSAGE_IGNORE_INSERTS,
							NULL,
							GetLastError(),
							0, // Default language
							(LPTSTR) &lpMsgBuf,
							0,
							NULL 
						);
			MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);

		}
		GetObject(hBitmap, sizeof(BITMAP), &bitmap);
		cxSource=bitmap.bmWidth;
		cySource=bitmap.bmHeight;
		return 0;

	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);
		return 0;

	case WM_PAINT:
		hdc = BeginPaint(hwnd, &ps);
		hdcMem = CreateCompatibleDC(hdc);
		SelectObject(hdcMem, hBitmap);
		for (y=0; y<cyClient; y+=cySource)
			for(x=0; x<cxClient; x+=cxSource)
			{
				BitBlt(hdc, x, y, cxSource, cySource, hdcMem, 0,0,SRCCOPY);
			}

		DeleteDC(hdcMem);
		EndPaint(hwnd, &ps);
		return 0;
	case WM_DESTROY:
		DeleteObject(hBitmap);
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hwnd, message, wParam, lParam);
}







Here's the resource file contents:

//Microsoft Developer Studio generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

TestBMP                 BITMAP  DISCARDABLE     "bitmap1.bmp"
#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED


[Edited by - kirkd on January 5, 2005 9:55:27 PM]
Advertisement
I'm not sure what you mean by "a resource file referring to the BMP file". The BMP resource needs to be inserted into the resource file doesn't it?
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
The resource file (*.rc) contains a line that references the bitmap file by name. I've inserted the Bitmap and named it through Visual Studio 6 SP5 as usual, but for some reason, the error always pops up.

-Kirk
I fixed it.

1) The source file should contain #include "resource.h"

2) The following line:

hBitmap = LoadBitmap(hInstance, TEXT("TestBMP"));

was changed to

hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(TestBMP));


The include line makes sense. The other makes little sense to me.




-Kirk



Resources created this way are not referenced by name by default, they are referenced by a 32bit integer value (you can give them a name though). TestBMP is #defined in "resource.h" to be the 32bit identifier of the resource.

LoadBitmap takes a string as its second parameter, the string is the name of the resource to load. Since the string is passed as a 32bit pointer, the LoadBitmap function checks the high word of the pointer value for 0, if it is zero, it treats the value as a resource identifier and not a pointer to a string; if it's not zero it treats the value as a pointer to a string. The MAKEINTRESOURCE is a macro that allows you to provide a 32bit integer identifier where a string is required without the compiler complaining about it.

Skizz
Good you managed to fix it yourself (I was about telling you to have a look to your resource.h file anyway).

If you want to specify named resources then the resource.h file should not define the new resource.

// in resource.h : nothing// in file.rcSomeUniqueName BITMAP DISCARDABLE "bitmap1.bmp"// the rc compiler will create a resource with the name "SOMEUNIQUENAME"


If your BITMAP is referenced with an ID - ie you have
// in resource.h#define SomeUniqueName 100// in file.rcSomeUniqueName BITMAP DISCARDABLE "bitmap1.bmp"// this is now equivalent to : 100 BITMAP DISCARDABLE "bitmap1.bmp"

Then you must use MAKEINRESOURCE() to tell LoadBitmap() that it is an ID - and not a string litteral.

Quote:Original post by Skizz
Resources created this way are not referenced by name by default, they are referenced by a 32bit integer value (you can give them a name though). TestBMP is #defined in "resource.h" to be the 32bit identifier of the resource.


Exact - minus the fact that resource IDs are 16 bit values, not 32 bit ones (welcome back in the realm of backward compability).

HTH,
Thank you both for the explanations. It is a bit contrived, I think, and doesn't make a lot of sense at this stage. Maybe one day, right??? 8^) I would think that the Petzold code would run, but the more I look the more I find that is not without problems.

-kirk

This topic is closed to new replies.

Advertisement