Advertisement

Blank Screen

Started by February 22, 2000 07:59 PM
9 comments, last by PsYcHoPrOg 24 years, 6 months ago
I am trying to load a bitmap onto a backbuffer using LoadBitmap() and then blit the information on the backbuffer, to the primary buffer. However, It''s not working! When I compile, I get a blank screen! What am I doing wrong?! Here is the code: #define WIN32_LEAN_AND_MEAN //include important stuff #include >windows.h< //brackets are inverted for HTML tag #include >windowsx.h< #include >mmsystem.h< #include >memory.h< #include >ddraw.h< #include "bmpblit.h" #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) HWND window_handle = NULL; HINSTANCE instance = NULL; LPDIRECTDRAW lpdd = NULL; LPDIRECTDRAW4 lpdd4 = NULL; LPDIRECTDRAWSURFACE4 pbuff = NULL; LPDIRECTDRAWSURFACE4 bbuff = NULL; DDSURFACEDESC2 ddsd; DDSCAPS2 ddscaps; 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 // 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 HDC hdc; // graphics device context // 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 = "class"; winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // save hinstance in global instance = hinstance; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(NULL, // extended style "class", // class "BlitBMP", // title WS_POPUP / WS_VISIBLE, 0,0, // initial x,y 640,480, // initial width, height NULL, // handle to parent NULL, // handle to menu hinstance,// instance of this application NULL))) // extra creation parms return(0); ShowCursor(FALSE); // save main window handle window_handle = hwnd; // initialize game here GameInit(); // 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 GameMain(); } // end while // closedown game here GameEnd(); // return to Windows like this return(msg.wParam); } // end WinM bool LoadBMP(LPDIRECTDRAWSURFACE4 surface, LPSTR filename, int bmpwidth, int bmpheight, int surfacewidth, int surfaceheight) { HBITMAP hbm; HDC imagedc; HDC surfacedc; hbm = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, bmpwidth, bmpheight, LR_LOADFROMFILE/LR_CREATEDIBSECTION); if(hbm == NULL) return FALSE; imagedc = CreateCompatibleDC(NULL); SelectObject(imagedc, hbm); if(FAILED(surface->GetDC(&surfacedc))) return FALSE; if(BitBlt(surfacedc, 0, 0, surfacewidth, surfaceheight, imagedc, 0, 0, SRCCOPY)== FALSE) return FALSE; if(surfacedc) { surface->ReleaseDC(surfacedc); } if(imagedc) { DeleteDC(imagedc); } if(hbm) { DeleteObject(hbm); } return TRUE; } int GameInit() { if(FAILED(DirectDrawCreate(NULL, &lpdd, NULL))) return(0); if(FAILED(lpdd->QueryInterface(IID_IDirectDraw4, (LPVOID *)&lpdd4))) return(0); if(FAILED(lpdd4->SetCooperativeLevel(window_handle, DDSCL_FULLSCREEN/ DDSCL_EXCLUSIVE/DDSCL_ALLOWREBOOT))) return(0); if(FAILED(lpdd4->SetDisplayMode(640, 480, 16, 0, 0))) return(0); memset(&ddsd, 0, sizeof(ddsd)); ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_CAPS/DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE/ DDSCAPS_COMPLEX/ DDSCAPS_FLIP; if(FAILED(lpdd4->CreateSurface(&ddsd, &pbuff, NULL))) return(0); ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if(FAILED(pbuff->GetAttachedSurface(&ddscaps, &bbuff))) return(0); LoadBMP(bbuff, "image.bmp", 640, 480, 640, 480); }//end GameInit() int GameMain() { if(KEYDOWN(VK_ESCAPE)) { SendMessage(window_handle, WM_CLOSE, 0, 0); } RECT source; RECT dest; source.top =0; source.left =0; source.bottom =480; source.right =640; dest.top =0; dest.left =0; dest.bottom =480; dest.right =640; if(FAILED(pbuff->Blt(&dest, bbuff, &source, DDBLT_WAIT, NULL))) return(0); return(1); }//end GameMain() int GameEnd() { if(lpdd4) { lpdd4->Release(); lpdd4 = NULL; } if(pbuff) { pbuff->Release(); pbuff = NULL; } if(bbuff) { bbuff->Release(); bbuff = NULL; } return(1); }
D:
Psychoprog you never give up do you?

I think you also need to load the bitmap''s palette with a DirectDraw util such as DDLoadPalette, then apply the palette to the appropriate buffer - correct me if this is wrong people I don''t use DirectX much.

You can find out how to do this in the DirectDraw samples in the DirectX SDK.

Paulcoz.
Advertisement
He doesn't have a palette, 'cause his program works in 16bit col.

Edited by - Melo on 2/23/00 4:11:00 PM
Well you should probably clear the memory for the back buffer(ddsd), after you create the primary surface. Also you may want to check your return values from GameInit and GameMain(and return (1) from GameInit if all goes well). Also you should release the surfaces in reverse order. So release the back first, then the primary, and then the direct draw object.

At the moment that''s all I see. But if you check your return values and clear the ddsd before setting up the back buffer and everything is ok and you still have a problem, tell me!
Working on: DoP
Okay, I changed the code a bit, and it still doesn''t work. I''ll give the functions here:


