DirectDraw 7 Setup Problem

Started by
17 comments, last by Bad Maniac 19 years, 6 months ago
For some reason DirectDraw won't setup. I run my application and I make it exit if there's a problem in my DDSetup() function, and it exits on it's own. Here's the source code for it:

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

char szAppName[256];

HWND hWnd;
MSG Msg;
WNDCLASSEX WndClass;
HDC hDC;

LPDIRECTDRAW7 lpDD;
DDSURFACEDESC2 DDSD;
DDSCAPS2 DDSCaps;
LPDIRECTDRAWSURFACE7 lpDDSPrimary, lpDDSSecondary;
LPDIRECTDRAWSURFACE7 lpDDSBlackBackground, lpDDSBitmapTest;

RECT rRect;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool DDSetup(void);
void DDRender(void);
void DDShutdown(void);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{

	strcpy(szAppName, "DirectX");

	WndClass.cbClsExtra = 0;
	WndClass.cbSize = sizeof(WNDCLASSEX);
	WndClass.cbWndExtra = 0;
	WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
	WndClass.hIcon = LoadIcon(hInstance, szAppName);
	WndClass.hIconSm = LoadIcon(hInstance, szAppName);
	WndClass.lpfnWndProc = WndProc;
	WndClass.lpszClassName = szAppName;
	WndClass.lpszMenuName = NULL;
	WndClass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

	RegisterClassEx(&WndClass);

	hWnd = CreateWindowEx(NULL, szAppName, szAppName, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);

	ShowWindow(hWnd, SW_SHOWDEFAULT);
	UpdateWindow(hWnd);

	if (!DDSetup())
	{

		PostQuitMessage(0);

	}

	while (Msg.message != WM_QUIT)
	{

		if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
		{

			TranslateMessage(&Msg);
			DispatchMessage(&Msg);

		}
		else
		{

			if (GetAsyncKeyState(VK_ESCAPE))
			{

				PostQuitMessage(0);

			}

			DDRender();

		}

	}

	DDShutdown();

	UnregisterClass(szAppName, hInstance);

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{

	switch (Msg)
	{

	case WM_CLOSE:

		DestroyWindow(hWnd);

		break;

	case WM_DESTROY:

		PostQuitMessage(0);

		break;

	default:

		break;

	}

	return DefWindowProc(hWnd, Msg, wParam, lParam);

}

bool DDSetup(void)
{

	if (DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL) != DD_OK)
	{

		return false;

	}

	if (lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT) != DD_OK)
	{

		return false;

	}

	if (lpDD->SetDisplayMode(800, 600, 16, 0, 0) != DD_OK)
	{

		return false;

	}

	DDSD.dwSize = sizeof(DDSD);
	DDSD.dwFlags = DDSD_CAPS;
	DDSD.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
	DDSD.dwBackBufferCount = 1;

	if (lpDD->CreateSurface(&DDSD, &lpDDSPrimary, NULL) != DD_OK)
	{

		return false;

	}

	DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;

	lpDDSPrimary->GetAttachedSurface(&DDSCaps, &lpDDSSecondary);

	lpDDSBlackBackground = DDLoadBitmap(lpDD, "blackbackground.bmp", 0, 0);

	lpDDSBitmapTest = DDLoadBitmap(lpDD, "test.bmp", 0, 0);
	DDSetColorKey(lpDDSBitmapTest, CLR_INVALID);

	return true;

}

void DDRender(void)
{

	SetRect(&rRect, 0, 0, 800, 600);
	lpDDSSecondary->BltFast(0, 0, lpDDSBlackBackground, &rRect, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);

	SetRect(&rRect, 0, 0, 32, 32);
	lpDDSSecondary->BltFast(0, 0, lpDDSBitmapTest, &rRect, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);

	lpDDSSecondary->GetDC(&hDC);

	SetBkMode(hDC, TRANSPARENT);
	SetTextColor(hDC, RGB(255, 0, 0));
	SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));

	TextOut(hDC, 100, 100, "Hello, World!", strlen("Hello, World!"));

	lpDDSSecondary->ReleaseDC(hDC);

	lpDDSPrimary->Flip(NULL, DDFLIP_WAIT);

}

void DDShutdown(void)
{

	if (lpDDSBlackBackground)
	{

		lpDDSBlackBackground->Release();
		lpDDSBlackBackground = NULL;

	}

	if (lpDDSSecondary)
	{

		lpDDSSecondary->Release();
		lpDDSSecondary = NULL;

	}

	if (lpDDSPrimary)
	{

		lpDDSPrimary->Release();
		lpDDSPrimary = NULL;

	}

	if (lpDD)
	{

		lpDD->Release();
		lpDD = NULL;

	}

}

