Requesting advice on my GUI code

Started by
5 comments, last by nuvem 19 years, 4 months ago
In my quest to create the greatest RPG of all time ;) I wanted to code a GUI. Well, maybe it isn't for the superRPG, I really am taking this on as a learning experience. I have gotten to a point where I can compile this bad boy and get pretty much want I wanted to get, but with memory leaks (I assume) everywhere, problems left and right, i am sure, and so on...as I said, a learning experience. So I have deceided to put this up, especially since I need to hear that I am doing something right (I hope) to keep my morale up. I figure who to show this to but people who know what they are doing and want to help someone learn. I apologize for the size, basically these windows are, in order: Main GUI Interface class interface Main GUI Interface class implementation Drawing class interface Drawing class implementation Button object interface Button object implementation The homemade linked list I whipped up to keep track of all the children. I would be BEYOND grateful, near enough to pledge my firstborn (not quite though...maybe when someone reviews my 3-d super dooper engine). Seriously, I would be so helpful if someone could take a little time and give me a bit of guidance on what I do wrong, what I do right. I think the code is understandable...I hope it is anyways. Also, I zipped up the whole damn thing and stuck it on my school site... I hope my only html skills still are up to par... GUI.zip One thing, I am by no means asking anyone to debug my stuff or tell me how to program. This thing does work. I get a button a moving mouse, static text and an update of the mouse location. I just really am asking if someone can take a look and tell me where I am moving in the right direction and where I am moving in the wrong direction. Thanks again! Much Obliged DrMol The Main GUI interface

class CWindow_GUI  
{
public:
//////////////
//Boring stuff
//////////////
	CWindow_GUI();
	virtual ~CWindow_GUI();
	
	virtual void Init( );
	void SetDXSystem( CDXDraw *DXControl );
	//static CDXDraw* 
	//CDXDraw *GetDXSystem( );
	
//////////////////////
//Subwindows and stuff
//////////////////////
	CWindow_GUI *GetParentWindow( );
	bool AddWindow( CWindow_GUI *window );
	void DeleteWindow( CWindow_GUI *window );
	void SetParentWindow( CWindow_GUI *window );
	void BringToTop( );
	bool CleanUp( );
//	void SetText( CTextGrinder cTG );

/////////////
//Visibility
/////////////
	void SetVisible( bool vis = true );
	bool GetVisible( ) const;

	void SetActive( bool Act = true );
	void GetActive( );
/////////////
//Positioning
////////////
	void SetPos( long x, long y );
	void SetSize( long Width, long Height );
	bool ClickInside( int x, int y);

	int MouseWindow( int MouseX, int MouseY, short button, short prevstate  );
	
	//Call this is mouse polling indicates a change of state
	int MouseStateChange( int MouseX, int MouseY, short button, short prevstate );


//	int VirtXPixel( int virtx );
//	int VirtYPixel( int virty );
	virtual void Test( int a );

/////////////////////////////////////
//Window creation
////////////////////////////////////
	int RenderAll( );
	virtual int RenderWindow( );
	
////////////////////////////////////
//Messaging, mechanics
////////////////////////////////////
	virtual void GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState );
	virtual void GM_CHILDCLICKED( );// const;

////////////////////////////////////
//Messaging, user defined
////////////////////////////////////
	virtual void GM_USERACTION_MOUSE( int Btn );
	
//	virtual void GM_ACTIVATED( );
	
	ConvertXToMS( int X );
	ConvertYToMS( int Y );

	

private:
	bool GUIWindowVisible;
	bool Visible;
	int index;
	CWindow_GUI *winParent;
	ArrayPtrCtrl< CWindow_GUI* > subWins;	//the array of pointers to subwindows
	bool Act;

protected:
//	CTextGrinder cText;
	CDXDraw *DXControl;
	SWindowCoord sCoord;
	bool TWindow;
	int ele;
	bool CTE( );
	
};


The Main class implementation

CWindow_GUI::CWindow_GUI()
{
	TWindow = false;
	winParent = NULL;	
	index = 0;
	sCoord.Height = 300;
	sCoord.Width = 300;
	sCoord.pos.top = 0;
	sCoord.pos.left = 0;


}

CWindow_GUI::~CWindow_GUI()
{
	winParent = NULL;	//no parent.  
	subWins.~ArrayPtrCtrl( );//Delete all subwindows
}

CWindow_GUI *CWindow_GUI::GetParentWindow( )
{
	return winParent;
};

bool CWindow_GUI::AddWindow( CWindow_GUI *window )
{
	//Make sure window is valid
	if ( window == NULL )
		return false;
	
	subWins.Add( window );//subWins
	window->SetParentWindow( this );

	if ( subWins.IsEmpty( ) == true )
		return false;

return true;
}

void CWindow_GUI::SetParentWindow( CWindow_GUI *window)
{
	winParent = window;
}

void CWindow_GUI::DeleteWindow( CWindow_GUI *window )
{
	subWins.Delete( window );
	
	window->SetParentWindow( NULL );
};

//////////////////////
void CWindow_GUI::SetVisible( bool vis )
{
	Visible = vis;
};

bool CWindow_GUI::GetVisible( ) const
{
	return Visible;
};

/////////////////////////

void CWindow_GUI::SetSize( long Width, long Height )
{
	sCoord.Width = Width;
	sCoord.Height = Height;
	sCoord.pos.right = Width + sCoord.pos.left;
	sCoord.pos.bottom = Height + sCoord.pos.top;

	CWindow_GUI *cGW = NULL;
	cGW = GetParentWindow( );
/*	if( cGW != NULL )
	{
		if( cGW->sCoord.pos.bottom < sCoord.pos.bottom )
		{
			sCoord.pos.top = cGW->sCoord.pos.bottom - sCoord.Height;	//translate up
			sCoord.pos.bottom = cGW->sCoord.pos.bottom;
		}
		if( cGW->sCoord.pos.right < sCoord.pos.right )
		{
			sCoord.pos.left = cGW->sCoord.pos.right - sCoord.Width;	//translate left
			sCoord.pos.right = cGW->sCoord.pos.right;
		}
	
	};
*/
}

