Skip to main content
gamedev.net
🔒 Locked

Help Loading Bitmaps

Started by aNonamuss 5 replies 1k views
Original Post
aNonamuss
aNonamuss
Could anyone please tell why the following code will not load bitmaps in the directory specified? I'm trying to make a demo that will display bitmaps, but all that happens is that DirectX comes up full screen, but the bitmap never appears. Thank you for your time. Here is the code
// Bitmap loading demo

// INCLUDES ///////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN  // just say no to MFC
#define INITGUID

#include <windows.h>   // include important windows stuff
#include <windowsx.h> 
#include <mmsystem.h>
#include <ddraw.h> // include directdraw

// DEFINES ////////////////////////////////////////////////
// defines for windows 
#define WINDOW_CLASS_NAME "WINCLASS1"

// default screen size
#define SCREEN_WIDTH    640  // size of screen
#define SCREEN_HEIGHT   480
#define SCREEN_BPP      16    // bits per pixel

// TYPES //////////////////////////////////////////////////////
// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;

// PROTOTYPES  //////////////////////////////////////////////
void LoadBitmapSurface(LPDIRECTDRAWSURFACE7 lpSurface, char *fname, int xs, int ys);
void DrawHBitmap(IDirectDrawSurface7 *lpSurface, HBITMAP hBitmap, int x, int y, int width, int height);

// MACROS /////////////////////////////////////////////////
// tests if a key is up or down
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

// initializes a direct draw struct
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }

// GLOBALS ////////////////////////////////////////////////
HWND      main_window_handle = NULL; // globally track main window
int       window_closed      = 0;    // tracks if window is closed
HINSTANCE hinstance_app      = NULL; // globally track hinstance

// directdraw stuff

LPDIRECTDRAW          lpdd         = NULL;   // dd object
LPDIRECTDRAW7         lpdd7        = NULL;   // dd4 object
LPDIRECTDRAWSURFACE7  lpddsprimary = NULL;   // dd primary surface
LPDIRECTDRAWSURFACE7  lpddsback    = NULL;   // dd back surface
DDSURFACEDESC2        ddsd;                  // a direct draw surface description struct
DDSCAPS2              ddscaps;               // a direct draw surface capabilities struct


// FUNCTIONS ////////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd, 
						    UINT msg, 
                            WPARAM wparam, 
                            LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT		ps;		// used in WM_PAINT
HDC				hdc;	// handle to a device context

// what is the message 
switch(msg)
	{	
	case WM_CREATE: 
        {
		// do initialization stuff here
        // return success
		return(0);
		} break;
   
	case WM_PAINT: 
		{
		// simply validate the window 
   	    hdc = BeginPaint(hwnd,&ps);	 
        
        // end painting
        EndPaint(hwnd,&ps);

        // return success
		return(0);
   		} break;

	case WM_DESTROY: 
		{

		// kill the application, this sends a WM_QUIT message 
		PostQuitMessage(0);

        // return success
		return(0);
		} break;

	default:break;

    } // end switch

// process any messages that we didn't take care of 
return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc

///////////////////////////////////////////////////////////

int Game_Main(void *parms = NULL, int num_parms = 0)
{
// this is the main loop of the game, do all your processing
// here

   
    // make sure this isn't executed again
if (window_closed)
   return(0);

// for now test if user is hitting ESC and send WM_CLOSE
if (KEYDOWN(VK_ESCAPE))
   {
   PostMessage(main_window_handle,WM_CLOSE,0,0);
   window_closed = 1;
   } // end if

// do nothing -- look at pretty picture

// return success or failure or your own return code here
return(1);

} // end Game_Main

////////////////////////////////////////////////////////////

