DirectDraw Bitmap Blitting (How original :D )

Started by
4 comments, last by TomKQT 15 years, 11 months ago
Well, hi. I'm trying to get DirectDraw to work, but I have absolutely no idea what I'm doing. I'll show you my code to show you what I've achieved so far... Please tell me why it is turning my screen black instead of displaying a bitmap on it :s Sorry if this question seems stupid or the answer seems obvious to you, I am completely self taught in everything I know, and there reaches a point where you just become absolutely confused and can't get a grasp of the concept without other's help. This is pretty much the first help I've tried to get from actual humans :o Yeah so enough blabbering, and here is my code if you feel like reading through it (I'm hoping this place has BBcode)

#include <windows.h>
#include <ddraw.h>

#pragma comment(lib, "ddraw.lib")

LPDIRECTDRAW lpDD;
LPDIRECTDRAWSURFACE lpMain;
LPDIRECTDRAWSURFACE lpBack;
LPDIRECTDRAWSURFACE lpPic;
bool QuitKey = false;

bool DD_init(HWND hwnd)
{
	HRESULT hr;
	hr = DirectDrawCreate(0, &lpDD, 0);
	if(hr != DD_OK) return false;
	hr = lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	if(hr != DD_OK) 
	{
		lpDD->Release();
		return false;
	}
	hr = lpDD->SetDisplayMode(1024, 768, 32);
	if(hr != DD_OK)
	{
		lpDD->Release();
		return false;
	}
	return true;
}

IDirectDrawPalette *DDLoadPalette(IDirectDraw * pdd, LPCSTR szBitmap)
{
    IDirectDrawPalette     *ddpal;
    int                     i;
    int                     n;
    int                     fh;
    HRSRC                   h;
    LPBITMAPINFOHEADER      lpbi;
    PALETTEENTRY            ape[256];
    RGBQUAD                *prgb;
    for (i = 0; i < 256; i++)
    {
        ape.peRed = (BYTE) (((i >> 5) & 0x07) * 255 / 7);
        ape.peGreen = (BYTE) (((i >> 2) & 0x07) * 255 / 7);
        ape.peBlue = (BYTE) (((i >> 0) & 0x03) * 255 / 3);
        ape.peFlags = (BYTE) 0;
    }
    if (szBitmap && (h = FindResource(NULL, szBitmap, RT_BITMAP)))
    {
        lpbi = (LPBITMAPINFOHEADER) LockResource(LoadResource(NULL, h));
        if (!lpbi)
            OutputDebugString("lock resource failed\n");
        prgb = (RGBQUAD *) ((BYTE *) lpbi + lpbi->biSize);
        if (lpbi == NULL || lpbi->biSize < sizeof(BITMAPINFOHEADER))
            n = 0;
        else if (lpbi->biBitCount > 8)
            n = 0;
        else if (lpbi->biClrUsed == 0)
            n = 1 << lpbi->biBitCount;
        else
            n = lpbi->biClrUsed;
        for (i = 0; i < n; i++)
        {
            ape.peRed = prgb.rgbRed;
            ape.peGreen = prgb.rgbGreen;
            ape.peBlue = prgb.rgbBlue;
            ape.peFlags = 0;
        }
    }
    else if (szBitmap && (fh = _lopen(szBitmap, OF_READ)) != -1)
    {
        BITMAPFILEHEADER        bf;
        BITMAPINFOHEADER        bi;

        _lread(fh, &bf, sizeof(bf));
        _lread(fh, &bi, sizeof(bi));
        _lread(fh, ape, sizeof(ape));
        _lclose(fh);
        if (bi.biSize != sizeof(BITMAPINFOHEADER))
            n = 0;
        else if (bi.biBitCount > 8)
            n = 0;
        else if (bi.biClrUsed == 0)
            n = 1 << bi.biBitCount;
        else
            n = bi.biClrUsed;
        for (i = 0; i < n; i++)
        {
            BYTE        r = ape.peRed;

            ape.peRed = ape.peBlue;
            ape.peBlue = r;
        }
    }
    pdd->CreatePalette(DDPCAPS_8BIT, ape, &ddpal, NULL);
    return ddpal;
}