bool LoadBMP(LPDIRECTDRAWSURFACE4 surface, LPSTR filename)
{
DDSURFACEDESC2 ddsd2;//to get the surface description
DDSCAPS2 ddscaps2;//to get the surface Caps
HBITMAP hbm; //handle to the bitmap object
HDC imagedc; //Handle to the image dc
HDC surfacedc;//Handle to the surface dc

//get the surface description
if(FAILED(surface->GetSurfaceDesc(&ddsd2)))
return FALSE;

//get the surface caps
if(FAILED(surface->GetCaps(&ddscaps2)))
return FALSE;

//load the bitmap into the handle of the object
hbm = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP,
ddsd2.dwWidth, ddsd2.dwHeight,
LR_LOADFROMFILE/LR_CREATEDIBSECTION);

//Check if the function worked
if(hbm == NULL)
return FALSE;

//Put the object into the dc
imagedc = CreateCompatibleDC(NULL);
SelectObject(imagedc, hbm);

//lock the surface
if(FAILED(surface->GetDC(&surfacedc)))
return FALSE;

//blit the bitmap to the surface

BitBlt(surfacedc, 0, 0, ddsd.dwWidth, ddsd.dwHeight,
imagedc, 0, 0, SRCCOPY);

//clean up everything

if(surfacedc)
surface->ReleaseDC(surfacedc);

if(imagedc)
DeleteDC(imagedc);

if(hbm)
DeleteObject(hbm);

}

int GameInit()
{
if(FAILED(DirectDrawCreate(NULL, &lpdd, NULL)))
return(0);

if(FAILED(lpdd->QueryInterface(IID_IDirectDraw4,
(LPVOID *)&lpdd4)))
return(0);

if(FAILED(lpdd4->SetCooperativeLevel(window_handle, DDSCL_FULLSCREEN/
DDSCL_EXCLUSIVE/DDSCL_ALLOWREBOOT)))
return(0);

if(FAILED(lpdd4->SetDisplayMode(640, 480, 16, 0, 0)))
return(0);

memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS/DDSD_BACKBUFFERCOUNT;
ddsd.dwBackBufferCount = 1;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE/
DDSCAPS_COMPLEX/
DDSCAPS_FLIP;

if(FAILED(lpdd4->CreateSurface(&ddsd, &pbuff, NULL)))
return(0);

ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

if(FAILED(pbuff->GetAttachedSurface(&ddscaps, &bbuff)))
return(0);

memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS/DDSD_HEIGHT/DDSD_WIDTH;
ddsd.dwWidth = 640;
ddsd.dwHeight = 480;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

if(FAILED(lpdd4->CreateSurface(&ddsd, &Bitmap, NULL)))
return (0);

LoadBMP(Bitmap, "image.bmp");
}//end GameInit()

int GameMain()
{

if(KEYDOWN(VK_ESCAPE))
{
SendMessage(window_handle, WM_CLOSE, 0, 0);
}


if(FAILED(bbuff->BltFast(0, 0, Bitmap, NULL,
DDBLTFAST_WAIT)))
return(0);

if(FAILED(pbuff->Flip(NULL, DDFLIP_WAIT)))
return(0);



return(1);

}//end GameMain()

int GameEnd()
{
if(lpdd4)
{
lpdd4->Release();
lpdd4 = NULL;
}
if(pbuff)
{
pbuff->Release();
pbuff = NULL;
}
if(bbuff)
{
bbuff->Release();
bbuff = NULL;
}
return(1);
}


The problem is, when my program runs, I hear a tone and am forced to CTR-ALT-DEL out of it. After I do so, I see a little yellow arrow next to the line:


if(FAILED(BltFast(0, 0, Bitmap, DDBLTFAST_WAIT)))


and I also see a dialogue box that says:

classFirst-chance exception in Blitex.exe: 0xC0000005: Access Violation.

It also says this in the debug box at the bottom of the screen. I am using VC++ 6.0. Please help if you can. I really have no Idea what the problem is.
D:
You still need to check the return value from:
LoadBmp(Bitmap,"image.bmp");

To make sure that the bitmap is loading.
If it is loading correctly, feel free to send me the code and I''ll be happy to figure it out for you.
Working on: DoP
Advertisement
Also don''t forget to release the old lpdd after the call to Query Interface instead of letting it hang around until you''re done.

Still Learning...
Still Learning...
Maybe you already know this, but have you tried taking some sample code that already works and changing little bits at a time until it does what you want it to do? That''s a helluva lot easier than trying to write the DirectX initialization from scratch.
Mike Weldon, a.k.a. FalloutBoymweldon@san.rr.com
This is what I have been doing. However, I don''t know how to fix the error that I get from the debugger.

"Remember, I'm the monkey, and you're the cheese grater. So no fooling around."
-Grand Theft Auto, London
D:
[imagedc = CreateCompatibleDC(NULL);
SelectObject(imagedc, hbm);
if(FAILED(surface->GetDC(&surfacedc)))
return FALSE;


if(BitBlt(surfacedc, 0, 0, surfacewidth, surfaceheight,
imagedc, 0, 0, SRCCOPY)== FALSE)
return FALSE;
]

I think your problem is here (above). Call surface->GetDC() then create a Compatible DC from the DC surface->GetDC() returns, not from NULL.
- Ryan -

This topic is closed to new replies.

Advertisement