void CWindow_GUI::SetPos( long x, long y )
{
	sCoord.pos.left = x;
	sCoord.pos.top = y;
	
	CWindow_GUI *cGW = NULL;
	cGW = GetParentWindow( );
	/*if( cGW != NULL )
	{
		if( cGW->sCoord.pos.left > sCoord.pos.left )
				sCoord.pos.left = cGW->sCoord.pos.left;
		if( cGW->sCoord.pos.top > sCoord.pos.top )
			sCoord.pos.top = cGW->sCoord.pos.top;		
	};*/

	sCoord.pos.right = sCoord.Width + sCoord.pos.left;
	sCoord.pos.bottom  = sCoord.Height + sCoord.pos.top;

}

//////////////////////////////////////////
void CWindow_GUI::BringToTop( )
{
	winParent->DeleteWindow( this );
	winParent->AddWindow( this );

}
/*
int CWindow_GUI::VirtXPixel( int virtx )
{
//	int width = (cWindow_Parent) ? cWindow_Parent->getpos().getwidth() : getscreendims().getwidth();
//    return((int)((double)virtx*(double)width/GUI_SCALEX));
}
*/

void CWindow_GUI::Init( )
{
//	Font = "Arial";
//	Point = 12;	
//	index = 0;
}

int CWindow_GUI::RenderWindow( )
{
	return 0;
}


int CWindow_GUI::RenderAll( )
{
	RenderWindow( );	
	
	int ind = subWins.GetCount( );	//Creates a starting spot for tree
	CWindow_GUI *cPtr;	//Create a basic window pointer
	
	if( subWins.GetCount( ) < 0 ) return false;	//error

	if( ind == 0 )	//No more children
	{
		return 0;
	};

	while ( ind >= 0 )	//Go through rest of children
	{
		cPtr = subWins.GetDataBW( ind );
		cPtr->RenderAll(  );
		ind--;
	};


  return -1;

};

void CWindow_GUI::SetDXSystem( CDXDraw *cDXDraw )
{
	DXControl = cDXDraw;
};
/*
CDXDraw *CWindow_GUI::GetDXSystem( )
{
	return DXControl;
}
*/
int CWindow_GUI::MouseWindow( int MouseX, int MouseY, short button, short prevstate  )
{
	int ind = subWins.GetCount( );	//Creates a starting sport for tree
	CWindow_GUI *cPtr;	//Create a basic window pointer
	
	if( subWins.GetCount( ) < 0 ) return false;	//error

	if( subWins.GetCount( ) == 0 )	//No more children
	{
		GM_MOUSEACTION( MouseX, MouseY, button, prevstate );	
		return 0;
	};

	while ( ind > 0 )	//Go through rest of children
	{
		cPtr = subWins.GetDataBW( ind );
		cPtr->MouseWindow( MouseX, MouseY, button, prevstate );
		ind--;
	};

return true;	
}

bool CWindow_GUI::ClickInside( int x,  int y )
{
	bool xVal, yVal;
	xVal = yVal = false;

	if( x >= sCoord.pos.left && x <= sCoord.pos.right )
		xVal = true;
	if( y >=sCoord.pos.top && y <= sCoord.pos.bottom )
		yVal = true;

	if( xVal == true && yVal == true )
		return true;

	return false;
};


void CWindow_GUI::GM_CHILDCLICKED( ) //const
{

	BringToTop( );
};

int CWindow_GUI::MouseStateChange( int MouseX, int MouseY, short button, short prevstate )
{
	//Something has happened with the mouse
	
	//if ( button is up ) and move = true, let windows handle it

	//else, a button state has changed
	//Get the window that it happened in, recusion here
	MouseWindow( MouseX, MouseY,  button,  prevstate  );

	//Let that window know that it has been clicked and pass all mouse info, button, last button state etc, hand the problem off

	return 0;


};


bool CWindow_GUI::CleanUp( )
{
	
	CWindow_GUI *cPtr = NULL;
	
		//Number of elements in the list

//	MessageBox( hWnd, "Start Debug", "CLEANUP", MB_OK );
		
//	if( index > subWins.GetCount( ) ) //error
//		return false;

		
	index++;		//bump the thing
	
	if ( subWins.IsValid( index - 1 ) == true &&  
		subWins.IsEmpty( ) == false )//this window has children
	{
		//get the pointer to the last element
		//Bump the count since we dont start with index = 0

		cPtr = subWins.GetData( index - 1 );
		cPtr->CleanUp( );
	}
	else if ( subWins.IsEmpty( ) == false && subWins.IsValid( index -1 ) == false )
	{
		subWins.DeleteAll( );
		cPtr = winParent;
		if ( cPtr == NULL )	//this window has no parent
		{
			index = 0;		//So reset the counter
			return false;			//End the function
		};


//		cPtr = winParent;
	}
	else	//no children
	{
		cPtr = winParent;
//		return 0;	

		if ( cPtr == NULL )	//this window has no parent
		{
			index = 0;		//So reset the counter
			return false;			//End the function
		};

	};

	cPtr->CleanUp( );	//Continue the parents render function
			
return true;
}


void CWindow_GUI::GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState )
{
	//Do nothing	
}


void CWindow_GUI::Test( int a )
{

}

void CWindow_GUI::GM_USERACTION_MOUSE( int Btn )
{

}


The Drawing class interface, draws all the objects. Wrapped not inplemented seperatley

class CDXDraw  
{
friend class CWindow;

public:
	CDXDraw( );
	virtual ~CDXDraw();

	bool Init( IDirect3DDevice8 *GraphicSystem, HWND h_Wnd );
	bool PrepareToDraw( );
	
