就是维护一个一定次数内的操作队列
解决方案 »
- Dephi需要包
- delphi中关于TStream的问题
- MScomm控件串口:十进制大于127就不能显示到LED的问题
- 如何取得另一程序中多个文本框的句柄和内容
- 在delphi中, 如何调用access2000数据库的报表?
- IdTCPClient中memorystream 的接收问题!急+郁闷!一晚上没折腾出来!
- 请问在TreeView控件范围内如何判断鼠标当前点击的位置不是节点位置,而是空白区域?
- 导出Excel的问题
- zswang(伴水)(需要充充电) 来拿分。
- 如何在程序中控制设置ODBC数据源的用户数据源?
- 菜鸟问题:用mediaPlay控件可以对.wav文件按帧播放吗?
- 高手救命阿,好奇怪阿???
{**********************************************************}
{ }
{ 功能:管理 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.