转贴:无限 Undo 和 Redo 功能 RichEdit 控件怎样实现 RxRichEdit 的无限 UnDo 功能? 在 RxRichEdit 里的查找对话框如果遮住了选定的文字时 ,会自动移开 ,请问是怎样实现的? 请给出代码可以吗?!最好有说明 ,谢谢~ :Zephyr, 时间 :2000-4-9 23:49:22, ID:216632多重 Undo 和 Redo 要 RichEdit v2.0 才提供 ,要用到 EM_SETUNDOLIMIT EM_GETUNDONAME EM_GETREDONAME EM_UNDO EM_CANUNDO EM_REDO EM_CANREDO :beta, 时间 :2001-5-20 11:02:30, ID:536939自己实现 ,不过很麻烦 :-p每次改变都把改变的 开始位置、长度、字符串和类型 添加到一个 TList 里面 ( 用一个 record)Undo 也就是提出某次操作的这些信息然后实现就可以了 ,你想 ,有了这些信息 ,完全可以重现原来的操作了 不过好像 Redo 还要用一个 TList,和 Undo 的不是同一个。 我曾经想做过 ,不过无法截获文字拖拽的消息 ,于是放弃 :-(mantousoft, 时间 :2001-5-29 19:33:11, ID:546071去下载 MiniHex 的源代码看看 ,下面是我从里面抄的 :){**********************************************************}{ }{ 功能 : 管理 Undo 和 Redo. }{ 说明 : 采用循环队列记录 Undo 动作和 Redo 动作 , }{ Undo 和 Redo 是两个不同的队列。 }{ }{**********************************************************} unit ActsMgr; interface uses 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; implementation constructor 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.
不行 编译要出错Build [Error] UMain.pas(370): Undeclared identifier: 'TAct' [Error] UMain.pas(371): Identifier redeclared: 'TAct' [Error] UMain.pas(373): Constant or type identifier expected [Error] UMain.pas(380): Constant or type identifier expected [Error] UMain.pas(381): Class, interface and object types only allowed in type section [Fatal Error] UMain.pas(388): Could not compile used unit 'UnitInsertChar.pas'问下楼上,帖子在哪里转的,麻烦地址给出来。另:有没有一个好点的关于无限Undo Redo的源码例子下载。谢谢大家。
与 hqhhh(枫叶) 相同,,,发送一个 EM_UNDO 消息就行了,
RichEdit1.perform(EM_SETUNDOLIMIT, 100, 0);100 - undo limit(works just for RichEdit 2, does not work on Memo and Edit)
RichEdit 控件怎样实现 RxRichEdit 的无限 UnDo 功能? 在 RxRichEdit 里的查找对话框如果遮住了选定的文字时 ,会自动移开 ,请问是怎样实现的?
请给出代码可以吗?!最好有说明 ,谢谢~
:Zephyr, 时间 :2000-4-9 23:49:22, ID:216632多重 Undo 和 Redo 要 RichEdit v2.0 才提供 ,要用到 EM_SETUNDOLIMIT EM_GETUNDONAME EM_GETREDONAME EM_UNDO EM_CANUNDO EM_REDO EM_CANREDO
:beta, 时间 :2001-5-20 11:02:30, ID:536939自己实现 ,不过很麻烦 :-p每次改变都把改变的 开始位置、长度、字符串和类型 添加到一个 TList 里面 ( 用一个 record)Undo 也就是提出某次操作的这些信息然后实现就可以了 ,你想 ,有了这些信息 ,完全可以重现原来的操作了 不过好像 Redo 还要用一个 TList,和 Undo 的不是同一个。
我曾经想做过 ,不过无法截获文字拖拽的消息 ,于是放弃 :-(mantousoft, 时间 :2001-5-29 19:33:11, ID:546071去下载 MiniHex 的源代码看看 ,下面是我从里面抄的 :){**********************************************************}{ }{ 功能 : 管理 Undo 和 Redo. }{ 说明 : 采用循环队列记录 Undo 动作和 Redo 动作 , }{ Undo 和 Redo 是两个不同的队列。 }{ }{**********************************************************}
unit ActsMgr;
interface
uses 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;
implementation
constructor 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.
编译要出错Build
[Error] UMain.pas(370): Undeclared identifier: 'TAct'
[Error] UMain.pas(371): Identifier redeclared: 'TAct'
[Error] UMain.pas(373): Constant or type identifier expected
[Error] UMain.pas(380): Constant or type identifier expected
[Error] UMain.pas(381): Class, interface and object types only allowed in type section
[Fatal Error] UMain.pas(388): Could not compile used unit 'UnitInsertChar.pas'问下楼上,帖子在哪里转的,麻烦地址给出来。另:有没有一个好点的关于无限Undo Redo的源码例子下载。谢谢大家。
delphi没有支持吧