I get no errors when I try to build and run this program. The blackbackground.bmp and test.bmp files are in the same directory as the main .exe.
=============================All knowledge is good; only the way it is put to use is good or evil.
Advertisement
Hello,

I haven't done direct draw 7 in a while so I wouldn't be able to help you out with the correctness of your code. One thing that I can suggest (it helps in debugging) is that you can have your functions return a different error code (an integer) for each error that it produces, instead of returning false all the time. This will tell you more about your errors and where it is failing if you print out the error code or a message associated with it.

Another debugging technique that I use is to print out messages to see if the program is executing that piece of code.

Once you find out where the error is happening then you can concentrate on that specific piece of code.

Hope that helps you find the specific problem,

Richard
I changed the Setup function to an int an had each error return a specific value to find that the error was in the SetCooperativeLevel() function, but what am I doing wrong? It looks fine to me.
=============================All knowledge is good; only the way it is put to use is good or evil.
Hmmmm, sounds like an invalid handle to the window can be the only problem. Check to see if hWnd == 0, if it is there is a problem with the CreateWindowEx() call (unless of course you can see the window then there would be nothing wrong with the handle).

Try changing the parts in the CreateWindowEx() where the width and height is and change it to a number (i.e. 800 width and 600 height) see if that affects it.

Richard
I would try tracing through the code with the debugger. There isn't that much code, so it shouldn't take very long to isolate the problem.
Michael Brennan, Ph.D.
I know it's not hWnd - I've done this before, but I accidentally deleted my other DirectX project so I started this one. I know that the Windows code is exactly the same, I had to look to the books on setting up DirectDraw again, though.

Yet I don't know how to use the debugger to check for errors. Any help?
=============================All knowledge is good; only the way it is put to use is good or evil.
I have debugged your code and got it to run correctly and I'm very sure what makes the DirectDraw-program end. Take a look at these lines of code:

	DDSD.dwSize = sizeof(DDSD);	DDSD.dwFlags = DDSD_CAPS;	DDSD.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;	DDSD.dwBackBufferCount = 1;	HRESULT hResult = lpDD->CreateSurface(&DDSD, &lpDDSPrimary, NULL);


The dwBackBufferCount member is set to 1 but the member hasn't been enabled! For example the ddsCaps member has been enabled by setting DDSD.dwFlags to DDSD_CAPS. CreateSurface will check which flags are enabled and then check the corresponding DDSD members so DDSD_BACKBUFFERCOUNT must be set in DDSD.dwFlags to enable DDSD.dwBackBufferCount:

	DDSD.dwSize = sizeof(DDSD);	DDSD.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;	DDSD.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;	DDSD.dwBackBufferCount = 1;	HRESULT hResult = lpDD->CreateSurface(&DDSD, &lpDDSPrimary, NULL);


The DDSD.BackBufferCount is needed because lpDDSPrimary has been set up for a flipping chain and CreateSurface expects at least 1 backbuffer but then the DDSD.dwBackBufferCount is not enabled. An error is produced and the application exits. Hope that helped.

