Object Oriented issue

I am creating a program that draws simple shapes and holds data about them. For this purpose I have designed a base class Shape:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Shape
{
protected:
	HDC hdc;
	POINT pa, pb, pc;
	HRGN shapeRgn;
	RECT shapeRect;
	float b,h;
	int idShape;
public:
	Shape(HDC dc, POINT a, POINT b, POINT c, int i) :
	  hdc(dc), pa(a), pb(b), pc(c), idShape(i)
	  {}
	Shape(HDC dc, POINT a, POINT b, int i) : 
	  hdc(dc), pa(a), pb(b), idShape(i)
	  {}
	~Shape()
	  {}
	void Erase();
	virtual float CalculateArea() = 0;
	virtual void Draw() = 0;
	virtual void SetShapeRgn() = 0;
	void SetShapeRect();
	bool TestSelect(POINT a);
};

Currently only one class (for a rectangle) inherits from Shape:
1
2
3
4
5
6
7
8
9
10
11
12
class Rect : public Shape
{
public:
	Rect(HDC hdc, POINT a, POINT b, int i) :
	  Shape(hdc,a,b,i)
	  {}
	void Draw();
	float CalculateArea();
	void SetShapeRect();
	void SetShapeRgn();
	bool TestSelect(POINT a);
};

In my window procedure, the user can draw a rectangle by clicking the left mouse button like so: (Note that this is a switch for an enumerated type which is controlled by a menu)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
		case RECTANGLE:
			if (click == 0)
			{
				GetCursorPos(&pa);
				ScreenToClient(renderWnd,&pa);

				click = 1;
			}
			else if (click == 1)
			{
				GetCursorPos(&pb);
				ScreenToClient(renderWnd,&pb);

				shapes[shapeCount] = new Rect(hdc,pa,pb,shapeCount);
				shapes[shapeCount]->Draw();
				shapes[shapeCount]->SetShapeRect();
				shapes[shapeCount]->SetShapeRgn();
				shapeCount++;

				click = 0;
			}
			break;

If the enumerated type is switched to SELECT, then the user should be able to click on the shape and select it. This is where the problem in my code is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
		case SELECT:
			GetCursorPos(&pa);
			ScreenToClient(renderWnd,&pa);

			for (int i = 0; i < shapeCount; i++)
			{
				if (test == 0)
				{
					test = shapes[i]->TestSelect(pa);
				}
				else if (test == 1)
				{
					currentShape = shapes[i];
					initSelect = 1;
					test = 0;
				}
			}

			break;

I can draw the rectangles; however when I go to select one, the program crashes. Here is the TestSelect() function:
1
2
3
4
5
6
7
bool Shape::TestSelect(POINT a)
{
	if (PtInRegion(shapeRgn,a.x,a.y))
		return true;
	else 
		return false;
}


I would greatly appreciate it if anyone could help me figure out why my program is crashing. I'm trying to keep the code posted in this original post to a minimum, but if you feel more information is pertinent, please let me know and i will post more of the code.

Thanks,
tyler22
Last edited on
What's the error name? Set breakpoint and debug to see where exactly program crashes.
The program crashes as it is going through this loop:
1
2
3
4
if (test == 0)
	{
		test = shapes[i]->TestSelect(pa);
        }

The debug process then jumps back to my message loop and I get the following error:
Unhandled exception at 0x77c815de in Geometry.exe: 0xC0000005: Access violation reading location 0x02011529.
At which step it crashes? You might have incremented shapeCount too much, and shapes[shapeCount-1] is NULL pointer.
This information may help:
If I only draw one shape and do the selection test, (thus shapeCount == 1), the program will not crash. (Although it will not select the shape either). Once I draw more than one shape and attempt to select it, the program crashes.

I believe it crashes at exactly this step:
test = shapes[i]->TestSelect(pa);
Access violation means you are trying to use TestSelect from pointer that doesnt hold any address.
or....
error is caused by PtInRegion method.

make
1
2
3
4
5
6
7
bool Shape::TestSelect(POINT a)
{
	if (PtInRegion(shapeRgn,a.x,a.y))
		return true;
	else 
		return false;
}


always return 0, and see if the programs crashes.
Also when debugging you can use "step in" on line test = shapes[i]->TestSelect(pa); to enter TestSelect and see if PtInRegion is not causing problems.
Last edited on
the issue must be with PtInRegion. When I set TestSelect to always return false, the program no longer crashes.

Now the question is, what is wrong with PtInRegion?
I don't know since you didn't show it :D.

You probably used as argument empty pointers.

Check shapeRgn,a.x,a.y before using PtInRegion.
Last edited on
Could you elaborate a little more? I'm sorry, i'm still a relative novice of c++. I don't see how these arguments could be empty.

When I do the debug, i put a breakpoint on the TestSelect() function. According to the debugger, the program never executes this line of code. Something must be wrong with this block of code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
		case SELECT:
			GetCursorPos(&pa);
			ScreenToClient(renderWnd,&pa);

			for (int i = 0; i < shapeCount; i++)
			{
				if (test == 0)
				{
					test = shapes[i]->TestSelect(pa);
				}
				else if (test == 1)
				{
					currentShape = shapes[i];
					initSelect = 1;
					test = 0;
				}
			}

			break;
Last edited on
You said that program crashes when executing PtInRegion, sindie TestSelect. Are the Shapes::TestSelect and Rect::TestSelect the same? I hope you know that when using test = shapes[i]->TestSelect(pa) you are using Shapes::TestSelect not Rect::TestSelect.

Debug again, find where exactly program crashes.

Something must be wrong with this block of code.
What SELECT should do? What it is doing now? Answer these and you will know where error is.
Last edited on
TestSelect() is only defined for class Shape. This is because I want the method to be the same for all derived classes. (I hope this is the proper implementation).

When I debug, the program iterates through this for loop
1
2
3
4
5
6
7
8
9
10
11
12
13
			for (int i = 0; i < shapeCount; i++)
			{
				if (test == 0)
				{
					test = shapes[i]->TestSelect(pa);
				}
				else if (test == 1)
				{
					currentShape = shapes[i];
					initSelect = 1;
					test = 0;
				}
			}

exactly one time before crashing and giving me the access violation reading error. I think the problem is with the shapes[] array. The debug pins show that this array is not initializing properly. Can someone please tell me how to properly initialize it?

Show us how are you initializing it right now?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
		case RECTANGLE:
			if (click == 0)
			{
				GetCursorPos(&pa);
				ScreenToClient(renderWnd,&pa);

				click = 1;
			}
			else if (click == 1)
			{
				GetCursorPos(&pb);
				ScreenToClient(renderWnd,&pb);

				shapes[shapeCount] = new Rect(hdc,pa,pb,shapeCount);
				shapes[shapeCount]->Draw();
				shapes[shapeCount]->SetShapeRect();
				shapes[shapeCount]->SetShapeRgn();
				shapeCount++;

				click = 0;
			}
			break;
Last edited on
Topic archived. No new replies allowed.