您好,欢迎来到九壹网。
搜索
您的当前位置:首页多步Undo Redo的实现

多步Undo Redo的实现

来源:九壹网
多步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 classCEditRecord : public CObject {

public:

CEditRecord(); public:

virtual BOOL Undo( )=0; virtual BOOL Redo( )=0; };

classCRecordCtrl:publicCObArray {

public:

CRecordCtrl( ); ~CRecordCtrl( ); private:

intnCurrRecord; intnMaxStep; public:

BOOL EnableUndo( ); BOOL EnableRedo( ); BOOL Undo( ); BOOL Redo( );

BOOL SetMaxStep(int n); };

externCEditCtrl Records;

//////////////////////////////////////////////////// // CEditRecord.Cpp

// Class CEdit、CEditCtrlImeplemetion

#include \"CEditRecord.h\" CRecordCtrl Records;

CEditRecord::CEditRecord( ) {

int mm=Records.GetSize( ); if(nCurrRecord==mm-1) {

if(mm==nMaxStep) {

//删除最早的记录

CEditRecord* pRec=(CEditRecord*)GetAt(0); deletepRec;

Records.RemoveAt(0); nCurrRecord--; } } else {

//删除所有Undo过的记录

for(int i=mm-1;i>nCurrRecord;i--) {

CEditRecord* pRec=(CEditRecord*)GetAt(i); deletepRec;

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); deletepUndo; } }

BOOL CRecordCtrl::EnableUndo( ) {

return (nCurrRecord>=0); }

BOOL CRecordCtrl::EnableRedo( ) {

return (nCurrRecordBOOL CRecordCtrl::Undo( ) {

if(!EnableUndo( )) return FALSE;

CEditRecord* pRec=(CEditRecord*)GetAt(nCurrRecord--); if(pRec==NULL) return FALSE;

returnpRec->Undo(); }

BOOL CRecordCtrl::Redo() {

if(!EnableRedo( )) return FALSE;

CEditRecord* pRec=(CEditRecord*)GetAt(++nCurrRecord); if(pRec==NULL) return FALSE;

returnpRec->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的记录 intnPack=mm-n;

int u=min(nCurrRecord,nPack); for(int i=u-1;i>=0;i--) {

CEditRecord* pRec=(CEditRecord*)GetAt(i); deletepRec; nCurrRecord--; }

//压缩用于Redo的记录 int v=nPack-u;

for(int i=0;iCEditRecord* 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\"

classCEditCutString:publicCEditRecord {

public:

CEditCutString(int,int); ~CEditCutString(); private: intPos; int Len;

char* pBuff; BOOL Avialiable;

public:

virtual BOOL Undo(); virtual BOOL Redo(); };

CEditCutString::CEditCutString(intp,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;jreturn 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; }

参考文献:

[1] Microsoft Visual C++ 2.0 for Win32大全,Microsoft Corporation著, 清华大学出版社,1996

[2] Davis,S.K.,Hands-On Turbo C++, Addison-Wesley, Reading, MA, 1991 [3] 张国锋,C++语言及其程序设计教程,电子工业出版社,1992

_____________________________________________________________________________________

The Realize of MutiRedo/MutiUndo

Wang Zemin

(Guangdong CommerialCollege,Guangzhou)

Abstract: In this paper, we study the realize of mutistep undo/redo, and we give an

example about this.

Keywords: base class,derivedclass,virtual function.

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务