Sign in to follow this  
dist0rted

DirectDraw 7 Setup Problem

Recommended Posts

dist0rted    100
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.

Share this post


Link to post
Share on other sites
BigR    138
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

Share this post


Link to post
Share on other sites
dist0rted    100
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.

Share this post


Link to post
Share on other sites
BigR    138
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

Share this post


Link to post
Share on other sites
dist0rted    100
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?

Share this post


Link to post
Share on other sites
Dim_Yimma_H    557
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

Share this post


Link to post
Share on other sites
dist0rted    100
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?

Share this post


Link to post
Share on other sites
Dim_Yimma_H    557
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

Share this post


Link to post
Share on other sites
Bad Maniac    252
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.

Share this post


Link to post
Share on other sites
dist0rted    100
It has to be something with my moniter, because that code didn't work either. Also, I tried sending the .exe to a friend over MSN and he got the same results - so it might be something I'm doing at compilation. I'm using MSVC++ .NET 2003.

Share this post


Link to post
Share on other sites
Dim_Yimma_H    557
Some time ago I had a motherboard with a built-in video card (shared system/video memory) and I wasn't able of getting any of my own fullscreen DirectDraw apps to run on it, I doubt that's the problem in this case though. The solution was to create the backbuffer explicitly with the CreateSurface method (no flipping chain) and use Blt instead of Flip (windowed mode, system memory blt, always works).

If you haven't done it already you may want to try the different display modes (resolution, bit-depht and frequancy) your video card AND monitor supports with the SetDisplayMode method.

I have no experience of VC++ .NET but I had some problems compiling DirectDraw 7 apps under VC++ 6.0 because it always used its older built-in DirectDraw libraries even though I specified the exact path. Now I use Bloodshed Dev-C++ 4.9.9.0 and it compiles without problems. Probably I just had some settings wrong though.

Share this post


Link to post
Share on other sites
dist0rted    100
I know for certain that it's the SetCooperativeLevel function by turning the DDSetup() into an int function and having the SetCooperativeLevel() function return the value 2 - and I called a MessageBox() if DDSetup() == 2.

Share this post


Link to post
Share on other sites
Evil Steve    2017
I'm surprised noones mentioned this yet. It'll give you a lot more information if you check the error code:

HRESULT hResult;

hResult = lpDD->SetCooperativeLevel(hWnd, DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
if(FAILED(hResult))
{
// Log the hResult value
return false;
}



Incidently, you should always use the FAILED() and SUCCEEDED() macros instead of checking for DD_OK.

In the above code, what is the value of hResult? Also, do you have the debug DirectX runtimes installed, with the debug output set to maxiumum? DirectX should give you information in the debug window when a function fails if you're using the debug runtimes.

Share this post


Link to post
Share on other sites
dist0rted    100
I know it's the damn SetCooperativeLevel function... I've debugged my ass off and I don't need to be shunned as if I'm an idiot just because I'm not showing every little tiny thing that I try.

(Yes I'm getting frustrated.)

Share this post


Link to post
Share on other sites
Dave Hunt    4872
Quote:
Original post by dist0rted
I know it's the damn SetCooperativeLevel function... I've debugged my ass off and I don't need to be shunned as if I'm an idiot just because I'm not showing every little tiny thing that I try.

(Yes I'm getting frustrated.)


Evil Steve's point was that if you check the return code from the SetCooperativeLevel call, it will tell you exactly why it is failing. Enter the return code into the DirectX Error Lookup tool to get a human translation of the code.

Share this post


Link to post
Share on other sites
RhoneRanger    100
I would strongly suggest that you do what Steve said, but on another note (I am not sure if I am remembering this correctly or not. )

Doesn't a fullscreen window in DX7 need to be overlapped?

CreateWindowEx(NULL, szAppName, szAppName, WS_POPUP|WS_OVERLAPPED (or whatever it is) ...



Share this post


Link to post
Share on other sites
Bad Maniac    252

if(FAILED(IDirectDraw_SetCooperativeLevel(Device,Window_Handle, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT)))
{
...
}





That's the line I use, Device is the Directdraw device (duuh) and Window_Handle is of course a hwnd to the window. That has worked for me some thousand times.

I't sthe same line You use, so there's no direct problem with the code. You need to log the return code from every call in your DDinit function, and find out what's wrong. There is nothing wrong with your SetCooplevel call, if it fails it's because of something failing before it. check the returns just like the previous posters said.

And no, I just tested with my app, and you don't have to specify WS_OVERLAPPEDWINDOW for it to work.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this