bool CreateSurfaces()
{
	DDSURFACEDESC ddsd;
	DDSCAPS ddscaps;
	HRESULT hr;
	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
	ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	ddsd.dwBackBufferCount = 1;
	hr = lpDD->CreateSurface(&ddsd, &lpMain, 0);
	if(hr != DD_OK)
	{
		lpDD->Release();
		return false;
	}
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	hr = lpMain->GetAttachedSurface(&ddscaps, &lpBack);
	if(hr != DD_OK)
	{
		lpMain->Release();
		lpDD->Release();
		return false;
	}
	ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
						  DDSCAPS_VIDEOMEMORY;
	ddsd.dwWidth = 50;
	ddsd.dwHeight = 50;
	hr = lpDD->CreateSurface(&ddsd, &lpPic, 0);
	if(hr != DD_OK)
	{
		lpDD->Release();
		lpMain->Release();
		lpBack->Release();
		return false;
	}
	LPDIRECTDRAWPALETTE lpPalette;
	lpPalette = DDLoadPalette(lpDD, "test.bmp");
	lpMain->SetPalette(lpPalette);
	lpPalette->Release();
	return true;
}


bool LoadBmp(LPDIRECTDRAWSURFACE lpDest, LPCSTR filename)
{
	HDC hdc;
	HDC hdcimage;
	hdcimage = CreateCompatibleDC(0);
	HRESULT hr;
	BITMAP bmp;
	HBITMAP pic = (HBITMAP)LoadImageA(0, filename, 0, 0, 0, LR_LOADFROMFILE);
	GetObject(pic, sizeof(BITMAP), &bmp);
	SelectObject(hdcimage, pic);
	hr = lpDest->GetDC(&hdc);
	if(hr != DD_OK) return false;
	BitBlt(hdc, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcimage, 0, 0, SRCCOPY);
	lpDest->ReleaseDC(hdc);
	DeleteDC(hdcimage);
	DeleteDC(hdc);
	return true;
}


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
	switch(msg)
	{
	case WM_DESTROY:
		QuitKey = true;
		break;
	}
	return DefWindowProcA(hwnd, msg, wparam, lparam);
}

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MSG msg;
	WNDCLASS wc;
	HWND hwnd;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(6);
	wc.hCursor = LoadCursorA(0, IDC_ARROW);
	wc.hIcon = 0;
	wc.hInstance = hInstance;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "lol";
	wc.lpszMenuName = 0;
	wc.style = CS_VREDRAW|CS_HREDRAW;
	RegisterClass(&wc);
	hwnd = CreateWindowA("lol", "hi", WS_OVERLAPPEDWINDOW | WS_THICKFRAME, 50, 50, 500, 600, 0, 0, hInstance, 0);
	ShowWindow(hwnd, SW_SHOW);
	if(!DD_init(hwnd))
		return 1;
	if(!CreateSurfaces())
		return 1;
	if(!LoadBmp(lpPic, "test.bmp"))
		return 1;
	RECT rect;
	rect.left = 0;
	rect.top = 0;
	rect.right = 50;
	rect.bottom = 50;
	lpBack->BltFast(0, 0, lpPic, &rect, 1);
	lpMain->Flip(0, 0);
	while(!QuitKey)
	{
		if(PeekMessageA(&msg,0,0,0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}
Advertisement
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.

The usual way to do this sort of thing is to use Direct3D and draw a textured quad. That way you get hardware acceleration, and you also get rotation, scaling, colour conversion and alpha blending for free.
There are too many problems there!. To bolster your DirectDraw understanding try click me!. Should give you enough infos to get you started. :)
Quote:Original post by Evil Steve
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.
More like 12 (or so) years. Anyway, DirectDraw has one gigantic advantage over D3D. It pretty much always just works right out of the box, without having to worry about up-to-date drivers or a modern graphics card or Windows version. Getting D3D to work reliably on a cheap five year old laptop with badly updated drivers is less than fun..
Granted this is probably mostly because because it's largely software emulated and driver developers aren't trying to squeeze every last cycle out of it with dirty tricks and complicated schemes, but it's nevertheless true.
In other words if performance isn't much of an issue and you only need basic blits then DirectDraw (or even GDI, though that lacks hardware page flipping) may well be a valid alternative.
Quote:Original post by Evil Steve
A little off topic - but why DirectDraw? It's about 8 years old or something, no longer being developed, has almost zero hardware support (Meaning you don't take any advantage of the graphics card at all), is an absolute nightmare to work with, and is useless for just about everything apart from overlays.

The usual way to do this sort of thing is to use Direct3D and draw a textured quad. That way you get hardware acceleration, and you also get rotation, scaling, colour conversion and alpha blending for free.



I dunno, I just thought it was the thing to learn before moving on to 3D stuff, but if using Direct3D is better I should probably learn that then ... Thanks for advice.

Quote:Original post by i_is_want_smart
I dunno, I just thought it was the thing to learn before moving on to 3D stuff, but if using Direct3D is better I should probably learn that then ... Thanks for advice.

Nope, you got it wrong. It's a common mistake to think that Direct3D is just for 3D graphics ;)
You can start with "2D" in Direct3D and then you'll have it easier to go for 3D.

This topic is closed to new replies.

Advertisement