何时准确发布在运行时分配的属性?

时间:2017-03-17 19:26:09

标签: c++ c++builder firemonkey c++builder-10.1-berlin

我有一个自定义控件,在运行时根据已发布的属性加载时需要做一些事情。但是,我遇到了一个问题,每当我检查已发布的属性时,它还没有设置,并且始终是默认值。

我首先尝试检查控件的构造函数中的属性,但很快发现它们尚未加载。我知道当屏幕上显示控件时,属性设置正确,因此根本不会加载属性的问题。

我接下来尝试覆盖Loaded Method,但仍然遇到同样的问题,所以我认为这不是我想要的。

void __fastcall TFmSearchBar::Loaded()
{
    TEdit::Loaded(); //call base class loaded

    if( MyProperty )
    {
        //do stuff
    }
}   

这些已发布的属性在什么时候实际设置?

只要属性设置正确,我可以/应该使用哪种方法来基于这些属性在我的控件中执行某些逻辑?

1 个答案:

答案 0 :(得分:1)

  

如果我在控件的构造函数中检查属性,则该属性始终是默认值,即使我在设计器中另有指定。

正确,因为尚未分配其设计时值。

  

这些已发布的属性在什么时候实际设置?

构建所有者(表单,框架或数据模块)时。它加载自己的DFM资源并解析它,构造存储的子组件并读取它们的属性值。

例如,假设您有以下DFM:

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ...
  object Edit1: TEdit
    Left = 136
    Top = 64
    Width = 121
    Height = 21
    TabOrder = 0
  end
  object Button1: TButton
    Left = 263
    Top = 62
    Width = 75
    Height = 25
    Caption = 'Button1'
    TabOrder = 1
  end
end

DFM流媒体流程大致转换为以下等效代码(为了简单起见,我留下了很多内部细节):

__fastcall TCustomForm::TCustomForm(TComponent *Owner)
    : TScrollingWinControl(Owner)
{
    this->FFormState << fsCreating;
    try
    {
        // locate, load, and parse the "Form1" DFM resource ...

        this->FComponentState << csLoading;
        this->Parent = ...;
        this->Name = L"Form1":
        this->FComponentState << csReading;
        this->Left = 0;
        this->Top = 0;
        this->Caption = L"Form1";
        ...

        TEdit *e = new TEdit(this);
        try
        {
            e->FComponentState << csLoading;
            e->Parent = this;
            e->Name = L"Edit1"; // <-- sets the derived Form's 'Edit1' member to this object
            e->FComponentState << csReading;
            e->Left = 136;
            e->Top = 64;
            e->Width = 121;
            e->Height = 21;
            e->TabOrder = 0;
            e->FComponentState >> csReading;
        }
        catch (...)
        {
            delete e;
            throw;
        }

        TButton *b = new TButton(this);
        try
        {
            b->FComponentState << csLoading;
            b->Parent = this;
            b->Name = L"Button1"; // <-- sets the derived Form's 'Button1' member to this object
            b->FComponentState << csReading;
            b->Left = 263;
            b->Top = 62;
            b->Width = 75;
            b->Height = 25;
            b->Caption = L"Button1";
            b->TabOrder = 1;
            b->FComponentState >> csReading;
        }
        catch (...)
        {
            delete b;
            throw;
        }

        this->FComponentState >> csReading;

        ...

        e->Loaded();
        b->Loaded();
        this->Loaded();
    }
    __finally
    {
        this->FFormState >> fsCreating;
    }
}

因此,正如您所看到的,当调用其构造函数时,组件的属性值仍然不可用。

  

只要属性设置正确,我可以/应该使用哪种方法来基于这些属性在我的控件中执行某些逻辑?

这取决于属性需要做什么。如果他们需要立即执行操作,您可以直接在他们的属性设置器中执行操作。但是如果他们需要等到第一次加载其他属性(如果一个属性依赖于另一个属性的值),则改为覆盖虚拟Loaded()方法,这在DFM流式传输完成后自动调用。属性设置器可以检查ComponentState属性的标志,以了解组件当前是否在设计时在表单设计器中运行,无论DFM当前是否正在流式传输等,然后根据需要采取相应措施

  

我试图覆盖已加载的方法,但仍然遇到同样的问题

究竟是什么?你没有解释你的实际问题是什么。请edit your question提供这些详细信息。

  

所以我不认为这正是我想要的。

最有可能的是,你可能只是没有正确使用它。