(edit) Code was too long for forum. I'm splitting it in 1/2

I'm currently working on a Direct3D class that simplifies D3D, so I can use it to make games, applications, etc.

I started on it yesterday, got it to work so it draw triangles with a different color on each vertex, and made a function that draws 2 triangles to make a quadrilateral(or at least something with 4 vertexes).

Now, before I started on making textures for the triangles/quads, I put better error handling in. Everything seemed fine. So I went and started a few changes, so I could have textures. I changed this line:

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZRHW |D3DFVF_DIFFUSE )

to

#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZ |D3DFVF_TEX1 )

I updated the structure. I ran the program to see if it still worked(which it shouldn't), and it didn't, so everything went as planned. I updated the rest of the program, and when I was done, bad things happened. I went and put debug info all around the program(in addition to the message box that popped up whenever a function failed), and tried to determine the source of the problem. A few hours later, I found that for some reason, the device was lost as soon as it was created(or at least when I tried to render triangles). Interestingly, the device wasn't lost before a particular function was called, but when it was called, at the start of the function(before any code was really executed there), it was lost.

Here's the full code to the program. I think I broke it more than it was before, but does anyone have any idea what's wrong with it:

Main header file:

#include <windows.h>
#include <vector>
#include <d3d9.h>
#include <d3dx9.h>
#define DIRECTINPUT_VERSION 0x0800
#include <dinput.h>
#include <time.h>
#include <stdio.h>
using namespace std;
extern HWND hwnd;
extern HINSTANCE hinstance;
extern bool running;
char *GetError(int error);
#define D3DFVF_CUSTOMVERTEX	(D3DFVF_XYZRHW |D3DFVF_DIFFUSE )
struct VERTEX
{
    FLOAT x, y, z, rhw; // The transformed position for the vertex
    DWORD color;        // The vertex color
};


class Direct3D {
	IDirect3D9 *d3d;
	IDirect3DDevice9 *d3ddevice;
	D3DDISPLAYMODE displaymode;
	int error;
	LPDIRECT3DVERTEXBUFFER9 vertex_buffer;
	vector<IDirect3DTexture9 *> surfaces;
public:
	Initialize(void);
	void StartRender(void);
	void DrawTriangle(VERTEX[3]);
	void DrawSquare(VERTEX[4]);
	int LoadSprite(char *file);
	void DrawSprite(int,int,int,int,int);
	void EndRender(void);
	void UnloseDevice(void);
	void ErrorHandle(int,char *);
	~Direct3D(void);
	bool Check(void);
};

class DirectInput {
	IDirectInput8 *dinput;
	IDirectInputDevice8 *keyboard;
	IDirectInputDevice8 *mouse;
	DIDEVCAPS mouse_data;
	DIDEVCAPS keyboard_data;
	unsigned char *buffer;
	HANDLE mouse_event;
	DIMOUSESTATE mouse_state;
	
public:
	int mouse_x,mouse_y;
	Initialize(void);
	int KeyPressed(int);
	int MousePressed(int);
	void Update();

	~DirectInput(void);
	
};

Direct3D class:

#include "main.h"

/**************************
Some comments:

  1. I use ErrorHandle() alot here. It can be confusing to understand what a section of code is doing when it's like this:

			ErrorHandle(function here,"Message);
	
	 All it does it check the return value of function for errors, and does what it needs. Tab the left and right of the
	 ErrorHandle function if it's difficult to understand the code since it's packed between a Errorhandle( and a ,"message");

  2. What this code is, is the source code for a Direct3D class.




**************************/
Direct3D::Initialize(void) {
	error = 0;
	char *message = NULL;
	if (NULL == (d3d = Direct3DCreate9(D3D_SDK_VERSION))) {//Creates D3D object
		MessageBox(NULL,"Couldn't create D3D","Error",0);
		running = false;//Program can't work if D3D isn't working
	}
	if (running) {

		if (FAILED(d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&displaymode))) {
			MessageBox(NULL,"Couldn't get info on your display mode adapter.","Environment = teh screwed",0);
			running = false;
		}
		D3DPRESENT_PARAMETERS d3dpp; //Get parameters working
		ZeroMemory( &d3dpp, sizeof(d3dpp) );
		d3dpp.Windowed = FALSE;
		d3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
		d3dpp.BackBufferFormat = displaymode.Format;
		d3dpp.BackBufferWidth = 640;
		d3dpp.BackBufferHeight = 480;
		d3dpp.BackBufferCount = 2;
		d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
		d3dpp.MultiSampleQuality = 0;
		d3dpp.hDeviceWindow = hwnd;
		d3dpp.EnableAutoDepthStencil = TRUE;
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
		d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
		d3dpp.FullScreen_RefreshRateInHz = 0;
		d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;


		if (running) {
			//Test if we can make a HAL device
			if (SUCCEEDED(error = d3d->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,displaymode.Format,displaymode.Format,TRUE))) {
				if( FAILED( error = d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,//Make device for D3D
					D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp, &d3ddevice ) ) ) {//Continuing...
					message = GetError(error);
					MessageBox(NULL,"D3D device initialization failed",message,0);
					running = false;
				}
			} else {
				message = GetError(error);
				MessageBox(NULL,"Hardware Abstraction Layer device can't be made on your comp",message,0);
				running = false;
			}
		}
	}
	
	error =  d3ddevice->CreateVertexBuffer(3*sizeof(VERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT,&vertex_buffer,NULL);
	ErrorHandle(error,"Couldn't create vertex buffers");
	 // We're going to handle lighting ourselves, for now
    d3ddevice->SetRenderState( D3DRS_LIGHTING, FALSE );

    // Turn on the zbuffer
    d3ddevice->SetRenderState( D3DRS_ZENABLE, TRUE );
	

	if (!running) {
		MessageBox(NULL,"Code ain't working. Direct3D ain't working. No game for you!","Exiting...",0);
		PostQuitMessage(0);
	}
}
Direct3D::~Direct3D(void) {
	if( d3ddevice != NULL)
		d3ddevice->Release();
	if( d3d != NULL)
		d3d->Release();

}

