Delphi XE2 - loadfromfile pngimage中的访问冲突

时间:2014-04-25 18:23:50

标签: delphi listbox delphi-xe2 access-violation

我有一个通常正常工作的图像列表框,但今天它没有明显的原因引发访问冲突。

这是我的代码:

procedure TfrmSelectIcon.ListBox1DrawItem(Control: TWinControl; Index: integer;
  Rect: TRect; State: TOwnerDrawState);
var
  icone: TImageItem; // Ticone;
  png1: TPngImage;
  ImageIcone: TPngImage;
  TextPosition: integer;
  nomearquivo: string;
  Images: TImageList;
begin

  icone := TImageItem(listaIcone.Items[StrToInt(TListBox(Control).Items.Strings
    [Index])]);
  // Ticone(listaIcone.Items[strtoint(TListBox(Control).Items.Strings[Index])]);
  nomearquivo := Diretorio + icone.arquivo;

  // ShowMessage(nomearquivo);

  TListBox(Control).Canvas.FillRect(Rect);
  if FileExists(nomearquivo) then
  begin
    png1 := TPngImage.Create;
    png1.LoadFromFile(nomearquivo);  //here happen the problem.
    png1.Draw(TListBox(Control).Canvas, Rect);
  end;

end;

该文件存在,它是一个.png。

错误发生在第五张图片上。

2 个答案:

答案 0 :(得分:2)

问题解决了:

TListBox(Control).Canvas.FillRect(Rect);
  if FileExists(nomearquivo) then
  begin
    png1 := TPngImage.Create;
    png1.LoadFromFile(nomearquivo);
    png1.Draw(TListBox(Control).Canvas, Rect);
    **FreeAndNil(png1);** //i put this line and works fine!
  end;

答案 1 :(得分:2)

您有内存泄漏,因为您没有释放您创建的TPngImage个对象。但更糟糕的是,您不应该在绘图操作期间加载图像文件。您应该事先加载一次图像,然后在每次需要绘制项目时重复使用它们。

尝试更像这样的事情:

private
  Images: array of TPngImage; // or any other container you want to use

...

procedure TfrmSelectIcon.FormDestroy(Sener: TObject);
var
  I: Integer;
begin
  for I := 0 to High(Images) do
    Images[I].Free;
end;

procedure TfrmSelectIcon.ListBox1DrawItem(Control: TWinControl; Index: integer; Rect: TRect; State: TOwnerDrawState);
var
  png: TPngImage;
begin
  png := Images[Index];
  if (png <> nil) and (not png.Empty) then
    png1.Draw(TListBox(Control).Canvas, Rect);
end;

var
  icone: TImageItem; // Ticone;
  nomearquivo: string;
  I: Integer;
begin
  SetLength(Images, ListBox1.Items.Count);
  for I := 0 to High(Images) do
    Images[I] := nil;
  for I := 0 to High(Images) do
  begin
    // personally, I would suggest storing the TImageItem pointers
    // in the TListBox.Items.Objects[] property for easier access:
    //
    // icone := TImageItem(ListBox1.Items.Objects[I]);
    //
    icone := TImageItem(listaIcone.Items[StrToInt(ListBox1.Items.Strings[I])]);

    nomearquivo := Diretorio + icone.arquivo;
    if FileExists(nomearquivo) then
    begin
      try
        Images[I] := TPngImage.Create;
        Images[I].LoadFromFile(nomearquivo);
      except
      end;
    end;
  end;
end;