int Game_Init(void *parms = NULL, int num_parms = 0)
{
// this is called once after the initial window is created and
// before the main event loop is entered, do all your initialization
// here

// first create base IDirectDraw interface
if (FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
   return(0);

// now query for IDirectDraw4
if (FAILED(lpdd->QueryInterface(IID_IDirectDraw7,
                               (LPVOID *)&lpdd7)))
   return(0);

// set cooperation to full screen
if (FAILED(lpdd7->SetCooperativeLevel(main_window_handle, 
                                      DDSCL_FULLSCREEN | 
                                      DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
   return(0);

// set display mode
if (FAILED(lpdd7->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
   return(0);

// clear ddsd and set size
DDRAW_INIT_STRUCT(ddsd); 

// enable valid fields
ddsd.dwFlags = DDSD_CAPS;

// request primary surface
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

// create the primary surface
if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, NULL)))
   return(0);

LoadBitmapSurface(lpddsprimary, "c:\\source\\images\\bitmap24.bmp", 0,0);
//lpddsprimary->Flip(NULL, DDFLIP_WAIT);

// return success or failure or your own return code here
return(1);

} // end Game_Init

/////////////////////////////////////////////////////////////

int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// this is called after the game is exited and the main event
// loop while is exited, do all you cleanup and shutdown here

// now the primary surface
if (lpddsprimary)
   {
   lpddsprimary->Release();
   lpddsprimary = NULL;
   } // end if

// now blow away the IDirectDraw7 interface
if (lpdd7)
   {
   lpdd7->Release();
   lpdd7 = NULL;
   } // end if

// return success or failure or your own return code here
return(1);

} // end Game_Shutdown

// WINMAIN ////////////////////////////////////////////////

int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create
HWND	   hwnd;	 // generic window handle
MSG		   msg;		 // generic message

// first fill in the window class stucture
winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style			= CS_DBLCLKS | CS_OWNDC | 
                          CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc	= WindowProc;
winclass.cbClsExtra		= 0;
winclass.cbWndExtra		= 0;
winclass.hInstance		= hinstance;
winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor		= LoadCursor(NULL, IDC_ARROW); 
winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

// save hinstance in global
hinstance_app = hinstance;

// register the window class
if (!RegisterClassEx(&winclass))
	return(0);

// create the window
if (!(hwnd = CreateWindowEx(NULL,                  // extended style
                            WINDOW_CLASS_NAME,     // class
						    "DirectDraw Bitmap Loading", // title
						    WS_POPUP | WS_VISIBLE,
					 	    0,0,	  // initial x,y
						    SCREEN_WIDTH,SCREEN_HEIGHT,  // initial width, height
						    NULL,	  // handle to parent 
						    NULL,	  // handle to menu
						    hinstance,// instance of this application
						    NULL)))	// extra creation parms
return(0);

// save main window handle
main_window_handle = hwnd;

// initialize game here
Game_Init();

// enter main event loop
while(TRUE)
	{
    // test if there is a message in queue, if so get it
	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	   { 
	   // test if this is a quit
       if (msg.message == WM_QUIT)
           break;
	
	   // translate any accelerator keys
	   TranslateMessage(&msg);

	   // send the message to the window proc
	   DispatchMessage(&msg);
	   } // end if
    
       // main game processing goes here
       Game_Main();
       
	} // end while

// closedown game here
Game_Shutdown();

// return to Windows like this
return(msg.wParam);

} // end WinMain

void LoadBitmapSurface(LPDIRECTDRAWSURFACE7 lpSurface, char *fname, int xs, int ys)
{
   HBITMAP hBitmap;

   hBitmap = (HBITMAP)LoadImage(NULL, fname, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
   DrawHBitmap(lpSurface, hBitmap, 0, 0, xs, ys);
   DeleteObject(hBitmap);
}


void DrawHBitmap(IDirectDrawSurface7 *lpSurface, HBITMAP hBitmap, int x, int y, int width, int height)
{
   HDC           hdcImage;
   HDC           hdc;
   BITMAP        bm;

   if (lpSurface == NULL || hBitmap == NULL)
      return;
   lpSurface->Restore();

   hdcImage = CreateCompatibleDC(NULL);
   SelectObject(hdcImage, hBitmap);

   GetObject(hBitmap, sizeof(bm), &bm);
   width = width == 0 ? bm.bmWidth  : width;
   height = height == 0 ? bm.bmHeight : height;

   lpSurface->GetDC(&hdc);
   BitBlt(hdc, x, y, width, height, hdcImage, 0, 0, SRCCOPY);
   lpSurface->ReleaseDC(hdc);
   DeleteDC(hdcImage);
}
///////////////////////////////////////////////////////////
  
Thanks again [edited by - aNonaMuss on January 11, 2003 5:41:44 PM]
aNonamuss
aNonamuss
I used the debugger and narrowed it down to the error occuring on the following line:


if (lpSurface == NULL || hBitmap == NULL)
return;


Looking at the state of the variables before the execution of the if statement, I determined that hBitmap is NULL. Could anyone, after analyzing the previous code I posted, figure out why both hBitmap could be NULL??


Thanks again.

[edited by - aNonaMuss on January 11, 2003 6:12:55 PM]
aNonamuss
aNonamuss
OK, I got that fixed. It turns out that I was pointing to an invalid filename (whoops) hence the invalid hBitmap

But I''m still getting the problem of not seeing the bitmap appear. I used the debugger to step through the entire program without any errors, but when it comes to the code where is copies the bitmap to VRAM, the bitmap flashes on the screen. But it won''t stay there.

If I run the program from the command prompt or windows explorer, I don''t even see the bitmap appear at all.


Thanks again,
nullstate
nullstate
Hey aNonamuss,

This might or might not be related to your problem. While writing my own programs, I''ve noticed that when I tried to write to the primary surface, before entering the window''s message loop, it always fails; Nothing but a blank screen.

However, if I set it up to write to the primary surface while in the game_main() function, it works just fine.
aNonamuss
aNonamuss
That did it bro!!!!

Thank you very much for the help. I don''t think I would have ever thought of moving my loadbitmap function.

Thanks again, you rock!!


-- aNona
JonW
JonW
I think it would be slow if you load the bitmap every frame and write it to the primary surface. If you are going to build a game off of this code (or even if you are just doing it for practice, it would be good to know), you should load the bitmap onto an offscreen surface in the init function, and then use DirectDraw''s blit function to render the offscreen surface to the primary buffer in the game loop function. At the beginning of the loop you should also clear the primary surface.

This is important because DirectDraw uses hardware acceleration, so its blit function is usually faster than GDI''s BitBlt. Plus it has to keep opening and closing the file on the harddrive.
aNonamuss
aNonamuss
Thanks for the tip Jon. That is what I ended up doing.

I renamed the LoadBitmap function, to CreateBitmap. Then I just have the user pass in the a surface object they created. I have the bitmap being loaded into the surface in the Init function. Then in main loop, I just blit that surface to the back buffer, then do a flip after any other game logic.

I didn''t have a clear primary surface operation in the main, so I''ll implement that also (thanks for the tip!)

Thanks again for all the help guys!


--aNona

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.