void Direct3D::StartRender(void) {
	
	d3ddevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
	error = d3ddevice->BeginScene();
	ErrorHandle(error,"Couldn't start the render");
	
}
char *GetError(int error) {
	switch (error) {
	case D3DERR_INVALIDCALL: return "Invalid function call";
	case D3DERR_NOTAVAILABLE: return "Comp sucks too much to make device";
	case D3DERR_OUTOFVIDEOMEMORY: return "No more memory for comp. Get a new video card.";
	case E_OUTOFMEMORY: return "No more memory for comp. Grab some more RAM somewhere.";
	case D3D_OK: return "Everything went fine. Error function called for no reason. This is prolly' a bug if displayed.";
	case D3DERR_DRIVERINTERNALERROR: return "Driver had an internal error. Might wanna' fix that, cause' this game ain't workin' till' you do";
	case D3DERR_DEVICELOST: return "Lost the device";
	}
	return "Unknown error occured.";
}

void Direct3D::DrawTriangle(VERTEX vertexes[3]) {
	VOID* pVertices;
	//Lock vertex buffers
	ErrorHandle(vertex_buffer->Lock( 0, sizeof(VERTEX)*3, (void**)&pVertices, 0 ),"I couldn't lock the vertex buffers.");
	memcpy( pVertices, vertexes, sizeof(VERTEX)*3 );
	//Unlock the vertex buffers, set stream sources, set FVF, and draw primitives. Pass return value to error handler.
	ErrorHandle(vertex_buffer->Unlock(),"I couldn't unlock vertex buffers. They don't like me....");
	ErrorHandle(d3ddevice->SetStreamSource( 0, vertex_buffer, 0, sizeof(VERTEX) ),"I couldn't set stream source");
	ErrorHandle(d3ddevice->SetFVF( D3DFVF_CUSTOMVERTEX ),"I couldn't set Flexible Vertex Format(FVF) for vertexes");
	ErrorHandle(d3ddevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ),"Couldn't draw triangles");
}

