【发布时间】:2013-10-28 22:24:11
【问题描述】:
我需要能够在我简单的 delphi 绘图中进行撤消和重做操作。所以我决定做一些容器来保存历史(不是完整的历史,只有几个以前的位图文件)。
unit HistoryQueue;
interface
uses
Graphics;
type
myHistory = class
constructor Create(Size:Integer);
public
procedure Push(Bmp:TBitmap);
function Pop():TBitmap;
procedure Clean();
procedure Offset();
function isEmpty():boolean;
function isFull():boolean;
function getLast():TBitmap;
protected
end;
var
historyQueueArray: array of TBitmap;
historyIndex, hSize:Integer;
implementation
procedure myHistory.Push(Bmp:TBitmap);
var tbmp:TBitmap;
begin
if(not isFull) then begin
Inc(historyIndex);
historyQueueArray[historyIndex]:=TBitmap.Create;
historyQueueArray[historyIndex].Assign(bmp);
end else begin
Offset();
historyQueueArray[historyIndex]:=TBitmap.Create;
historyQueueArray[historyIndex].Assign(bmp);
end;
end;
procedure myHistory.Clean;
var i:Integer;
begin
{ for i:=0 to hSize do begin
historyQueueArray[i].Free;
historyQueueArray[i].Destroy;
end; }
end;
constructor myHistory.Create(Size:Integer);
begin
hSize:=Size;
SetLength(historyQueueArray, hSize);
historyIndex:=-1;
end;
function myHistory.isEmpty: boolean;
begin
Result:=(historyIndex = -1);
end;
function myHistory.isFull: boolean;
begin
Result:=(historyIndex = hSize);
end;
procedure myHistory.Offset;
var i:integer;
begin
//historyQueueArray[0]:=nil;
for i:=0 to hSize-1 do begin
historyQueueArray[i]:=TBitmap.Create;
historyQueueArray[i].Assign(historyQueueArray[i+1]);
end;
end;
function myHistory.Pop: TBitmap;
var
popBmp:TBitmap;
begin
popBmp:= TBitmap.Create;
popBmp.Assign(historyQueueArray[historyIndex]);
Dec(historyIndex);
Result:=popBmp;
end;
function myHistory.getLast: TBitmap;
var
tBmp:TBitmap;
begin
tBmp:= TBitmap.Create;
tBmp.Assign(historyQueueArray[historyIndex]);
Result:=tBmp;
end;
end.
在我的程序中我就是这样使用它的。
保存在历史中:
procedure TMainForm.FormCreate(Sender: TObject);
begin
{...}
picHistory:=myHistory.Create(10); //FOR UNDO
tempHistory:=myHistory.Create(10); //FOR REDO
end;
//if mouse is up - that mean we finish to draw something on canvas, so we gonna save what we drew
procedure TMainForm.imgMainMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var bmp:TBitmap;
begin
mouseIsDown:=false;
bmp:=TBitmap.Create;
try
bmp.Assign(imgMain.Picture.Bitmap);
picHistory.Push(bmp);
finally
bmp.Free;
end;
end;
并进行撤消和重做。
procedure TMainForm.btnUndoClick(Sender: TObject);
var redBmp:TBitmap;
begin
if(not picHistory.isEmpty) then begin //if we draw something before
//prepare to save what've done into history for redo
redBmp:=TBitmap.Create;
redBmp.Assign(picHistory.getLast);
//showing what were done with image before on screen
MainForm.imgMain.Canvas.Draw(0,0, picHistory.Pop);
//but in case we want to be able get back our last changes we save it into redo history
tempHistory.Push(redBmp);
redBmp.Free;
end;
end;
{...}
procedure TMainForm.btnRedoClick(Sender: TObject);
begin
//if there were something into history for redo then show int on canvas
if(not tempHistory.isEmpty) then
MainForm.imgMain.Canvas.Draw(0,0, tempHistory.Pop);
end;
但是有一些奇怪的事情发生了——我推动Undo 没有任何改变。当我继续 Redo 时,它就像 Undo 一样工作。
顺便说一句,当我以不同的长度声明重做和撤消的历史时
procedure TMainForm.FormCreate(Sender: TObject);
begin
{...}
picHistory:=myHistory.Create(6); //FOR UNDO
tempHistory:=myHistory.Create(12); //FOR REDO
end;
然后逐步了解picHistory 中发生的情况,它的数组长度似乎不是 6,而是 12!所以我认为这两个对象使用同一个数组!为什么会发生这种情况以及如何改正?
【问题讨论】:
标签: delphi bitmap delphi-7 paint undo-redo