So it's this program which isn't behaving as it should.
these are the classes I'm haing problems with:

#ifndef _CMENU_H_
#define _CMENU_H_

#include "Vec2.h"
#include "Background.h" 
#include "Sprite.h"		
#include "BackBuffer.h"		

class Button
{
public:
	enum ButtonState
	{
		NORMAL,		//when cursor is not near the button
		ANIMATED	//mouseover event
	};
	Button(const char*,const char*,const char*,Vec2&);
//const char* 's are the name of the bitmaps for the mask, normal image, and animated image; 
//Vec2 is the position on the screen
														
	virtual ~Button(void);
	bool Update(POINT&);	//takes the curent cursor position(POINT)and changes the button state
	void  Draw(const BackBuffer*);	//draws the button
protected:
	Sprite* image[2];     //image[0] is normal state,image[1] the animated image of the button
	RECT rc;	      //rectangle which defines borders of the button
	ButtonState State;    //button state
};


class Menu
{
protected:
	int		NrButtons;
	Background*	m_imgBackground;//the screen background image
	vector<Button*> v_button;	//the button container
public:

	Menu(const BackBuffer *pBackBuffer,const char*);//const char* is the name of the textfile
	virtual ~Menu		(void);
	int      Update		( POINT& mouse_pos,bool press_mouse);
	void     Draw		(const BackBuffer *pBackBuffer);
};

#endif //CMENU_H

and this is the definition:

#include "CMenu.h"

Button::Button(const char* img1, const char* img2, const char* mask,Vec2& pos)
{
	this->image[0]=new Sprite(img1,mask);
	this->image[1]=new Sprite(img2,mask);

	for (int i=0;i<2;i++)
		this->image[i]->mPosition=pos;
	
	this->rc.left	=pos.x-this->image[0]->width()/2;
	this->rc.top	=pos.y-this->image[0]->height()/2;
	this->rc.right  =this->rc.left+ this->image[0]->width();
	this->rc.bottom =this->rc.top+ this->image[0]->height();

	this->State=NORMAL;
}
Button::~Button()
{
	if(this->image!=NULL)
	{
		delete this->image[0];
		this->image[0]=NULL;
		delete this->image[1];
		this->image[1]=NULL;
	}
}
bool Button::Update(POINT& tmp)
{
	if(this->rc.top<=tmp.y && this->rc.bottom>=tmp.y && this->rc.left<=tmp.x && this->rc.right>=tmp.x)
	{
		this->State=ANIMATED;
		return true;
	}
	else
	{
		this->State=NORMAL;
		return false;
	}
}

void Button::Draw(const BackBuffer* pBackBuffer)
{
	this->image[State]->setBackBuffer(pBackBuffer);
	this->image[State]->draw();
}


Menu::Menu(const BackBuffer *pBackBuffer,const char* filename)
{
	ifstream	File;
	string		mask,imag,imag1;
	Vec2        bt_position;
	Button*		tButton=NULL;

	this->m_imgBackground=NULL;
	m_imgBackground = new CImageFile;
	
	File.open(filename);
	
	File>>imag;
	File>>this->NrButtons;
	m_imgBackground->LoadBitmapFromFile(imag.c_str(), pBackBuffer->getDC());
	
	for(int bt_index = 0; bt_index < NrButtons; bt_index++)
	{
		File >> mask; //rading the mask
		File >> imag; //normal image
		File >> imag1;//animated image
        File >> bt_position.x;    
		File >> bt_position.y;
		if(tButton!=NULL)
		{
			delete tButton;
			tButton=NULL;
		}
		tButton=new Button(imag1.c_str(),imag.c_str(),mask.c_str(),bt_position);
		this->v_button.push_back(tButton);
	}
	File.close();
}

Menu::~Menu()
{
	if(this->m_imgBackground!=NULL)
	{
		delete this->m_imgBackground;
		this->m_imgBackground=NULL;
	}
	this->v_button.empty();
}

int Menu::Update(POINT& mouse_pos,bool press_mouse)
{
	for(int i=0;i<NrButtons;i++)
		if(this->v_button[i]->Update(mouse_pos)&& true==press_mouse)
			return i++;
	return -1;
}

void Menu::Draw(const BackBuffer* temp)
{
	m_imgBackground->Paint(temp->getDC(), 0, 0);
	for(int i=0;i<this->NrButtons;i++)
		this->v_button[i]->Draw(temp);
}

The trouble I'm having is with the last function, because only the last button read(from the textfile) gets drawn

Recommended Answers

All 3 Replies

Heh, the last function looks great. Consider the possibility that (for some reason) you have only one valid button to draw. (Hint: the problem is actually in your Menu constructor, and has been discussed and re-discussed so many times in this forum that there's a sticky topic for it at the top of the C++ topic list!)

If the hint isn't helping, start inserting debug "cout <<" statements everywhere that makes sense, such as at the end of your Button constructor function to print out all the member values. Good luck!

Heh, the last function looks great. Consider the possibility that (for some reason) you have only one valid button to draw. (Hint: the problem is actually in your Menu constructor, and has been discussed and re-discussed so many times in this forum that there's a sticky topic for it at the top of the C++ topic list!)

If the hint isn't helping, start inserting debug "cout <<" statements everywhere that makes sense, such as at the end of your Button constructor function to print out all the member values. Good luck!

Please correct me if my answer is wrong
so as you said, the function is actually functioning fine, since it get's to draw everything in the vector, the problem's what's in the vector
In the constructor I push in the vector a pointer to where memory was allocated, but because I delete the memory allocated in the previous loop(line 72->76) and set to NULL(and because the pointers in the vector have the same address, they will also point to NULL)such as only the last vector wasn't equal to NULL.
BTW: If i wanted to do something like this:

vector< String* > tmp(5);
...
tButton=new Button(imag1.c_str(),imag.c_str(),mask.c_str(),bt_position);
tmp=tButton;
...
this->v_button.swap(tmp);

unless I've had definde the '='operator for the class, it would fail, so how would I define it?

You shouldn't delete your buttons in your constructor. Do it in your destructor, using a for loop.

The for loop in your constructor should look like this:

//...

for(int bt_index = 0; bt_index < NrButtons; bt_index++)
{
    File >> mask; //rading the mask
    File >> imag; //normal image
    File >> imag1;//animated image
    File >> bt_position.x;
    File >> bt_position.y;

    tButton = new Button(imag1.c_str(), imag.c_str(), mask.c_str(), bt_position);
    this->v_button.push_back(tButton);
}

//...

In the constructor I push in the vector a pointer to where memory was allocated, but because I delete the memory allocated in the previous loop(line 72->76)
and set to NULL(and because the pointers in the vector have the same address, they will also point to NULL)such as only the last vector wasn't equal to NULL.

When you push_back a pointer in your vector, a new pointer (careful here, a new pointer, not a new button) is created
and set to point to the address tButton does. Setting tButton to NULL doesn't affect the pointer stored in your vector.

However, deleting tButton sends a message to your OS that that particular memory area is free
to be used by your OS or by other programs. This is bad because the pointers in your vector
point to that area too. The result of using the data in that memory area is undefined.

Since your program doesn't crash and you don't see your buttons, my guess is that either your buttons are drawn but
because they have the same size and position you only see the last one, or the OS puts some other data in that
memory area, which, if interpreted as a button, has extreme position values and is thus drawn out of screen.

EDIT:

that particular memory area is free to be used by your OS or by other programs

Oops... This is wrong. Heap memory is per-process. Ah! Of course! This explains it!
The way you do it, every pointer in your vector points to the same address, which is the
address where the last button is stored. Try printing the pointers and see if I'm right.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.