小女子初来乍到 急求VC中关于撤消功能的实现,该如何解决

小女子初来乍到 急求VC中关于撤消功能的实现
有个用VC做的监控的项目,可以在界面上添加 直线等元素,并且可以更改这些元素的属性 及移动 复制,
现在需要增添一个撤销的功能,虚心请教高人指点,1)是用链表来做么? 2)希望提供详尽的代码或思路 不胜感激!!!!!!

------解决方案--------------------
C/C++ code

class CRUAct
{
public:
    virtual ~CRUAct() {};
    virtual void Redo()=0;
    virtual void Undo()=0;
    CString GetText(){ return m_strText;}
    void SetIsUndo(BOOL bIsUndo){ m_bIsUndo = bIsUndo;}
    BOOL IsUndo(){ return m_bIsUndo;}
protected:
    BOOL m_bIsUndo;
    CString m_strText;
};

typedef CList<CRUAct*, CRUAct*> CRedoUndoBuffer;
class CRedoUndo
{
public:
    CRedoUndo();
    ~CRedoUndo();
public:
    void AddUndo(CRUAct *pRUAct);
    void AddRedo(CRUAct *pRUAct);
    void Redo(int nNum);
    void Undo(int nNum);
    BOOL CanRedo();
    BOOL CanUndo();
    void GetRedoActions(CStringArray& lstActions);
    void GetUndoActions(CStringArray& lstActions);
protected:
    void Clear(CRedoUndoBuffer& ru);
    void Fill(CRedoUndoBuffer& ru, CStringArray& lstActions);
    CRedoUndoBuffer m_redo;
    CRedoUndoBuffer m_undo;
};

class CURRotate : public CRUAct
{
public:
    CURRotate(int nPage, int nRotate);
    virtual void Redo();
    virtual void Undo();
protected:
    int m_nPage;
    int m_nRotate;
};

CRedoUndo::CRedoUndo()
{
}

CRedoUndo::~CRedoUndo()
{
    Clear(m_undo);
    Clear(m_redo);
}

void CRedoUndo::Clear(CRedoUndoBuffer& ru)
{
    POSITION pos;
    CRUAct *pRUAct;
    for (pos=ru.GetHeadPosition();pos != NULL;)
    {
        pRUAct = ru.GetNext(pos);
        ASSERT(pRUAct);
        delete pRUAct;
    }
    ru.RemoveAll();
}

void CRedoUndo::AddUndo(CRUAct *pRUAct)
{
    m_undo.AddHead(pRUAct);
    Clear(m_redo);
}

void CRedoUndo::AddRedo(CRUAct *pRUAct)
{
    m_redo.AddHead(pRUAct);
}

void CRedoUndo::Redo(int nNum)
{
    for (int i=0;i<nNum;i++)
    {
        CRUAct *pRUA = m_redo.GetHead();
        pRUA->Redo();
        m_redo.RemoveHead();
        pRUA->SetIsUndo(TRUE);
        m_undo.AddHead(pRUA);
    }
}

void CRedoUndo::Undo(int nNum)
{
    for (int i=0;i<nNum;i++)
    {
        CRUAct *pRUA = m_undo.GetHead();
        pRUA->Undo();
        m_undo.RemoveHead();
        pRUA->SetIsUndo(FALSE);
        m_redo.AddHead(pRUA);
    }
}

BOOL CRedoUndo::CanRedo()
{
    return m_redo.GetSize() > 0;
}

BOOL CRedoUndo::CanUndo()
{
    return m_undo.GetSize() > 0;
}

void CRedoUndo::GetRedoActions(CStringArray& lstActions)
{
    Fill(m_redo, lstActions);
}

void CRedoUndo::GetUndoActions(CStringArray& lstActions)
{
    Fill(m_undo, lstActions);
}

void CRedoUndo::Fill(CRedoUndoBuffer& ru, CStringArray& lstActions)
{
    CRUAct *pRUAct;
    for (POSITION pos = ru.GetHeadPosition(); pos != NULL;)
    {
        pRUAct = ru.GetNext(pos);
        ASSERT(pRUAct);
        lstActions.Add(pRUAct->GetText());
    }
}

CURRotate::CURRotate(int nPage, int nRotate)
{
    m_nPage = nPage;
    m_nRotate = nRotate;
    if (nRotate > 0)
        m_strText.LoadString(ID_VIEW_COUNTERCLOCKWISE);
    else
        m_strText.LoadString(ID_VIEW_CLOCKWISE);
    int nPos = m_strText.Find('\n');
    if (nPos > 0)
        m_strText.SetAt(nPos,0);
}

void CURRotate::Redo()
{
    Rotate(m_nPage,m_nRotate,FALSE);
}

void CURRotate::Undo()
{
    Rotate(m_nPage,-m_nRotate,FALSE);
}