	///////////////////////////////////////////////
	//Window Drawing functions
	//////////////////////////////////////////////
	bool DrawWindow( RECT Coord, struct SWinImages );
	bool DrawStatic( RECT Coord, STxtInf sTextInf, char *Text  );
	bool DrawButton( RECT Coord, SButtonInf sBI );
	
	int ScaleX( int x );
	int ScaleY( int y );
	void ScaleRect( RECT &r );
	
	/*
	bool DrawButton( RECT winRect, SButtonInf sBI, LPDIRECTDRAWSURFACE7 lpDDS );
	bool ButtonBlit( RECT winRect, LPDIRECTDRAWSURFACE7 lpDDS );
*/
private:
	///////////////////////////////////////////////
	//Window Drawing functions
	//////////////////////////////////////////////
	IDirect3DDevice8 *DXDevice;
	ID3DXFont *DXFont;
	LOGFONT lf;

	HWND hWnd;

	CD3DFont *hFont;

	bool Init2D( );
	bool DrawButtonAuto( RECT Coord, SButtonInf sBI );
	bool DrawBorderedBox( RECT Coord, SButtonInf sBI, bool NoBox = false );
	int SysWidth,  SysHeight;
	
	RECT windowSize;

};

The Drawing class implementation, this needs the most work, i guess


CDXDraw::CDXDraw( )
{
	SysWidth=800;
	SysHeight =600;
	DXFont = NULL;
}

CDXDraw::~CDXDraw()
{
	if( hFont )
	{
		hFont->DeleteDeviceObjects( );
		delete hFont;
		hFont = NULL;
	}
	DXDevice->Release( );

}

bool CDXDraw::Init( IDirect3DDevice8 *GraphicsSystem, HWND h_Wnd )
{
	if( ( DXDevice = GraphicsSystem ) == NULL )
		return false;

	hWnd = h_Wnd;

return true;
}


bool CDXDraw::DrawWindow( RECT Coord, SWinImages sWI)
{
	bool BGFill = false;
	LPDIRECT3DTEXTURE8 Tex = NULL;
	
	//ERROR CHECKING
	if( Coord.right < Coord.left )
		return false;
	if( Coord.bottom < Coord.top )
		return false;
	if( DXDevice == NULL )
		return false;

	SButtonInf sBI;
	//DRAW THE BORDERS
	if( sWI.BordersOn == true )
	{
		
		sBI.BorderWidth = 3;
		sBI.DrawUp = true;
		DrawBorderedBox( Coord, sBI, true );
	}
	else sBI.BorderWidth = 0;


	Coord.bottom -= sBI.BorderWidth;
	Coord.top += sBI.BorderWidth;
	Coord.left += 2 * sBI.BorderWidth;
	Coord.right -= sBI.BorderWidth;


	
	//SEE IF WE ARE USING A BG COLOR OR AN IMAGE
	if( sWI.BG == NULL )
		BGFill = TRUE;

	if( BGFill == FALSE )
	{	
		if( FAILED ( D3DXCreateTextureFromFileEx( DXDevice, sWI.BG, 0, 0, 0, 0,
									D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
									D3DX_DEFAULT, 0, NULL, NULL, &Tex ) ) )
			BGFill = TRUE;
		
	}
	
	//SET THIS THING UP AS A BILLBOARD
	D3DXMATRIX Mtrx2D;
	D3DXMATRIX Identity;

	D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth,  (float) SysHeight, 0.0f, 1.0f );
	D3DXMatrixIdentity( &Identity );

	DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
	DXDevice->SetTransform( D3DTS_WORLD, &Identity );
	DXDevice->SetTransform( D3DTS_VIEW, &Identity );

	LPDIRECT3DVERTEXBUFFER8 Vertices = NULL;



	//WORK OUT THE SIZES
	float Width = (float) ( Coord.right ) - (float) ( Coord.left );
	float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
		ScaleRect( Coord );

	//SEND THE VERTICES TO THE BUFFER AND SET UP THE INFO
	DXDevice->CreateVertexBuffer( 8 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &Vertices );

	PARAMETERS *pVertices = NULL;

	

	Vertices->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[1].color = pVertices[2].color = pVertices[3].color = sWI.color;


	pVertices[0].x = pVertices[3].x = -Width / 2.0f; 
	pVertices[1].x = pVertices[2].x = Width/2.0f ; 

	pVertices[0].y = pVertices[1].y = Height/2.0f;
	pVertices[2].y = pVertices[3].y = -Height/2.0f;

	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;
