在 Delphi 组件创建中,谁控制 ComponentState 属性?

问题描述 投票:0回答:1

我正在编写 AlmediaDev 的 TscPanel 和 GlyphIcons 的一个小包装,以创建类似于 TLabeledEdit 的行为。在设计时添加组件后,我想检查 3 个条件:

  1. 如果是设计时间(通过
    csDesigning in ComponentState
  2. 如果所有者是 TForm(即它没有被添加到另一个面板或其他面板中)。
  3. 如果
    TscStyledForm
    已经在该表单上并且激活了阴影属性。

我的问题源于这样一个事实:我的 ComponentState 似乎是空的,这让我思考谁管理、添加或删除该属性的标志。由于它是从 TComponent 一直继承的,所以我不相信它是由第三方管理的。

作为一个附带问题,我是否能够从表单访问其他组件并在设计时更改它们的属性?就像我的第三个条件一样,如果它没有激活,我不能自己激活它吗?

提前致谢。


编辑 1 添加了我用来检索 ComponentState 的代码

constructor TImprovedFluentTopBar.Create(AOwner: TComponent);
begin

  ShowMessage('Creating');
  if (csDesigning in ComponentState) then     // Pesquisar sobre isso aqui
  begin
    ShowMessage('Checking');
    if not (AOwner is TForm) then
    begin
      raise Exception.Create('Owner must be a TForm.');
    end;

    var Found: Boolean := False;
    for var I:Integer := 0 to TForm(AOwner).ComponentCount - 1 do   // Cast de AOwner para TForm. Acessa a componentCount do TForm.
    begin
      if TForm(AOwner).Components[I] is TImprovedFluentTopBar then
      begin
        raise Exception.Create('TImprovedFluentTopBar is already on the form.');
      end
      else if TForm(AOwner).Components[I] is TscStyledForm then
      begin
        Found := True;
      end;
    end;

    if not Found then
    begin
      raise Exception.Create('TscStyleControls not found in current TForm');
    end;
  end else begin
     ShowMessage(ComponentStateAsString(ComponentState));
  end;

  inherited Create(AOwner);
  Self.Caption := '';
  Self.DragForm := True;
  FCloseButton := TscGPGlyphButton.Create(Self);
  FCloseButton.Align := alRight;
  FCloseButton.SetBounds(20, 60, 20, 20);
  FMinimizeButton := TscGPGlyphButton.Create(Self);
  FMinimizeButton.Align := alRight;
  FMinimizeButton.SetBounds(20, 20, 20, 20);
end;

和 ComponentStateAsString:

function ComponentStateAsString(ACS: TComponentState): String;
begin
  Result := 'States: ';
  if (csAncestor in ACS) then
  begin
    Result := Result + 'csAncestor ';
  end;

  if (csDesigning in ACS) then
  begin
    Result := Result + 'csDesigning ';
  end;

  if (csDestroying in ACS) then
  begin
    Result := Result + 'csDestroying ';
  end;

  if (csFixups in ACS) then
  begin
    Result := Result + 'csFixups ';
  end;

  if (csFreeNotification in ACS) then
  begin
    Result := Result + 'csFreeNotification ';
  end;

  if (csInline in ACS) then
  begin
    Result := Result + 'csInline ';
  end;

  if (csLoading in ACS) then
  begin
    Result := Result + 'csLoading ';
  end;

  if (csReading in ACS) then
  begin
    Result := Result + 'csReading ';
  end;

  if (csWriting in ACS) then
  begin
    Result := Result + 'csWriting ';
  end;

  if (csDesignInstance in ACS) then
  begin
    Result := Result + 'csDesignInstance ';
  end;


end;
delphi
1个回答
0
投票

我的问题源于这样一个事实:我的 ComponentState 似乎是空的,这让我思考谁管理、添加或删除该属性的标志。

csDesigning
标志通过
ComponentState
方法添加到组件的
TComponent.SetDesigning()
属性或从中删除,当您的组件添加到已具有
TComponent.InsertComponent()
Owner
组件时,
csDesigning
会调用该方法。旗帜。如果
inherited
参数不是
InsertComponent()
,则组件的
AOwner
构造函数会调用
nil

constructor TComponent.Create(AOwner: TComponent);
begin
  ...
  if AOwner <> nil then AOwner.InsertComponent(Self);
end;

procedure TComponent.InsertComponent(const AComponent: TComponent);
var
  ...
begin
  ...
  if csDesigning in ComponentState then
    AComponent.SetDesigning(True);
  ...
end;

procedure TComponent.SetDesigning(Value, SetChildren: Boolean);
var
  I: Integer;
begin
  if Value then
    Include(FComponentState, csDesigning) else
    Exclude(FComponentState, csDesigning);
  if SetChildren then
    for I := 0 to ComponentCount - 1 do Components[I].SetDesigning(Value);
end;

因此,组件的构造函数应该在读取

inherited
属性之前调用 ComponentState 构造函数
BEFORE
。但是,您正在调用
inherited
AFTER 阅读
ComponentState
,这就是为什么您还没有看到分配的
csDesigning
标志:

constructor TImprovedFluentTopBar.Create(AOwner: TComponent);
begin
  inherited Create(AOwner); // <-- DO THIS FIRST!

  ShowMessage('Creating');
  ...
  //inherited Create(AOwner); // <-- NOT HERE!
  ...
end;

如果您不想早点调用

inherited
,那么您必须检查
csDesigning
属性中的
AOwner.ComponentState
标志:

constructor TImprovedFluentTopBar.Create(AOwner: TComponent);
begin

  ShowMessage('Creating');
  if (AOwner <> nil) and (csDesigning in AOwner.ComponentState) then
  begin
    ...
  end;

  inherited Create(AOwner);
  ...
end;
© www.soinside.com 2019 - 2024. All rights reserved.