继承TWinControl实现了2个控件组合,但是拖拉控件到界面上时就提示错误了。请教下高手。
错误提示如下:
Access violation at address 0081F52D in module 'vcl70.bpl'. Read of address 0000004C.代码如下type  THSSearchX = class(TWinControl) 
  private
    procedure WMSize(var Message: TWMSize); message WM_SIZE;
    procedure AutoSize;
  protected
    FText :String;
    FCombo: TComboBox;
    FEdit : TEdit;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy;override;
  end;procedure Register;implementation
procedure Register;
begin
  RegisterComponents('Test', [THSSearchX]);
end;
procedure THSSearchX.AutoSize;
begin
   FComBo.Width := (Width-2) div 2;
    FEdit.Left := Fcombo.Left+Fcombo.Width;
  FEdit.Width := Width-FCombo.Width-Fcombo.Left;
end;constructor THSSearchX.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  parent := TWincontrol(AOwner);
  Height := 40;
  Width :=209;  FCombo:= TComboBox.Create(self);
  FCombo.Parent :=self;  FComBo.Visible := true;
  FComBo.Top := 2;
  FComBo.Left :=2;  FEdit := TEdit.Create(self);
  Fedit.Parent := self;
  FEdit.Top := FcomBo.Top;
  FEdit.Left := Fcombo.Left+Fcombo.Width;
  FEdit.Width := Width-FCombo.Width-Fcombo.Left;
end;procedure THSSearchX.CreateWnd;
begin
  inherited;
end;destructor THSSearchX.Destroy;
begin
  FCombo.Free;
  FEdit.Free;
  inherited;
end;
procedure THSSearchX.WMSize(var Message: TWMSize);
begin
  inherited;
  AutoSize;
end;

解决方案 »

  1.   

    这样修改
    procedure THSSearchX.AutoSize;
    begin
      if not Assigned(FComBo) or not Assigned(FEdit) then Exit;
      FComBo.Width := (Width-2) div 2;
        FEdit.Left := Fcombo.Left+Fcombo.Width;
      FEdit.Width := Width-FCombo.Width-Fcombo.Left;
    end;原因是:
    constructor THSSearchX.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Parent := TWincontrol(AOwner);
      Height := 40;
      Width := 209; 
    //...
    end;
    构造中,对容器(Parent)的赋值和对高宽的赋值都会触发WM_SIZE消息
    明显在构造中触发了WM_SIZE时,FComBo和FEdit对象还没有赋值。
      

  2.   

    另外修改一下排列的顺序也可:
    type
      THSSearchX = class(TWinControl)
      private
        procedure AutoSize;
      protected
        FText: string;
        FCombo: TComboBox;
        FEdit: TEdit;
        procedure Resize; override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      end;
    procedure THSSearchX.AutoSize;
    begin
      FComBo.Width := (Width - 2) div 2;
        FEdit.Left := FCombo.Left + FCombo.Width;
      FEdit.Width := Width - FCombo.Width - FCombo.Left;
    end;constructor THSSearchX.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      Height := 40;
      Width := 209;  FCombo := TComboBox.Create(Self);
      FCombo.Parent := Self;  FComBo.Visible := True;
      FComBo.Top := 2;
      FComBo.Left := 2;  FEdit := TEdit.Create(Self);
      Fedit.Parent := Self;
      FEdit.Top := FcomBo.Top;
      FEdit.Left := FCombo.Left + FCombo.Width;
      FEdit.Width := Width - FCombo.Width - FCombo.Left;
      if AOwner is TWinControl then Parent := TWinControl(AOwner);
    end;destructor THSSearchX.Destroy;
    begin
      FCombo.Free;
      FEdit.Free;
      inherited;
    end;procedure THSSearchX.Resize;
    begin
      inherited;
      AutoSize;
    end;
    建议:
    1、大小写区分;
    2、加入适当空格;
    3、输入参数的判断(如:if AOwner is TWinControl);
    4、尽量用重载方法而不直接用消息(如:Resize)。
      

  3.   

    伴水老大,你提供的两种方法我都测试了下。问题还是存在。
    还是提示错误。
    Delphi7+WindowsXp
      

  4.   

    对不起,伴水你的方法正确。我测试又点了旧的控件了。
    多谢了。另我在CSDN里看到你回别人的帖子说 可以在CreatWnd中对包含的控件进行Parent赋值。这之间的逻辑关系可以简单讲讲么,谢谢。
      

  5.   

    CreateWnd()方法,顾名思义是创建窗体句柄(使Handle属性有效)。Create()是构造对象实例。
    Create()先于CreateWnd()执行,在Create()中Handle不一定被赋值。测试如下代码:
    uses ComCtrls;procedure TForm1.Button1Click(Sender: TObject);
    var
      vToolBar: TToolBar;
      vToolButton: TToolButton;
    begin
      vToolBar := TToolBar.Create(Self);
      vToolButton := TToolButton.Create(Self);
      vToolButton.Parent := vToolBar; // 异常:“没有父窗体(Parent Window)”
    end;
    在对ToolButton对象Parent属性赋值会抛出异常。
    即:有一些控件必须依赖以父窗体。(父窗体的Handle必须确定)这个帖子里:
    http://topic.csdn.net/t/20060909/15/5010408.html具体查阅VCL内核代码,分析调用堆栈。