///////////////////////////////////////////////////////
	pVertices[4].x = pVertices[7].x = -Width / 2.0f ;
	pVertices[5].x = pVertices[6].x = Width / 2.0f;
	 
	
	pVertices[4].y = pVertices[5].y = ( Height * .1 ) / 2 + ( Height / 2 ) - ( ( Height * .1) / 2 );
	pVertices[6].y = pVertices[7].y = -( Height * .1 ) / 2 + ( Height / 2 ) - ( (Height * .1) / 2 );

	pVertices[4].z = pVertices[5].z = pVertices[6].z = pVertices[7].z = 0.0f;

	pVertices[4].color = pVertices[5].color = pVertices[6].color = pVertices[7].color = sWI.TitleColor;

	Vertices->Unlock( );
	//TODO: put lock and unlock only once in rendering sequence

	//MOVE IT BASED ON ENTERED COORDS
	D3DXMATRIX Position;
	D3DXMatrixTranslation( &Position, 
							-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left, 
							( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top , 
							0.0f 
							);
	
	DXDevice->SetTransform( D3DTS_WORLD, &Position );

	//RENDER IT TO THE BACK BUFFER
	if( BGFill == FALSE )
		DXDevice->SetTexture( 0, Tex );

	DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
	DXDevice->SetStreamSource( 0, Vertices, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
	
	if( BGFill == TRUE )
	{
		DXDevice->SetTexture( 0, NULL );
		if( Tex != NULL )
			Tex->Release( );	
	}

//////////////////////////////////////////////////////////////

	if( sWI.TitleBar == true )
	{
		if( sWI.TitleLoc != NULL )
		{
			
			D3DXCreateTextureFromFileEx( DXDevice, sWI.TitleLoc, 0, 0, 0, 0,
									D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT,
									D3DX_DEFAULT, 0, NULL, NULL, &Tex );
			
			DXDevice->SetTexture( 0, Tex );
		};
	
		DXDevice->SetStreamSource( 0, Vertices, sizeof( PARAMETERS ) );
		DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 4, 2 );

	

		sWI.TitleText = "Hello World";
		if( sWI.TitleText != NULL )
		{
			STxtInf sTextInf;
			sTextInf.Color = 0xff000000;
			sTextInf.Font = "Arial";	//TODO:Make variable
			sTextInf.Point = ( ( (int)( Height * .1 ) % 2 ) ? Height : ( Height - 1 ) );
			sTextInf.Bold = 0;
			sTextInf.Italic = false;
			sTextInf.Underline = false;
			
			sTextInf.Center = FALSE;
			sTextInf.VCenter = FALSE;
			
			Coord.left = Coord.left / 2;	//+3 is a buffer from left
			Coord.top = Coord.top / 2 + 11;// + ( 6 + 2 * sBI.BorderWidth ); 

			sTextInf.Point = 12;
			DrawStatic( Coord, sTextInf, sWI.TitleText );
		};
	}

	

return true;
}

bool CDXDraw::DrawStatic( RECT Coord, STxtInf sTextInf, char *Text )
{

	DWORD Flag = 0L;
	if( sTextInf.Bold == true )
		Flag = 0x0001;
	hFont = new CD3DFont( sTextInf.Font, sTextInf.Point, Flag );

	hFont->InitDeviceObjects( DXDevice );
	hFont->RestoreDeviceObjects( );

	ScaleRect( Coord );
	
	SIZE fExt;

	hFont->GetTextExtent( Text, &fExt );
	
	
	Coord.top += (Coord.bottom - Coord.top  - fExt.cy )/2;
	Coord.left += ( Coord.right - Coord.left - fExt.cx )/2   ;
	
	

	hFont->DrawText( Coord.left, Coord.top, sTextInf.Color, Text ); 



	
return true;

}

bool CDXDraw::DrawButton( RECT Coord, SButtonInf sBI )
{
	SWinImages sWI = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
	char *txt;

	if( sBI.DrawUp == true )
	{
		sWI.BG = sBI.UImage;
		txt = sBI.UText;
	}
	else
	{
		sWI.BG = sBI.DImage;
		txt = sBI.DText;
	}

	if( sBI.AutoDraw )
		DrawBorderedBox( Coord, sBI );
	else
	{
	
		sWI.color = 0xffffff;	//Backup, but can't be black
		sWI.TitleBar = false;	//Make sure the thing doesn't draw a title bar
			
		DrawWindow( Coord, sWI );
	}

	
	sBI.sTxtInf.Center = TRUE;
	sBI.sTxtInf.VCenter = TRUE;
	
	DrawStatic( Coord, sBI.sTxtInf, txt );

  
return true;
}
	



bool CDXDraw::DrawBorderedBox( RECT Coord, SButtonInf sBI, bool NoBox )
{

	//Add in a texture handler later

	LPDIRECT3DVERTEXBUFFER8 VtxLBox = NULL;
	LPDIRECT3DVERTEXBUFFER8 VtxBBox = NULL;
	
	if( DXDevice == NULL )
		return false;

	DWORD ColorDrkBase, ColorLtBase;
	
	
	
	if( sBI.DrawUp == TRUE )
	{
		ColorDrkBase = 0xff000000;
		ColorLtBase = 0xffffffff;	
	}
	else
	{
		ColorDrkBase = 0xffffffff;
		ColorLtBase = 0xff000000;
	}

	PARAMETERS *pVertices = NULL;

	
	DXDevice->SetRenderState( D3DRS_AMBIENT,RGB(255,255,255) );
	DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
	

	//SET THIS THING UP AS A BILLBOARD
	D3DXMATRIX Mtrx2D;
	D3DXMATRIX Identity;

	D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth,  (float) SysHeight, 0.0f, 1.0f );
	D3DXMatrixIdentity( &Identity );

	DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
	DXDevice->SetTransform( D3DTS_WORLD, &Identity );
	DXDevice->SetTransform( D3DTS_VIEW, &Identity );

	
	//WORK OUT THE SIZES
	float Width = (float) ( Coord.right ) - (float) ( Coord.left );
	float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
	
	ScaleRect( Coord );
///////////////////////////////
//Draw big box
	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBBox );

	VtxBBox->Lock (0, 0, (BYTE**) &pVertices, 0 );

	//Color of corners
	pVertices[0].color = ColorLtBase ;
	pVertices[1].color = 0xffb6b6b6;	//Medium grey
	pVertices[3].color = 0xffa0a0a0;
	pVertices[2].color = ColorDrkBase;
	

	//H/W of the big box
	pVertices[0].x = pVertices[3].x = -Width / 2.0f; 
	pVertices[1].x = pVertices[2].x = Width/2.0f; 
	
	pVertices[0].y = pVertices[1].y = Height/2.0f;
	pVertices[2].y = pVertices[3].y = -Height/2.0f;

	//Stupid stuff
	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;
	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxBBox->Unlock();	

