form里面有很多edit控件,用户可以输入
当点击撤销按钮时,能够将刚才的操作撤销

解决方案 »

  1.   

    以下代码用于RichEdit,希望你能变通使用。
    { 功能:管理 Undo 和 Redo. }{ 说明:采用循环队列记录Undo动作和Redo动作, }{ Undo和Redo是两个不同的队列。 }{ }{**********************************************************}unit ActsMgr;interfaceusesWindows, Messages, SysUtils, Classes,Controls, Forms, Dialogs;typeTActType = ( //动作类型atNone,atModify,atInsert,atDelete);PAct = ^TAct;TAct = record //动作记录Enabled: Boolean; //该动作是否能用ActType: TActType; //动作类型Buf: string; //缓冲区Offset: Integer; //偏移Count: Integer; //字节数CurPos: Integer; //光标位置Prev: PAct; //Prev指针Next: PAct; //Next指针end;TActs = array of TAct;TActsMgr = classprivateFUndoActs: TActs; //Undo队列FUndoHead: PAct; //队列头指针FUndoTail: PAct; //队列尾指针FRedoActs: TActs; //Redo队列FRedoHead: PAct; //队列头指针FRedoTail: PAct; //队列尾指针FMaxUndo: Integer; //最大Undo次数procedure SetMaxUndo(Value: Integer);procedure InitAct(var Act: TAct);publicconstructor Create(AMaxUndo: Integer);destructor Destroy; override;property MaxUndo: Integer read FMaxUndo write SetMaxUndo;function AddUndoItem: PAct;function AddRedoItem: PAct;function Undo: PAct;function Redo: PAct;function CanUndo: Boolean;function CanRedo: Boolean;end;implementationconstructor TActsMgr.Create(AMaxUndo: Integer);beginSetMaxUndo(AMaxUndo);end;destructor TActsMgr.Destroy;beginSetLength(FUndoActs, 0);SetLength(FRedoActs, 0);end;procedure TActsMgr.SetMaxUndo(Value: Integer);vari: Integer;beginFMaxUndo := Value;SetLength(FUndoActs, FMaxUndo + 1);for i := 0 to FMaxUndo dobeginif i = FMaxUndo thenFUndoActs[i].Next := @FUndoActs[0]elseFUndoActs[i].Next := @FUndoActs[i+1];if i = 0 thenFUndoActs[i].Prev := @FUndoActs[FMaxUndo]elseFUndoActs[i].Prev := @FUndoActs[i-1];FUndoActs[i].Enabled := False;end;FUndoHead := @FUndoActs[0];FUndoTail := @FUndoActs[0];SetLength(FRedoActs, FMaxUndo + 1);for i := 0 to FMaxUndo dobeginif i = FMaxUndo thenFRedoActs[i].Next := @FRedoActs[0]elseFRedoActs[i].Next := @FRedoActs[i+1];if i = 0 thenFRedoActs[i].Prev := @FRedoActs[FMaxUndo]elseFRedoActs[i].Prev := @FRedoActs[i-1];FRedoActs[i].Enabled := False;end;FRedoHead := @FRedoActs[0];FRedoTail := @FRedoActs[0];end;procedure TActsMgr.InitAct(var Act: TAct);beginwith Act dobeginEnabled := True;Buf := '';Offset := 0;Count := 0;CurPos := 0;end;end;function TActsMgr.AddUndoItem: PAct;beginInitAct(FUndoHead^);Result := FUndoHead;if FUndoHead^.Next = FUndoTail thenFUndoTail := FUndoTail^.Next;FUndoHead := FUndoHead^.Next;FUndoHead^.Enabled := False;end;function TActsMgr.AddRedoItem: PAct;beginInitAct(FRedoHead^);Result := FRedoHead;if FRedoHead^.Next = FRedoTail thenFRedoTail := FRedoTail^.Next;FRedoHead := FRedoHead^.Next;FRedoHead^.Enabled := False;end;function TActsMgr.Undo: PAct;beginif not CanUndo thenbeginResult := nil;Exit;end;FUndoHead := FUndoHead^.Prev;FRedoHead := FRedoHead^.Prev;Result := FUndoHead;end;function TActsMgr.Redo: PAct;beginif not CanRedo thenbeginResult := nil;Exit;end;Result := FRedoHead;FRedoHead := FRedoHead^.Next;FUndoHead := FUndoHead^.Next;end;function TActsMgr.CanUndo: Boolean;beginResult := (FUndoHead <> FUndoTail);end;function TActsMgr.CanRedo: Boolean;beginResult := FRedoHead^.Enabled;end;end.