程序结束时PNGImage“访问冲突”错误

时间:2015-05-07 14:36:15

标签: delphi png delphi-7

我在我的项目中使用PNGImage库,整个GUI由.png图像组成,我在运行时加载到TImages。出于某些目的,我必须动态创建大量彼此相似的组件组。每个组都包含一些TImages,并有一个按钮,允许用户进入另一个页面,其中包含有关被点击项目的更多详细信息。

我正在使用的代码:

procedure TMain_Frame.selection_click(Sender: TObject);
var id: string;
begin
  id := StringReplace(TLabel(sender).Name, 'label_item_select_', '', [rfReplaceAll]);
  hide_created_components; // It does Free all components
  show_details(id);
end; // (1)
Access violation发生

(1)错误。奇怪的是它发生完全随机:错误可能在第一次点击时发生,或者可能不会发生10次点击。如果没有发生错误,F8会引导我进入PNGImage库,其中有些东西已完成。但是当发生错误时,F7 / 8立即抛出它而不做它必须做的事情。只有当我从动态创建的对象转到静态时,才会出现此问题。

CPU窗口显示此ASM代码发生错误:

movzx ecx, [edi]

ecx值为755A2E09,edi为00000000

.Free所有动态创建的组件是否正确?或者应该使用.Destroy代替?为什么PNGImage会在程序end;内部进入?

<小时/> 演示:

unit Unit1;
interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, pngimage, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Image1: TImage;
    procedure selection_click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure create_label;
var Button: TLabel;
begin
  Button := TLabel.Create(Form1);
  with Button do
  begin
    Name := 'dynamic_label_1';
    Parent := Form1;
    Autosize := false;
    Left := 100;
    Top := 100;
    Width := 150;
    Height := 20;
    Caption := 'Dynamic Label: Click Me';
    BringToFront;
    Cursor := crHandPoint;
  end;
  Button.OnClick := Form1.selection_click;
end;

procedure hide_dyn_label(L: TLabel; mode: boolean);
begin
  if mode then
  begin
    L.Free;
    Form1.Image1.Picture.LoadFromFile(PAnsiChar('button_close.png'));
    Form1.Image1.Visible := true;
  end
  else
    create_label;
end;

procedure TForm1.selection_click(Sender: TObject);
var id: string;
begin
  id := StringReplace(TLabel(Sender).Name, 'dynamic_label_', '', [rfReplaceAll]);
  Form1.Button1.Visible := true;
  hide_dyn_label(Form1.FindComponent('dynamic_label_1') as TLabel, true);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  create_label;
  Form1.Image1.Visible := false;
  Form1.Button1.Visible := false;
end;

end.

1 个答案:

答案 0 :(得分:7)

您仍然在其TLabel事件处理程序OnClick中释放Selection_Clickhide_dyn_label()调用调用L.Free的{​​{1}}。你不能这样做。使用某种延迟破坏,f.ex。使用布尔变量FreeDynLabels,您可以在Application.OnIdle中查看。或者将自定义消息发布到表单。