/////////////////////////////////
//Draw little box (button itself)
	//	sBI.BorderWidth = ScaleY( sBI.BorderWidth );

	if( NoBox == false ) 
	{
		DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
										FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxLBox );

		VtxLBox->Lock (0, 0, (BYTE**) &pVertices, 0 );

		//Color is all the same
		pVertices[0].color = pVertices[1].color = pVertices[3].color = pVertices[2].color = sBI.color;

		//W/H, this is modified
		pVertices[0].x = pVertices[3].x = -Width / 2.0f + sBI.BorderWidth; 
		pVertices[1].x = pVertices[2].x = Width /2.0f - sBI.BorderWidth; 

		pVertices[0].y = pVertices[1].y = Height/2.0f  - sBI.BorderWidth;
		pVertices[2].y = pVertices[3].y = -Height/2.0f + sBI.BorderWidth;


		//Useless crap
		pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

		pVertices[1].u = pVertices[2].u = 1.0f;
		pVertices[0].u = pVertices[3].u = 0.0f;

		pVertices[0].v = pVertices[1].v = 0.0f;
		pVertices[2].v = pVertices[3].v = 1.0f;

		VtxLBox->Unlock();	

	};

/////////////////////////////////////////////////
//TRANSLATION
	D3DXMATRIX Position;


	D3DXMatrixTranslation( &Position, 
		-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left, 
		( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top , 
			0.0f);
	
//-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left, 
//							( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top , 
//							0.0f 
//							);
	
	
	
	
	DXDevice->SetTransform( D3DTS_WORLD, &Position );


/////////////////////////////////////////////////	
//RENDERING SEQUENCE
	DXDevice->SetStreamSource( 0, VtxBBox, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );


	if( NoBox == false )
	{
		DXDevice->SetStreamSource( 0, VtxLBox, sizeof( PARAMETERS ) );
		DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );
	};

return true;
}






bool CDXDraw::DrawButtonAuto( RECT Coord, SButtonInf sBI )
{

	LPDIRECT3DVERTEXBUFFER8 VtxLeft = NULL;
	LPDIRECT3DVERTEXBUFFER8 VtxBottom = NULL;
	LPDIRECT3DVERTEXBUFFER8 VtxTop = NULL;
	LPDIRECT3DVERTEXBUFFER8 VtxRight = NULL;
	LPDIRECT3DVERTEXBUFFER8 VtxBox = NULL;


	DWORD ColorDrkFade, ColorDrkBase, ColorLtBase, ColorLtFade;

	
	if( sBI.DrawUp == TRUE )
	{
		ColorDrkFade = 0xff7d7d7d;
		ColorDrkBase = 0xff646464;
		ColorLtBase = 0xffffffff;
		ColorLtFade = 0xffd2d2d2;
	}
	else
	{
		ColorDrkFade = 0xffd2d2d2;
		ColorDrkBase = 0xffffffff;
		ColorLtBase = 0xff646464;
		ColorLtFade = 0xff7d7d7d;
	}

	PARAMETERS *pVertices = NULL;


	if( DXDevice == NULL )
		return false;

	DXDevice->SetRenderState( D3DRS_AMBIENT,RGB(255,255,255) );
	DXDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	DXDevice->SetVertexShader( FVF_WINDOWVERTEX );
	

	//SET THIS THING UP AS A BILLBOARD
	D3DXMATRIX Mtrx2D;
	D3DXMATRIX Identity;

	D3DXMatrixOrthoLH( &Mtrx2D, (float) SysWidth,  (float) SysHeight, 0.0f, 1.0f );
	D3DXMatrixIdentity( &Identity );

	DXDevice->SetTransform( D3DTS_PROJECTION, &Mtrx2D );
	DXDevice->SetTransform( D3DTS_WORLD, &Identity );
	DXDevice->SetTransform( D3DTS_VIEW, &Identity );

	

	//WORK OUT THE SIZES
	float Width = (float) ( Coord.right ) - (float) ( Coord.left );
	float Height = (float) ( Coord.bottom )- (float) ( Coord.top );
	float Buffer = 5;

	ScaleRect( Coord );
////////////////////////////////////////////////////
//Left Square

	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxLeft );

	
	VtxLeft->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[3].color = ColorLtBase;
	pVertices[1].color = pVertices[2].color = ColorLtFade;
	
	pVertices[0].x = pVertices[3].x = -Width / 2.0f ; 
	pVertices[1].x = pVertices[2].x = -Width/2.0f +4; 

	pVertices[0].y = Height/2.0f;	//The angled corner
	pVertices[1].y = Height/2.0f;
	
	pVertices[2].y = -Height/2.0f;
	pVertices[3].y = -Height/2.0f - 2;


	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxLeft->Unlock();
////////////////////////////////////////////////////
//Right Square

	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxRight );

	
	VtxRight->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[3].color = ColorDrkBase;
	pVertices[1].color = pVertices[2].color = ColorDrkFade;
	
	pVertices[0].x = pVertices[3].x = Width / 2.0f ; 
	pVertices[1].x = pVertices[2].x = Width/2.0f -4; 

	pVertices[0].y = -Height/2.0f;	//The angled corner
	pVertices[1].y = -Height/2.0f +3;
	
	pVertices[2].y = Height/2.0f -3;
	pVertices[3].y = Height/2.0f +1;


	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxRight->Unlock();
///////////////////////////////////////////////////////
//Bottom Square	


	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBottom );

	VtxBottom->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[1].color = ColorDrkFade;
	pVertices[3].color = pVertices[2].color = ColorDrkBase;
	
	pVertices[0].x = -Width / 2.0f + 4.45;
	pVertices[3].x = -Width / 2.0f - 1; 
	
	pVertices[1].x = pVertices[2].x = Width/2.0f; 

	pVertices[0].y = pVertices[1].y = -Height/2.0f +4 ;
	
	pVertices[2].y =  -Height/2.0f -1;
	pVertices[3].y = -Height/2.0f -1;

	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxBottom->Unlock();	
///////////////////////////////////////////////////////
//Top Square	

	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxTop );

	VtxTop->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[1].color = ColorLtBase;
	pVertices[3].color = pVertices[2].color = ColorLtFade;
	
	pVertices[0].x = pVertices[3].x = -Width / 2.0f ; 
	
	pVertices[1].x = Width/2.0f ;
	pVertices[2].x = Width/2.0f - 4; 

	
	pVertices[0].y = pVertices[1].y = Height/2.0f +1 ;
	pVertices[2].y = pVertices[3].y = Height/2.0f -3;


	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxTop->Unlock();
