Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I am having trouble getting the fol

Status
Not open for further replies.

Bones3

Programmer
Jul 27, 2003
151
US
I am having trouble getting the following to do what I want it to do:

rectList is a CObList containing objects that are of my class CMyRect. r is a member of CMyRect, and is a CRect. In my application, I have several rectangles dispayed, many overlapping each other. What I want this application to do is to delete the rectangles that are clicked on. Thus I have this the following:


void CMainFrame::OnLButtonDown(UINT nFlags, CPoint pt)
{
nbrRects = rectList.GetCount();
pos = rectList.GetHeadPosition();

for (int i = 0; i < nbrRects; i++)
{
pRect = (CMyRect*)rectList.GetNext(pos);
if (pRect->r.PtInRect(pt))
{
rectList.RemoveAt(pos);
delete pRect;
}
}
}

When running the app, I click on some of the outside rectangles and nothing happens. When clicking on a rectanle toward the center, I get an assertation failure and am pointed to line 299 in list_o.cpp which goes like this:

ASSERT(AfxIsValidAddress(pOldNode, sizeof(CNode)));

and I determined one of my problems is at rectList.RemoveAt(pos). I can't figure out what the problem with this line is, and I can't figure out why the rectangles are still being displayed on the Client window.

Please tell me what I am doing wrong here! lol Thanks in advance.

-Bones
 
The rectangles are probably still displayed because you don't force a redraw of your window (something like Invalidate(this) at the end of OnLButtonDown).

I don't know anything about CObjList, BUT, looking at the MSDN reference (a good habit to develop!), one finds about GetNext:

Gets the list element identified by rPosition, then sets rPosition to the POSITION value of the next entry in the list.


If you want to delete the current object, you will need to store the POSITION, as in the following example taken for the RemoveAt entry in MSDN:

Code:
   CObList list;
   POSITION pos1, pos2;
   CObject* pa;
   
   list.AddHead( new CAge( 21 ) );
   list.AddHead( new CAge( 40 ) );
   list.AddHead( new CAge( 65 ) ); // List now contains (65 40, 21).
   for( pos1 = list.GetHeadPosition(); ( pos2 = pos1 ) != NULL; )
   {
       if( *(CAge*) list.GetNext( pos1 ) == CAge( 40 ) )
       {
           pa = list.GetAt( pos2 ); // Save the old pointer for
                                  //deletion.
           list.RemoveAt( pos2 );
           delete pa; // Deletion avoids memory leak.
       }
   }
#ifdef _DEBUG
   afxDump.SetDepth( 1 );
   afxDump << &quot;RemoveAt example: &quot; << &list << &quot;\n&quot;;
#endif

Vincent
 
Ok, the rectangles are displayed in OnPaint, so that is how I was testing to see if it would work, but it would probably be nice if I put an Invalidate() in.

I now believe the pos was giving me an elusive view of the position, and I was slightly confused by MSDN's code so I have eliminated that issue as you can see in the code I have posted. All of the rectangles now have the assertation error when clicked on, which seems more logical.

Now, with that taken care of, (ty Vincent) here is a new analysis of my problem:

void CMainFrame::OnLButtonDown(UINT nFlags, CPoint pt)
{
for (int i = 0; i < 21; i++)
{
pos = rectList.FindIndex(i);
pRect = (CMyRect*)rectList.GetAt(pos);
if (pRect->r.PtInRect(pt))
{
CClientDC dc(this);
dc.TextOut(5, 5, &quot;Here!&quot;);
rectList.RemoveAt(rectList.FindIndex(i));
delete pRect;
}
}
}

The TextOut function is somehow able to be called after the crash, so the rectangles would get deleted if the program were allowed to continue. When debugging, there is an unhandled exception at this line:

pRect = (CMyRect*)rectList.GetAt(pos);

and when I break there, here is my dissasembly (which I can barely literate in unfortunately)

pRect = (CMyRect*)rectList.GetAt(pos);
0041539F mov eax,dword ptr [this]
004153A2 mov ecx,dword ptr [eax+0F8h]
004153A8 push ecx
004153A9 mov ecx,dword ptr [this]
004153AC add ecx,0D4h
004153B2 call CObList::GetAt (4114D8h)
004153B7 mov edx,dword ptr [this] // <-BREAK IS HERE
004153BA mov eax,dword ptr [eax]
004153BC mov dword ptr [edx+0F0h],eax

so something must be wrong with GetAt(pos) right? I can't figure out what it is.

-Bones
 
How many rectangles do you have? If you have less than 21, then the FindIndex function will return NULL, and GetAt will surely not like that!

However, adapting MSDN's code is not that hard:

Code:
void CMainFrame::OnLButtonDown(UINT nFlags, CPoint pt)
{
    nbrRects = rectList.GetCount();
    pos = rectList.GetHeadPosition();
    POSITION posPrevious = pos;

    for (int i = 0; i < nbrRects; i++)
    {
        pRect = (CMyRect*)rectList.GetNext(pos);
        if (pRect->r.PtInRect(pt))
        {
            rectList.RemoveAt(posPrevious);
            delete pRect;
        }
        posPrevious = pos;
    }
}

should work fine (but I have not tested it.

Vincent
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top