2013-10-20 56 views
2

我需要能夠使用簡單的delphi繪製Undo和Redo操作符。所以我決定做一些容器來保存歷史記錄(不是完整的歷史記錄,只有少數以前的位圖文件)。兩個不同的對象使用一個內存區域?

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

以及當我分步申報歷史重做,並用不同的lenght撤消像

procedure TMainForm.FormCreate(Sender: TObject); 
begin 
{...} 
    picHistory:=myHistory.Create(6); //FOR UNDO 
    tempHistory:=myHistory.Create(12); //FOR REDO 
end; 

然後豔記的方式會發生什麼picHistory好像lenght的這陣不是6,這是12!所以我認爲這兩個對象使用同一個數組!爲什麼會發生,以及如何使它正確?

回答

5

myHistory類的兩個實例共享相同的全局數據。您必須將您的數據聲明移到類中,以使其成爲每個實例的數據而不是全局數據。

試試這個:

type 
myHistory = class 
    private 
    historyQueueArray: array of TBitmap; //Now they are class members instead of global 
    historyIndex, hSize:Integer; 
    public 
    constructor Create(Size:Integer); 
    procedure Push(Bmp:TBitmap); 
    function Pop():TBitmap; 
    procedure Clean(); 
    procedure Offset(); 
    function isEmpty():boolean; 
    function isFull():boolean; 
    function getLast():TBitmap; 
    protected 
    end; 
+0

謝謝你,先生!我甚至沒有自己意識到,當我急於做出某些事情時,我比以前更愚蠢:c – DanilGholtsman

相關問題