///////////////////////////////////////////////////////
//Box	

	DXDevice->CreateVertexBuffer( 4 * sizeof( PARAMETERS ), D3DUSAGE_WRITEONLY,
									FVF_WINDOWVERTEX, D3DPOOL_MANAGED, &VtxBox );

	VtxBox->Lock (0, 0, (BYTE**) &pVertices, 0 );

	pVertices[0].color = pVertices[1].color = pVertices[3].color = pVertices[2].color = sBI.color;
	
	
	pVertices[0].x = pVertices[3].x = -Width / 2.0f +4; 
	pVertices[1].x = pVertices[2].x = Width/2.0f -4; 

	
	pVertices[0].y = pVertices[1].y = Height/2.0f  -2;
	pVertices[2].y = pVertices[3].y = -Height/2.0f +4;


	pVertices[0].z = pVertices[1].z = pVertices[2].z = pVertices[3].z = 0.0f;

	pVertices[1].u = pVertices[2].u = 1.0f;
	pVertices[0].u = pVertices[3].u = 0.0f;

	pVertices[0].v = pVertices[1].v = 0.0f;
	pVertices[2].v = pVertices[3].v = 1.0f;

	VtxBox->Unlock();	
/////////////////////////////////////////////////
//TRANSLATION
	D3DXMATRIX Position;

	D3DXMatrixTranslation( &Position, 
		-( ( SysWidth / 2.0f ) - ( Width/2.0f ) ) + Coord.left, 
		( SysHeight / 2.0f ) - ( Height/2.0f ) - Coord.top , 
			0.0f);
	
	DXDevice->SetTransform( D3DTS_WORLD, &Position );
	
	
/////////////////////////////////////////////////	
//RENDERING SEQUENCE
	DXDevice->SetStreamSource( 0, VtxBox, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

	
	DXDevice->SetStreamSource( 0, VtxLeft, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );


	DXDevice->SetStreamSource( 0, VtxBottom, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

	DXDevice->SetStreamSource( 0, VtxRight, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

	DXDevice->SetStreamSource( 0, VtxTop, sizeof( PARAMETERS ) );
	DXDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 );

	
	return true;	
}



int CDXDraw::ScaleX( int X )
{
	GetClientRect( hWnd, &windowSize);
	return ( windowSize.right - 5.0 ) / (float) SysWidth * X;
}


int CDXDraw::ScaleY( int Y )
{
	GetClientRect( hWnd, &windowSize);
	return ( windowSize.bottom - 5.0 ) / (float) SysHeight * Y;
}


void CDXDraw::ScaleRect( RECT &r )
{
	if( &r == NULL )
		return;
	
	GetWindowRect( hWnd, &windowSize);
	r.left = ( ( windowSize.right ) / (float) SysWidth )* r.left;
	r.right = ( ( windowSize.right ) / (float) SysWidth ) * r.right;
	r.bottom = ( ( windowSize.bottom ) / (float) SysHeight ) * r.bottom;
	r.top = ( (windowSize.bottom ) / (float)SysHeight  ) * r.top;

  }

Interface for a Button Object

class CButton : public CWindow_GUI   
{
public:
	CButton();
	virtual ~CButton();
	virtual int RenderWindow( );
	virtual void Init( );

	//	virtual void Init( );

//these refer to the face
	void SetImage( char *UpImage, char *DownImage = NULL );

	void SetButtonText( char *UpText, char* DownText = NULL );

	bool CreateSurface( );

	void SetFont( char *FontType = NULL );
	void SetPoint( int Point = 12 );
	void SetColor( DWORD Color = 0 );
	void SetMargins( short Vertical, short Horizontal );
	
	void SetParams( bool Italic = false, bool Bold = false, bool Underline = false );
	void SetAutoDraw( bool Auto = true, DWORD color = 0xffBCBCBC );

	void SetCommandLeft( void *ComLMB );
//	virtual void Test( int a );

//Messaging
	virtual void GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState );
	
protected:
	SButtonInf sButtonInf;
//	void *CommandLB();

};
#endif



CButton::CButton()
{
	
}

CButton::~CButton()
{

}

void CButton::Init( )
{
	//TODO: Put this in initialize
	sButtonInf.DrawUp = true;
	
	sButtonInf.sTxtInf.Italic = false;
	sButtonInf.sTxtInf.Bold = 0;
	sButtonInf.sTxtInf.Underline = false;
	sButtonInf.sTxtInf.Font = "Times New Roman";
	sButtonInf.sTxtInf.Point = 10;
	sButtonInf.sTxtInf.Color = 0xff000000;
	sButtonInf.BorderWidth = 3;

	sButtonInf.AutoDraw = true;
	sButtonInf.color = 0xffBCBCBC;

	sButtonInf.UText = "Hello World";
	sButtonInf.DText = "Hello World";
	sButtonInf.DrawUp = true;
	
	sButtonInf.HMargin = 4;
	sButtonInf.VMargin = 4;

	SetPos( 0, 0 );
	SetSize( 100, 100 );
}

void CButton::SetFont( char *FontType )
{
	if( FontType != NULL )
		sButtonInf.sTxtInf.Font = FontType;
	else
		sButtonInf.sTxtInf.Font = "Arial";
}

void CButton::SetPoint( int Point )
{
	if( Point % 2 )
		Point--;
	
	if( Point > 24 )
		Point = 24;
	
	if( Point == 0 )
		Point = 12;
	
	if( Point < 8 )
		Point = 8;
	
	sButtonInf.sTxtInf.Point = Point;

}

void CButton::SetColor( DWORD Color )
{
	sButtonInf.sTxtInf.Color = Color;
}