\Jimmy H
That is another error, but this still doesn't make the program run correctly. I know it's that SetCooperativeLevel() function, but I have no idea what I'm doing wrong. I've tried putting the screen size (1075 x 768) in place of the GetSystemMetrics() calls, but it still craps out on me. What the hell is going on here?
=============================All knowledge is good; only the way it is put to use is good or evil.
Are you sure its the SetCooperativeLevel-function? The only problem to fix I found was when setting up the DDSD and calling CreateSurface for the primary surface, so it became:
DDSD.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
I will post the code I got to work, its exactly the same as your code but I included ddutil.cpp manually, enabled the DDSD.dwBackBufferCount member as explained and removed the loading and blitting of the bitmaps since I don't have them. I put comments above these changes. Here goes:
#include <windows.h>#include <ddraw.h>#include "ddutil.h"//included the ddutil.cpp manually#include "ddutil.cpp"char szAppName[256];HWND hWnd;MSG Msg;WNDCLASSEX WndClass;HDC hDC;LPDIRECTDRAW7 lpDD;DDSURFACEDESC2 DDSD;DDSCAPS2 DDSCaps;LPDIRECTDRAWSURFACE7 lpDDSPrimary, lpDDSSecondary;LPDIRECTDRAWSURFACE7 lpDDSBlackBackground, lpDDSBitmapTest;RECT rRect;LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);bool DDSetup(void);void DDRender(void);void DDShutdown(void);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow){	strcpy(szAppName, "DirectX");	WndClass.cbClsExtra = 0;	WndClass.cbSize = sizeof(WNDCLASSEX);	WndClass.cbWndExtra = 0;	WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);	WndClass.hIcon = LoadIcon(hInstance, szAppName);	WndClass.hIconSm = LoadIcon(hInstance, szAppName);	WndClass.lpfnWndProc = WndProc;	WndClass.lpszClassName = szAppName;	WndClass.lpszMenuName = NULL;	WndClass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;	RegisterClassEx(&WndClass);	hWnd = CreateWindowEx(NULL, szAppName, szAppName, WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);	ShowWindow(hWnd, SW_SHOWDEFAULT);	UpdateWindow(hWnd);	if (!DDSetup())	{		PostQuitMessage(0);	}	while (Msg.message != WM_QUIT)	{		if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))		{			TranslateMessage(&Msg);			DispatchMessage(&Msg);		}		else		{			if (GetAsyncKeyState(VK_ESCAPE))			{				PostQuitMessage(0);			}			DDRender();		}	}	DDShutdown();	UnregisterClass(szAppName, hInstance);}LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam){	switch (Msg)	{	case WM_CLOSE:		DestroyWindow(hWnd);		break;	case WM_DESTROY:		PostQuitMessage(0);		break;	default:		break;	}	return DefWindowProc(hWnd, Msg, wParam, lParam);}bool DDSetup(void){	if (DirectDrawCreateEx(NULL, (void **)&lpDD, IID_IDirectDraw7, NULL) != DD_OK)	{		return false;	}	if (lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT) != DD_OK)	{		return false;	}	if (lpDD->SetDisplayMode(800, 600, 16, 0, 0) != DD_OK)	{		return false;	}	DDSD.dwSize = sizeof(DDSD);		//DDSD.dwFlags must be set to DDSD_CAPS | DDSD_BACKBUFFERCOUNT to enable    //both DDSD.ddsCaps and DDSD.dwBackBufferCount when calling CreateSurface	DDSD.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;	DDSD.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;	DDSD.dwBackBufferCount = 1;	if (lpDD->CreateSurface(&DDSD, &lpDDSPrimary, NULL) != DD_OK)	{		return false;	}	DDSCaps.dwCaps = DDSCAPS_BACKBUFFER;	lpDDSPrimary->GetAttachedSurface(&DDSCaps, &lpDDSSecondary);	//removed the loading of the bitmaps since I don't have them	//lpDDSBlackBackground = DDLoadBitmap(lpDD, "blackbackground.bmp", 0, 0);	//lpDDSBitmapTest = DDLoadBitmap(lpDD, "test.bmp", 0, 0);	//DDSetColorKey(lpDDSBitmapTest, CLR_INVALID);	return true;}void DDRender(void){    //removed the blt-ing of the bitmaps since I don't have them	//SetRect(&rRect, 0, 0, 800, 600);	//lpDDSSecondary->BltFast(0, 0, lpDDSBlackBackground, &rRect, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT);	//SetRect(&rRect, 0, 0, 32, 32);	//lpDDSSecondary->BltFast(0, 0, lpDDSBitmapTest, &rRect, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);	lpDDSSecondary->GetDC(&hDC);	SetBkMode(hDC, TRANSPARENT);	SetTextColor(hDC, RGB(255, 0, 0));	SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));	TextOut(hDC, 100, 100, "Hello, World!", strlen("Hello, World!"));	lpDDSSecondary->ReleaseDC(hDC);	lpDDSPrimary->Flip(NULL, DDFLIP_WAIT);}void DDShutdown(void){	if (lpDDSBlackBackground)	{		lpDDSBlackBackground->Release();		lpDDSBlackBackground = NULL;	}	if (lpDDSSecondary)	{		lpDDSSecondary->Release();		lpDDSSecondary = NULL;	}	if (lpDDSPrimary)	{		lpDDSPrimary->Release();		lpDDSPrimary = NULL;	}	if (lpDD)	{		lpDD->Release();		lpDD = NULL;	}}

I hope it helped this time. Believe me, this code works, i just compiled and run it. If not its not the code that's the problem then its probably the video card not supporting something or a linker that does not tell when there are linking errors. What compiler/environment do you use?

\Jimmy H
Quote:Original post by dist0rted
I've tried putting the screen size (1075 x 768)

For real? Because I doubt you'd find many video cards actually supporting that resolution. I'm sure you meant 1024x768. But I thought I'd mention it just to make sure.
JRA GameDev Website//Bad Maniac

This topic is closed to new replies.

Advertisement