void Direct3D::EndRender(void) {
	ErrorHandle(d3ddevice->EndScene(),"Couldn't end rendering.");
	ErrorHandle(d3ddevice->Present(NULL,NULL,NULL,NULL),"Couldn't draw vertexes on screen");
}

void Direct3D::DrawSquare(VERTEX vertexes[4]) {
	VERTEX temp[3];
	temp[0] = vertexes[0];
	temp[1] = vertexes[1];
	temp[2] = vertexes[2];
	DrawTriangle(temp);
	temp[0] = vertexes[1];
	temp[1] = vertexes[0];
	temp[2] = vertexes[3];
	DrawTriangle(temp);
}

int Direct3D::LoadSprite(char *file) {
	IDirect3DTexture9 *surface;
	if (FAILED(error = D3DXCreateTextureFromFile(d3ddevice,file,&surface))) {
		running = false;
		MessageBox(NULL,"Couldn't load sprite",GetError(error),0);
	}
	return surfaces.size();
	surfaces.push_back(surface);
}

void Direct3D::DrawSprite(int number,int x,int y, int width,int height) {
	
}

bool Direct3D::Check(void) {
	if (FAILED(d3ddevice->TestCooperativeLevel())) return true;
	return false;
}
void Direct3D::ErrorHandle(int error,char *message) {
	bool normal = false;
	switch (error) {
	case D3DERR_INVALIDCALL: normal = true;break;
	case D3DERR_NOTAVAILABLE:normal = true;break;
	case D3DERR_OUTOFVIDEOMEMORY:normal = true;break;
	case E_OUTOFMEMORY:normal = true;break;
	case D3D_OK:break;
	case D3DERR_DRIVERINTERNALERROR:normal = true;break;
	case D3DERR_DEVICELOST: normal = true;break;
	default: normal = true;break;
	}
	if (normal) {
		running = false;
		MessageBox(hwnd,message,GetError(error),0);
	}
}