void CButton::SetParams( bool Italic, bool Bold, bool Underline )
{
	if( Bold )
		sButtonInf.sTxtInf.Bold = 700;
	else
		sButtonInf.sTxtInf.Bold = 0;

	sButtonInf.sTxtInf.Italic = Italic;
	sButtonInf.sTxtInf.Underline = Underline;
}

void CButton::SetImage( char *UpImage, char *DownImage  )
{
	sButtonInf.UImage = UpImage;

	if( DownImage == NULL )
		sButtonInf.DImage  = sButtonInf.UImage;
	else
		sButtonInf.DImage = DownImage;

}

void CButton::SetButtonText( char *UpText, char* DownText  )
{
	sButtonInf.UText = UpText;
	
	if ( DownText == NULL )
		sButtonInf.DText = sButtonInf.UText;
	else
		sButtonInf.DText = DownText;

}

int CButton::RenderWindow( )
{
	DXControl->DrawButton( sCoord.pos, sButtonInf );

return 0;
}

void CButton::SetMargins( short Vertical, short Horizontal )
{
	sButtonInf.VMargin = Vertical;
	sButtonInf.HMargin = Horizontal;

}

void CButton::GM_MOUSEACTION( int MouseX, int MouseY, short Btn, short LastBtnState )
{
	bool inside = ClickInside( MouseX, MouseY );
	bool up = sButtonInf.DrawUp;
	
	//State machine
	if( inside == true && up == true )//Button has been clicked on
		sButtonInf.DrawUp = false;
	
	if( inside == true && up == false )//Button has been activated
	{	
		sButtonInf.DrawUp = true;
		GM_USERACTION_MOUSE( Btn );
		// 		(void)CommandLB( );
	}
	if( inside == false && up == false )//Button has been cancelled
		sButtonInf.DrawUp = true;

}

void CButton::SetAutoDraw( bool Auto, DWORD color )
{
	sButtonInf.AutoDraw = Auto;
	sButtonInf.color = color;
}


/*
void CButton::Test( int a )
{
	if( sButtonInf.DrawUp == false )
		sButtonInf.DrawUp = true;
	else
		sButtonInf.DrawUp = false;
}*/

void CButton::SetCommandLeft( void *ComLMB )
{
//	CommandLB() = ComLMB();

}

The likned list template, homemade I might say...

template< class NTYPE >
class ArrayPtrCtrl
{
public:
	ArrayPtrCtrl( );
	~ArrayPtrCtrl( );
	//TODO: NEED DELETE ELEMENT NOT ITEM
	//ALSO NEED TO ADD INSERT IN LINKS
	//ALSO NEED TO REVIEW ALL ITERATION ROUTINES

	int Add( NTYPE value );	//add pointer to back
	int Delete( NTYPE value );	//delete a given pointer
	
	NTYPE GetData( int ind ) const;		//Give index # and get data
	NTYPE GetDataBW( int index ) const;
	
	bool IsValid( int ind );
	bool IsEmpty( );
	int GetCount( );
	void DeleteAll( );

private:
	APtrNode< NTYPE > * Search( NTYPE Data );
	NTYPE GetDBW( int index, int dest, APtrNode< NTYPE > *ptr  ) const;


	int size;
	APtrNode< NTYPE > *Start;	//Pointer to start of list
	APtrNode< NTYPE > *End;		//pointer to end

	APtrNode< NTYPE > *getNewNode( const NTYPE/*, APtrNode< NTYPE > last*/ );

	NTYPE Value;
	int count;
};

///////////////////////////////////////////////////////////////
/////////Implementaion
///////////////////////////////////////////////////////////////

template< class NTYPE >
ArrayPtrCtrl< NTYPE >::ArrayPtrCtrl( ) 
	: Start( NULL ), End( NULL ) 
{
	count = 0;
};


template< class NTYPE >
ArrayPtrCtrl< NTYPE >::~ArrayPtrCtrl( ) 
{
	//List has stuff in it
	if( !IsEmpty( ) )
	{
		APtrNode< NTYPE > *currentPtr = Start;
		APtrNode< NTYPE > *tempPtr;
		
		while ( currentPtr != NULL )
		{
			tempPtr = currentPtr;	//make addy of temp be that of the current ptr
			currentPtr = currentPtr->nextPtr;//change the current
			tempPtr->data = NULL;
			delete tempPtr;	//delete the one that was previous
			tempPtr = NULL;

		}
	}
}


template< class NTYPE >
ArrayPtrCtrl< NTYPE >::Add( NTYPE value )
{
	//FOUL!!!!
//	if ( value == NULL )
//		return -1;


	APtrNode< NTYPE > *nPtr = getNewNode( value );

	if( nPtr ==  NULL )
		MessageBox( NULL, "nPtr Null", "AptrNode", MB_YESNO );

	if( value == NULL )
		MessageBox( NULL, "value Null", "AptrNode", MB_YESNO );

	if ( IsEmpty( ) )		//List is empty
	{
 		Start = nPtr;
		End = nPtr;
		nPtr->lastPtr = Start;
	}
	else
	{
		End->nextPtr = nPtr;	//Assign the last ptr's new ptr 
		nPtr->lastPtr = End;
		
		End = nPtr;				//Assign last pointer to the new ptr
	};

	

	count++;
	
	return 1;
};


template< class NTYPE >
//This adds another point to the node
APtrNode< NTYPE > *ArrayPtrCtrl< NTYPE >::getNewNode ( NTYPE value/*, APtrNode< NTYPE > last*/ )
{
	APtrNode< NTYPE > *ptr = 
		new APtrNode< NTYPE > ( value );

	return ptr;
};


