我做一个程序,需要有undo和redo功能,请教各位右经验的大虾们,该如何下手,使用剪贴板呢还是其他!请详细点!先给100分(我一次最多只能给100),不过零开贴给!

解决方案 »

  1.   

    怎么会用到剪贴版呢,又不是拷贝粘贴。
    具体的你可以看看一个叫memomize的模式!
      

  2.   

    定义一个结构,存放以前的操作,进行undo或redo时,利用保存的操作数据进行恢复或重新操作
      

  3.   

    我是操作的一个文件,我不能每次把它全部保存八,那样很占内存的!to  yhb4(胖子)
    如何使用缓存机制,请详细好么?
      

  4.   

    可看看一个叫做"memomize"的模式
      

  5.   

    定义一个数据结构,设定可redo, undo的次数,每次CTRL+C的时候,
    1).将剪贴板中内容取出保存
    2).将当前选择内容置于剪贴板中
     undo的时候,指针前移一次,取出其内容填充,直遇到HEAD,
     redo的时候,指针后移一次,取出其内容填充,直遇到TAIL-->剪贴板
    至于占用内存的问题,可以有很多办法解决,一种就是当数据超过一定容量的时候,
    将其保存到文件中,你的数据结构中只保留着索引;另一种就是用内存映射文件等等都可以...
      

  6.   

    多步Undo/Redo的实现
        应用软件中,Undo/Redo功能为用户提供了方便,而多步Undo/Redo则更是如此。
    本文利用C++面对象的程序设计技术,研究了多步Undo/Redo的实现方法。    首先,我们建立一个基类CEditRecord,对于每一种操作,都从该基类上派
    生出与操作相对应的类,记载操作过程,供以后进行具体的Undo/Redo操作;基
    类CEditRecord中的纯虚函数,为Undo、Redo操作提供接口。    然后,我们建立一个用于控制Undo/Redo的类:CRecordCtrl。 CRecordCtrl
    类从基类CObArray上派生,用于记载已经进行过的操作,响应Undo/Redo命令等;
    其中的nMaxStep变量表示允许Undo/Redo的次数,nCurrRecord变量表示当前的Undo
    的位置;函数Undo()和Redo()用于响应来自系统菜单、快捷键或者工具条的Undo
    和Redo命令;函数SetMaxStep()用于设置允许Undo/Redo的次数。////////////////////////////////////////////////////////
    // CEditRecord.h
    // Class CEditRecord、CEditCtrl Definition
    class CEditRecord : public CObject
    {
    public:
    CEditRecord();
    public: 
    virtual BOOL Undo( )=0;
    virtual BOOL Redo( )=0;
    };class CRecordCtrl:public CObArray
    {
    public:
    CRecordCtrl( );
    ~CRecordCtrl( );
    private: 
    int nCurrRecord;
    int nMaxStep;
    public:
    BOOL EnableUndo( );
    BOOL EnableRedo( );
    BOOL Undo( );
    BOOL Redo( );
    BOOL SetMaxStep(int n); 
    }; extern CEditCtrl Records;
    ////////////////////////////////////////////////////
    // CEditRecord.Cpp
    // Class CEdit、CEditCtrl Imeplemetion#include "CEditRecord.h"
    CRecordCtrl Records;CEditRecord::CEditRecord( )
    {
    int mm=Records.GetSize( );
    if(nCurrRecord==mm-1)

    if(mm==nMaxStep)
    {
    //删除最早的记录
    CEditRecord* pRec=(CEditRecord*)GetAt(0);
    delete pRec;
    Records.RemoveAt(0);
    nCurrRecord--;
    }
    }
    else
    {
    //删除所有Undo过的记录
    for(int i=mm-1;i>nCurrRecord;i--)
    {
    CEditRecord* pRec=(CEditRecord*)GetAt(i);
    delete pRec;
    Records.RemoveAt(i); 

    } nCurrRecord=Records.Add(this);
    }CRecordCtrl::CRecordCtrl( )
    {
    nCurrRecord=-1;
    nMaxStep=5;
    }CRecordCtrl::~CRecordCtrl( )
    {
    for(int i=GetSize()-1;i>=0;i--)
    {
    CEditRecord* pUndo=(CEditRecord*)GetAt(i);
    delete pUndo;
    }
    }BOOL CRecordCtrl::EnableUndo( )
    {
    return (nCurrRecord>=0);
    }BOOL CRecordCtrl::EnableRedo( )
    {
    return (nCurrRecord<GetSize( )-1);
    }BOOL CRecordCtrl::Undo( )
    {
    if(!EnableUndo( )) return FALSE;CEditRecord* pRec=(CEditRecord*)GetAt(nCurrRecord--);
    if(pRec==NULL) return FALSE;return pRec->Undo();
    }BOOL CRecordCtrl::Redo()
    {
    if(!EnableRedo( )) return FALSE;CEditRecord* pRec=(CEditRecord*)GetAt(++nCurrRecord);
    if(pRec==NULL) return FALSE;return pRec->Redo();
    }
    BOOL CRecordCtrl::SetMaxStep(int n)
    {
    if(n<1) return FALSE;
    int mm=GetSize( );if(UndoStep<=n || mm<=n) 
    {
    UndoStep=n;
    return TRUE;

    else 

    //压缩用于Undo的记录
    int nPack=mm-n;
    int u=min(nCurrRecord,nPack);
    for(int i=u-1;i>=0;i--)
    {
    CEditRecord* pRec=(CEditRecord*)GetAt(i);
    delete pRec; 
    nCurrRecord--;
    }//压缩用于Redo的记录
    int v=nPack-u;
    for(int i=0;i<v;i++)
    {
    CEditRecord* pRec=(CEditRecord*)GetAt(mm-i-1);
    if(pRedo==NULL) delete pRec; 
    }

    return TRUE;
    }
    在CEditRecord的生成函数中,首先判定是否达到允许的最大Undo次数; 如果
    未达到,直接把this指针加入到阵列中;如果超过,需要从阵列中,清除一些关于早期的操作的记录,然后把this
    指针加入到阵列中。函数CRecordCtrl::SetMaxStep( )中,对于缩小Undo/Redo次数这种情况,特别是在阵列中已经
    记载了较多的操作,则需清除一些。在CRecordCtrl类的析构函数中,清除阵列中的每一个CEditRecord对象。下面给出一个例子说明如何建立CEditRecord对象,为方便计,假设进行的操作是从一个全局性
    的字符串pText中删除一段内容,我们用Pos表示所删内容在pText中的相对位置, 用Len表示所删内
    容的长度,并假设全局串pTetx的存储空间足够大。1.从基类CEditRecord上派生出CEditCutString;
    2.设置私有变量Pos、Len用于表示所删内容在pText中的相对位置、长度;设置私有变量pBuff
    用于分配存储空间,保存所删内容;设置私有变量Avialiable用于表示可否进行Undo/Redo。/////////////////////////////////////////////////////
    // Example 
    // 
    #include "CEditRecord.h"class CEditCutString:public CEditRecord
    {
    public:
    CEditCutString(int,int);
    ~CEditCutString(); 
    private:
    int Pos;
    int Len;
    char* pBuff; 
    BOOL Avialiable;public:
    virtual BOOL Undo();
    virtual BOOL Redo(); 
    };
    CEditCutString::CEditCutString(int p,int n)
    {
    Pos=p;
    Len=n; 
    pBuff=new char[n]; if(pBuff==NULL)
    Avialiable=FALSE;
    esle

    Avialiable=TRUE; 
    memcpy(pBuff,pText+Pos,Len);
    }
    }CEditCutString::~CEditCutString
    {
    if(Avialiable)
    delete []pBuff; 
    }BOOL CEditCutString::Undo()
    {
    if(!Avialiable)
    return FALSE; int l=strlen(pText);
    for(int i=l;i>=Pos;i--)
    pText[i+Len]=pText[i]; for(int j=0;j<Len;j++)
    pText[Pos+j]=pBuff[j];return TRUE;
    }BOOL CEditCutString::Redo()
    {
    if(!Avialiable)
    return FALSE; int l=strlen(pText);for(int i=Pos;i<=l-Len;i++)
    pText[i]=pText[i+Len]; return TRUE;
    }