DirectInput class(probably unrelated, but it's still part of the code):

#include "main.h"

DirectInput::Initialize(void) {
	int error;
	char *message;
	buffer = new unsigned char[256];
	//Make DirectInput8
	if (SUCCEEDED(error = DirectInput8Create(hinstance,DIRECTINPUT_VERSION,IID_IDirectInput8,(void**)&dinput,NULL))) {
		if (SUCCEEDED(error = dinput->CreateDevice(GUID_SysKeyboard,&keyboard,NULL))) {//Make keyboard device
			if (SUCCEEDED(error = dinput->CreateDevice(GUID_SysMouse,&mouse,NULL))) {//Make mouse device
				//Add more stuff here
			} else {//If it breaks, here's the errors for each of the 3 'if' statements.
				message = GetError(error);
				MessageBox(NULL,"Couldn't create mouse device",message,0);
				running = false;
			}
		} else {
			message = GetError(error);
			MessageBox(NULL,"Couldn't create keyboard device",message,0);
			running = false;
		}
	} else {
		message = GetError(error);
		MessageBox(NULL,"Couldn't create DirectInput",message,0);
		running = false;
	}
	if (FAILED(error = keyboard->SetDataFormat(&c_dfDIKeyboard))) {
		message = GetError(error);
		MessageBox(NULL,"Couldn't set keyboard data format",message,0);
		running = false;
	}
	if (FAILED(error = mouse->SetDataFormat(&c_dfDIMouse))) {
		message = GetError(error);
		MessageBox(NULL,"Couldn't set mouse data format",message,0);
		running = false;
	}
	if (FAILED(error = keyboard->SetCooperativeLevel(hwnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) {
		message = GetError(error);
		MessageBox(NULL,"Couldn't set keyboard cooperative level",message,0);
		running = false;
	}
	if (FAILED(error = mouse->SetCooperativeLevel(hwnd,DISCL_FOREGROUND | DISCL_NONEXCLUSIVE))) {
		message = GetError(error);
		MessageBox(NULL,"Couldn't set mouse cooperative level",message,0);
		running = false;
	}
	mouse_event = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (mouse_event == NULL) {
		MessageBox(NULL,"Couldn't create an event for mouse device","Ruh-roh...",0);
		running = false;
	}
	if (FAILED(error = mouse->SetEventNotification(mouse_event))) {
		MessageBox(NULL,"Couldn't associate mouse interrupt with DirectInput device","Ruh-roh...",0);
		running = false;
	}
	keyboard->Acquire();
	mouse->Acquire();
	if (!running) {
		MessageBox(NULL,"Couldn't get DirectInput to work. No game for you!","Exiting...",0);
		PostQuitMessage(0);
	}	
	mouse_x = 0;
	mouse_y = 0;
}

DirectInput::~DirectInput(void) {
	if (buffer) delete [] buffer;
	mouse->Unacquire();
	keyboard->Unacquire();
	if (keyboard != NULL)
		keyboard->Release();
	if (mouse != NULL)
		mouse->Release();
	if (dinput != NULL) 
		dinput->Release();
}

void DirectInput::Update() {
	keyboard->GetDeviceState(sizeof(char)*256,buffer);
	mouse->GetDeviceState(sizeof(mouse_state),(LPVOID)&mouse_state);
	mouse_x += mouse_state.lX;
	mouse_y += mouse_state.lY;

}

int DirectInput::KeyPressed(int key) {
	return buffer[key] & 0x80;
}

int DirectInput::MousePressed(int button) {
	return mouse_state.rgbButtons[button] & 0x80;
}
#include "main.h"
HINSTANCE hinstance;
HWND hwnd;
const char g_szClassName[] = "WindowClass";
int ncmdshow;
bool running = true;
#define MOUSE_LEFT 0
#define MOUSE_RIGHT 1
Direct3D direct3d;
DirectInput directinput;
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch(msg)
    {
        case WM_CLOSE:
            DestroyWindow(hwnd);
			running = false;
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
			running = false;
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}
HWND MakeWindow(void) {
	WNDCLASSEX wc;
	 //Register the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hinstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    //Create the Window
	RECT DesktopSize;
	GetClientRect(GetDesktopWindow(),&DesktopSize);
    hwnd = CreateWindow(g_szClassName,"Window",NULL,0,0,DesktopSize.right,DesktopSize.bottom,NULL,NULL,hinstance,NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, "Window Creation Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, ncmdshow);
    UpdateWindow(hwnd);
	return hwnd;
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hprevinstance,LPSTR lpcmdline,int nshowcmd) {
	char buffer[256];
	VERTEX vertexes[3] = {
		{0.0f,0.0f,1.0f,1.0f,0xffff0000},
		{500.0f,0.0f,1.0f,1.0,0xff00ff00},
		{250.0f,250.0f,1.0f,1.0f,0xff0000ff}};
	for (ncmdshow = 0;ncmdshow<256;ncmdshow++) 
		buffer[ncmdshow] = 0;
	ncmdshow = nshowcmd;
	hinstance = hInstance;
	MakeWindow();
	directinput.Initialize();
	direct3d.Initialize();

	//int num = direct3d.LoadSprite("C:\\Documents and Settings\\Owner.YOUR-US67PI6LUV\\Desktop\\Pictures\\dimension-gate.jpg");
	MSG msg;

	
	while (running) {
		directinput.Update();

		while (PeekMessage(&msg,hwnd,0,0,PM_REMOVE)) {
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			if (msg.message == WM_CLOSE || msg.message == WM_DESTROY) running = false;
		}
		if (directinput.KeyPressed(DIK_ESCAPE)) PostQuitMessage(0);
		direct3d.StartRender();
		direct3d.DrawTriangle(vertexes);
		direct3d.EndRender();
		//PostQuitMessage(0);
	}
	return 0;
}

I believe that's it. Be sure to link with dxguid.lib, dinput8.lib, d3d9.lib, and d3dx9.lib.

It could use a few more comments, but I think it's pretty obvious what it all does, at least if you know DirectX.

I've been debugging and trying almost everything I could think of for about 5 hours now. Any help would be appreciated.

Anyone? I found it crashes during the while loop where PeekMessage() is, but I still haven't been able to fix it.

This article has been dead for over six months. Start a new discussion instead.