//This will return the address of data
template< class NTYPE >
APtrNode< NTYPE > *ArrayPtrCtrl< NTYPE >::Search( NTYPE data )
{
	APtrNode< NTYPE > *currentPtr = Start;
	while ( currentPtr != NULL )
	{
		//Check if the current node has the data being searched for
		if ( currentPtr->GetData( ) == data )
		{
			//if so, return the node address
			return currentPtr;
			break;
		};
		//This sets the current pointer address to the address specified in
		//currentpointer.NextPointer
		currentPtr = currentPtr -> nextPtr;
	};
	return NULL;
};

template< class NTYPE >
int ArrayPtrCtrl< NTYPE >::Delete( NTYPE data )
{
	//Pointer to delete
	APtrNode< NTYPE > *delPtr = Search( data );
	
	//See if the data is in the list
	if(  delPtr == NULL )
		return NULL;
	
	//Since it is, begin from 1st address
	APtrNode< NTYPE > *currentPtr = Start;

	if ( currentPtr == delPtr )
	{
		Start = currentPtr->nextPtr;
		currentPtr->nextPtr = NULL;

		delete delPtr;
		return true;
	};//just in case it is the first pointer
	
	while( currentPtr->nextPtr != NULL )//until end of list
	{
		//if the next pointer address is equal to the address of
		//the & of the node to be deleted, then set the next pointer
		//to the one of the pointer to be deleted
		if ( currentPtr->nextPtr == delPtr )
		{
			currentPtr->nextPtr = delPtr->nextPtr;
			delPtr->nextPtr = NULL;

		return true;
		};
		currentPtr = currentPtr->nextPtr;

		//break;
	};
	return NULL;//Somethings wrong
};

template< class NTYPE >
bool ArrayPtrCtrl< NTYPE >::IsValid( int index )
{
	int in;	//index
	APtrNode< NTYPE > *currentPtr;	//


	currentPtr = Start;

	if ( currentPtr == NULL )
		return false;

	if( index == 0 )
		return true;	//since this is the first on the list and wont get tested
	
	//loop through chain up to index
	for( in = 0 ; in<index ; in++ )
	{

	//jump to next node
		
		currentPtr = currentPtr->nextPtr;	//take the current pointer, 
											//and assign it to the next on the list.
		
		if ( currentPtr == NULL )	//if the pointer becomes invalid, then the
			return false;//error	//link does not exist
	}//we have 1

	
	return true;//since CurrentPtr does exist, return true
	
};

template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetData( int index ) const
{
	int in;
	APtrNode< NTYPE > *currentPtr;
	currentPtr = Start;
	
	//loop through chain
	for( in = 0 ; in<index ; in++ )
	{
		//jump to next node
		currentPtr = currentPtr->nextPtr;	//take the current pointer, 
											//and assign it to the next on the list.
		
		if ( currentPtr == NULL )
			return NULL;//error
	}//we have 1
	if ( index == 0 )
	{
		currentPtr = Start;	//in case the current pointer 
							//is start and not a next ptr
		//when point is reached, return the data
		return currentPtr->GetData( );
	}
	else
		return currentPtr->GetData( );

	
};


template< class NTYPE >
bool ArrayPtrCtrl< NTYPE >::IsEmpty( ) 
{
	if ( Start == NULL )
		return true;
	else
		return false;
};


template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetDBW( int index, int dest, APtrNode< NTYPE > *ptr ) const
{
	if( index == dest )
		return ptr->GetData( );

	GetDBW( index, (dest-1), ptr->lastPtr );
}
	


template< class NTYPE >
NTYPE ArrayPtrCtrl< NTYPE >::GetDataBW( int index ) const
{
	if( index > count ) return 0;
	
	if( index == count )
		return End->GetData( );

	if( index <= 0 )
		return Start->GetData( );
	
	GetDBW( index, count, End );
	
};

template< class NTYPE >
int ArrayPtrCtrl< NTYPE >::GetCount( )
{
	return count;
}

template< class NTYPE >
void ArrayPtrCtrl< NTYPE >::DeleteAll( )
{
	if( IsEmpty( ) == false )
	{
		APtrNode< NTYPE > *currentPtr = Start;
		APtrNode< NTYPE > *tempPtr;
		
		while ( currentPtr != NULL )
		{
			tempPtr = currentPtr;	//make addy of temp be that of the current ptr
			currentPtr = currentPtr->nextPtr;//change the current
			tempPtr->data = NULL;
			Start = NULL;
			End = NULL;
			delete tempPtr;	//delete the one that was previous
			//tempPtr = NULL;
		}
	}
}

Advertisement
Definitely use an std::list. Definitely.
Can't say that your design is wrong cause it's quite popular among GUI writers, but you definitely should read carefully this series of tutorials http://www.gamedev.net/reference/articles/article994.asp, I would also strongly encourage you to download source code of engine I'm currently writing (link is in signature, but it's cvs which could be quite complicated to use, so I can send you some code via mail. It's design is rather originall and targeted especially at writing games, with strong need for abstraction and flexibility - I have negative experience writing GUI's traditional way, so I tried the other way, which suprisingly appears to be very promising.
Thanks for the help guys! Can't wait to take a look at that source.

Dan
I tried to send you mail with sources, using email adress I've found in your profile but I got delivery failure etc. Could you send me your valid email (probably using private messagess?)
std::list Is that an actualy linked list template or do you mean one of the many available, like std::vector or something. I have not used any of Microsoft's templates very much (It is a template, right) so maybe I'll check it out on msdn.

DrMol
Quote:Original post by DrMol
std::list Is that an actualy linked list template or do you mean one of the many available, like std::vector or something. I have not used any of Microsoft's templates very much (It is a template, right) so maybe I'll check it out on msdn.

DrMol


std::list is indeed a linked list template (vector on the other hand is a resizable array). There's also the std::deque (similar to vector, but allows O(1) operations on both ends).

Additionally, they're not Microsoft's :) They're part of standard c++ (just like std::cout) and are pretty much available no matter what compiler you use (and even if you could find one without them, there's STLPort. Learn to use what's there, and you'll never regret it.

This topic is closed to new replies.

Advertisement