两个不同的对象使用一个内存区域?

时间:2013-10-20 12:36:07

标签: delphi bitmap delphi-7 paint undo-redo

我需要能够在我的简单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一样。

顺便说一句,我宣布重做和撤消历史记录的方式与

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

然后在picHistory中发生的事情看起来好像它的数字长度不是6,它是12!所以我认为这两个对象使用同一个数组!为什么会发生这种情况以及如何使其正确?

1 个答案:

答案 0 :(得分: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;
相关问题