简体   繁体   English

Delphi XE2-loadfromfile pngimage中的访问冲突

[英]Delphi XE2 - Access violation in loadfromfile pngimage

I have a listbox of images that normally works fine, but today it throws a access violation for no apparent reason. 我有一个通常可以正常工作的图像列表框,但是今天,它没有明显的原因引发访问冲突。

Here is my code: 这是我的代码:

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;

The file exists and it's a .png. 该文件存在,并且是一个.png文件。

The bug happens just on the fifth image. 该错误仅发生在第五张图像上。

Problem solved: 问题解决了:

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;

You have a memory leak, as you are not freeing the TPngImage objects you create. 您有内存泄漏,因为您没有释放创建的TPngImage对象。 But worse, you should NOT be loading image files during a drawing operation to begin with. 但是更糟糕的是,在开始绘制过程中,您不应该加载图像文件。 You should instead load the images once beforehand and then reuse them each time an item need to be drawn. 相反,您应该预先加载图像一次,然后在每次需要绘制项目时重新使用它们。

Try something more like this: 尝试更多类似这样的方法:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM