Delphi 7使用自定义组件的无效指针操作

时间:2013-09-26 23:04:35

标签: delphi custom-controls delphi-7

我有一个自定义组件类,我用它作为框架将注释和用户详细信息等加载到表单上。 Class是面板的子类,包含3个标签和一个备忘录。

关闭我的表单或尝试释放该对象后,我收到“无效的指针操作”错误。我知道这是试图释放一个对象两次,或访问不可用的RAM。但是,我不知道如何解决它。它让我退了很多,因为我必须在不同的主题上加载不同的评论,直到我清除当前评论的形式我才能做到。

以下是与课程相关的代码:

    type
      TSkeleton = class(TPanel)
        private
        fName : TLabel;
        fStudNo : TLabel;
        fTimeAndDate : TLabel;
        fComment : TMemo;
     public
       Constructor Create (AOwner: TComponent); overload; override;
       constructor Create(AOwner:TForm; sName, sStudNo, sTime, sDate, sComment: string; ComCount: integer); overload;
 end;
{ TSkeleton }

constructor TSkeleton.Create(AOwner: TComponent);
begin
//
end;

constructor TSkeleton.Create(AOwner: TForm; sName, sStudNo, sTime, sDate,
  sComment: string; ComCount: integer);
begin
  inherited Create(AOwner);
  Parent := AOwner;
  Width := 800;
  Height := 250;
  Top := 448+((ComCount-1)*250);
  Left := 16;
  BevelInner := bvSpace;
  BevelOuter := bvLowered;

  fName := TLabel.Create(fName);
  self.InsertControl(fName);
  with fName do
  begin
   Caption := sName;
   Font.Name := 'Garamond';
   Font.Size  := 30;
   Left := 7;
   Top := 4;
  end;

  fStudNo := TLabel.Create(fStudNo);
  self.InsertControl(fStudNo);
    with fStudNo do
      begin
       Caption := sStudNo;
       Font.Name := 'Garamond';
       Font.Size  := 15;
       Left := 15;
       Top := 52;
      end;

  fTimeAndDate := TLabel.Create(fTimeAndDate);
  self.InsertControl(fTimeAndDate);
    with fTimeAndDate do
      begin
       Caption := sTime + ' ' + sDate;
       Font.Name := 'Garamond';
       Font.Size  := 20;
       Left := 583;
       Top := 4;
      end;

  fComment := TMemo.Create(fComment);
  self.InsertControl(fComment);
    with fComment do
      begin
       Lines.Add(sComment);
       Font.Name := 'Garamond';
       Font.Size  := 12;
       Left := 152;
       Top := 56;
       Height := 161;
       Width := 633;
       ReadOnly := True;
       ScrollBars := ssVertical;
      end;

end;

如果您想查看其他代码(阅读文本文件,创建对象数组等),请说明。它与班级没有直接关系,因此我认为没有必要。

提前谢谢。

编辑:基于@Remy Lebeau的代码和@ NGLN的评论,我决定发布所有必要的内容。

根据@ Remy的代码修复课程后,我仍然收到错误。这让我相信错误是我使用该类的地方,特别是在我创建的对象数组中。

以前,我的代码是

  for i := 0 to ComCount-1 do
  begin
    fArrObjects[i+1] :=  TSkeleton.Create(TargetForm);
    with fArrObjects[i+1] do
    begin
      Parent := TargetForm;
      TheName := fArrComments[i][0];
      StudNo := fArrComments[i][1];
      Time := fArrComments[i][2];
      Date := fArrComments[i][3];
      Comment := fArrComments[i][4];
      ComCount := i+1;
    end;

更改

fArrObjects[i+1]

 fArrObjects[i]

解决了这个问题。

感谢@Remy纠正班级中的错误。

1 个答案:

答案 0 :(得分:4)

您的代码存在一些问题。

Parent := AOwner;

不要从构造函数内部设置Parent。调用者有责任在首先完全构造对象后设置Parent

您没有定义析构函数,而是使用nil所有者创建子对象。 TSkeleton应该是所有者,例如:

//fName := TLabel.Create(fName);
fName := TLabel.Create(Self);
...

您不应该直接致电InsertControl()。请改用Parent属性,例如:

//self.InsertControl(fName);
fName.Parent := Self;
...

为什么你有两个构造函数?您重写的构造函数不会执行任何操作,甚至不会调用基本构造函数,并且您的自定义构造函数不会在设计时调用(除非您有其他代码可编程地创建TSkeleton实例)。我建议你摆脱自定义构造函数并公开已发布的属性以根据需要操作子控件。

最后,由于您要创建子组件,因此应通过TComponent.SetSubComponen()标记它们。

话虽如此,尝试更像这样的事情:

type
  TSkeleton = class(TPanel)
  private
    fName : TLabel;
    fStudNo : TLabel;
    fTimeAndDate : TLabel;
    fComment : TMemo;

    fTime: string;
    fDate: string;
    fComCount: Integer;

    function GetTheName: string;
    procedure SetTheName(const AValue: string);
    function GetStudNo: string;
    procedure SetStudNo(const AValue: string);
    procedure SetTime(const AValue: string);
    procedure SetDate(const AValue: string);
    function GetComment: string;
    procedure SetComment(const AValue: string);
    procedure SetComCount(AValue: integer);

  public
    constructor Create (AOwner: TComponent); override;

  published
    property TheName: string read GetTheName write SetTheName;
    property StudNo: string read GetStudNo write SetStudNo;
    property Time: string read fTime write SetTime;
    property Date: string read fDate write SetDate;
    property Comment: string read GetComment write SetComment;
    property ComCount: integer read fComCount write SetComCount;
  end;

constructor TSkeleton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  Width := 800;
  Height := 250;
  Left := 16;
  BevelInner := bvSpace;
  BevelOuter := bvLowered;

  fName := TLabel.Create(Self);
  fName.SetSubComponent(True);
  fName.Parent := Self;
  fName.Font.Name := 'Garamond';
  fName.Font.Size  := 30;
  fName.Left := 7;
  fName.Top := 4;

  fStudNo := TLabel.Create(Self);
  fStudNo.SetSubComponent(True);
  fStudNo.Parent := Self;
  fStudNo.Font.Name := 'Garamond';
  fStudNo.Font.Size  := 15;
  fStudNo.Left := 15;
  fStudNo.Top := 52;

  fTimeAndDate := TLabel.Create(Self);
  fTimeAndDate.SetSubComponent(True);
  fTimeAndDate.Parent := Self;
  fTimeAndDate.Font.Name := 'Garamond';
  fTimeAndDate.Font.Size  := 20;
  fTimeAndDate.Left := 583;
  fTimeAndDate.Top := 4;

  fComment := TMemo.Create(Self);
  fComment.SetSubComponent(True);
  fComment.Parent := Self;
  fComment.Font.Name := 'Garamond';
  fComment.Font.Size  := 12;
  fComment.Left := 152;
  fComment.Top := 56;
  fComment.Height := 161;
  fComment.Width := 633;
  fComment.ReadOnly := True;
  fComment.ScrollBars := ssVertical;
end;

function TSkeleton.GetTheName: string;
begin
  Result := fName.Caption;
end;

procedure TSkeleton.SetTheName(const AValue: string);
begin
  fName.Caption := AValue;
end;

function TSkeleton.GetStudNo: string;
begin
  Result := fStudNo.Caption;
end;

procedure TSkeleton.SetStudNo(const AValue: string);
begin
  fStudNo.Caption := AValue;
end;

procedure TSkeleton.SetTime(const AValue: string);
begin
  if fTime <> AValue then
  begin
    fTime := AValue;
    fTimeAndDate.Caption := fTime + ' ' + fDate;
  end;
end;

procedure TSkeleton.SetDate(const AValue: string);
begin
  if fDate <> AValue then
  begin
    fDate := AValue;
    fTimeAndDate.Caption := fTime + ' ' + fDate;
  end;
end;

function TSkeleton.GetComment: string;
begin
  Result := fComment.Text;
end;

procedure TSkeleton.SetComment(const AValue: string);
begin
  fComment.Text := AValue;
end;

procedure TSkeleton.SetComCount(AValue: integer);
begin
  if fComCount <> AValue then
  begin
    fComCount := AValue;
    Top := 448+((FComCount-1)*250);
  end;
end;
相关问题