就是维护一个一定次数内的操作队列

解决方案 »

  1.   

    在delphi栏里找到的
    {**********************************************************}
    {                                                          }
    {  功能:管理 Undo 和 Redo.                                }
    {  说明:采用循环队列记录Undo动作和Redo动作,              }
    {        Undo和Redo是两个不同的队列。                      }
    {                                                          }
    {**********************************************************}unit ActsMgr;interfaceuses
      Windows, Messages, SysUtils, Classes,
      Controls, Forms, Dialogs;type
      TActType = (              //动作类型
                  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 = class
      private
        FUndoActs: 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);  public
        constructor 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);
    begin
      SetMaxUndo(AMaxUndo);
    end;destructor TActsMgr.Destroy;
    begin
      SetLength(FUndoActs, 0);
      SetLength(FRedoActs, 0);
    end;procedure TActsMgr.SetMaxUndo(Value: Integer);
    var
      i: Integer;
    begin
      FMaxUndo := Value;
      SetLength(FUndoActs, FMaxUndo + 1);
      for i := 0 to FMaxUndo do
      begin
        if i = FMaxUndo then
          FUndoActs[i].Next := @FUndoActs[0]
        else
          FUndoActs[i].Next := @FUndoActs[i+1];
        if i = 0 then
          FUndoActs[i].Prev := @FUndoActs[FMaxUndo]
        else
          FUndoActs[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 do
      begin
        if i = FMaxUndo then
          FRedoActs[i].Next := @FRedoActs[0]
        else
          FRedoActs[i].Next := @FRedoActs[i+1];
        if i = 0 then
          FRedoActs[i].Prev := @FRedoActs[FMaxUndo]
        else
          FRedoActs[i].Prev := @FRedoActs[i-1];
        FRedoActs[i].Enabled := False;
      end;
      FRedoHead := @FRedoActs[0];
      FRedoTail := @FRedoActs[0];
    end;procedure TActsMgr.InitAct(var Act: TAct);
    begin
      with Act do
      begin
        Enabled := True;
        Buf := '';
        Offset := 0;
        Count := 0;
        CurPos := 0;
      end;
    end;function TActsMgr.AddUndoItem: PAct;
    begin
      InitAct(FUndoHead^);
      Result := FUndoHead;  if FUndoHead^.Next = FUndoTail then
        FUndoTail := FUndoTail^.Next;
      FUndoHead := FUndoHead^.Next;
      FUndoHead^.Enabled := False;
    end;function TActsMgr.AddRedoItem: PAct;
    begin
      InitAct(FRedoHead^);
      Result := FRedoHead;  if FRedoHead^.Next = FRedoTail then
        FRedoTail := FRedoTail^.Next;
      FRedoHead := FRedoHead^.Next;
      FRedoHead^.Enabled := False;
    end;function TActsMgr.Undo: PAct;
    begin
      if not CanUndo then
      begin
        Result := nil;
        Exit;
      end;
      FUndoHead := FUndoHead^.Prev;
      FRedoHead := FRedoHead^.Prev;
      Result := FUndoHead;
    end;function TActsMgr.Redo: PAct;
    begin
      if not CanRedo then
      begin
        Result := nil;
        Exit;
      end;
      Result := FRedoHead;
      FRedoHead := FRedoHead^.Next;
      FUndoHead := FUndoHead^.Next;
    end;function TActsMgr.CanUndo: Boolean;
    begin
      Result := (FUndoHead <> FUndoTail);
    end;function TActsMgr.CanRedo: Boolean;
    begin
      Result := FRedoHead^.Enabled;
    end;end.
      

  2.   

    我的方法最简单:你把文件每操作一次都保存一份临时文件(也可以选择只保存关键部分),然后的工作就是维持这个文件序列!