unit uTest;interfaceuses    SysUtils, Classes, Controls, StdCtrls;    type
       TMyEdit = class(TEdit)
          private
            FLinkLabel: TLabel;
            FStart:Boolean;
            FOpen:Boolean;
            procedure FSetLinkLabel(AValue: TLabel);
            procedure SetStart(Value:Boolean);
            procedure SetOpen(Value:Boolean);
          protected
            procedure Change;override;
          public
          published
            property LinkLabel: TLabel read FLinkLabel write FSetLinkLabel;
            property Start:Boolean read FStart write SetStart;
            property Open:Boolean read FOpen write SetOpen;
    end;
procedure Register;implementationprocedure Register;
begin
    RegisterComponents('Linco', [TMyEdit]);
end;procedure TMyEdit.Change;
begin
  inherited;
    if LinkLabel <> nil then
    LinkLabel.Caption := Text;
end;procedure TMyEdit.FSetLinkLabel(AValue: TLabel);
begin
  FLinkLabel := AValue;
end;
procedure TMyEdit.SetOpen(Value: Boolean);
begin
   if Value<>FOpen then
      FOpen:=Value;
end;procedure TMyEdit.SetStart(Value: Boolean);
begin
   if Value<>FStart then
      FStart:=Value;
end;end.
安装好后,往一个FORM上放一个TMyEdit来做测试。
在设计时的时候,静态邦定一个TLable设Open,Start都设为TRUE。
之后在这三个
SetStartSetOpenFSetLinkLabel方法中设断点。运行。大家注意到没有。为什么是先触发SetStart这个方法。有没有办法按我所想的顺序来触发。

解决方案 »

  1.   

      FStart:Boolean;
      FOpen:Boolean;
    上面两个变量的上下顺序换一下试试。  if Value<>FOpen then
      FOpen:=Value;
    上两句代码无意义,直接FOpen:=Value;即可。
      

  2.   

    把form文件(*.dfm)以文本方式打开,找到 FStart和FOpen的设置语句,把它们的前后位置换一下。
      

  3.   

    问题已解决一半了。跟这个dfm确实有点关系。
    目前顺下的问题是FSetLinkLabel 这个方法无论是在dfm中为第一位置,还是最后一位置,都是最后引发的。
    为什么Boolean的比对象连接的要快呢?
      

  4.   

    VCL 初初始化的代码
    begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.Application.CreateForm(TForm1, Form1); 的详细过程Application.CreateForm(TForm1, Form1); 
    |-Form1.NewInstance; 
    |-Form1.Create(Application); 
      |-Form1.CreateNew(Application); 
      |-InitInheritedComponent(Form1, TForm); 
        |-InternalReadComponentRes(Form1.ClassName, Form1ResHInst, Form1); 
          |-TResourceStream.Create(Form1ResHInst, Form1.ClassName, RT_RCDATA); 
          |-TResourceStream.ReadComponent(Form1); 
            |-TReader.Create(ResourceStream, 4096); 
            |-TReader.ReadRootComponent(Form1); 
              |-TReader.ReadSignature; 
             *|-TReader.ReadPrefix(Flags, ChildPos); 
              |-IF Form1 = nil THEN Form1 := FindClass(ReadStr).Create; 
              |-Include(Form1.FComponentState, csLoading); 
              |-Include(Form1.FComponentState, csReading); 
              |-Form1.Name := FindUniqueName(ReadStr); 
             ?|-FFinder := TClassFinder.Create; 
             *|-Form1.ReadState(Reader); 
                |-TCustomForm.ReadState(Reader); 
                  { DisableAlign; } 
                |-TWinControl.ReadState(Reader); 
                  { DisableAlign; } 
               *|-TControl.ReadState(Reader); 
                  { Include(FControlState, csReadingState); } 
                  { Parent := TWinControl(Reader.Parent);   } 
               *|-TComponent.ReadState(Reader); 
                  |-Reader.ReadData(Form1); 
                    |-Reader.ReadDataInner(Form1); 
                      |-WHILE NOT EndOfList DO Reader.ReadProperty(Form1); 
                        |-IF PropInfo &lt;&gt; nil THEN ReadPropValue(Form1, PropInfo); 
                       *|-ELSE Form1.DefineProperties(Reader); 
                      |-WHILE NOT EndOfList DO ReadComponent(nil); 
                        |-ReadPrefix(Flags, Position); 
                        |-IF ffInherited THEN FindExistingComponent 
                        |-ELSE CreateComponent; 
                       *|-SubComponent.ReadState(Reader); (Like Form1.ReadState) 
                   ?|-DoFixupReferences; 其中有      |-WHILE NOT EndOfList DO Reader.ReadProperty(Form1); 
    ReadData 调用 ReadDataInner 读取 root 元件及 root 的子元件的属性信息
    这时候会触发你的断点条件查看属性信息列表的顺序的简单代码, 就是窗口加载时的顺序var
      I, O: TMemoryStream;
    begin
      I := TMemoryStream.Create;
      o := TMemoryStream.Create;  I.WriteComponent(MyEdit1);
      I.Seek(0, soFromBeginning);
      ObjectBinaryToText(i, o);
      o.Seek(0, soFromBeginning);
      Memo1.Lines.LoadFromStream(o);
    你要看vcl是如何保存的, 看 I.WriteComponent(MyEdit1);的vcl源代码procedure TWriter.WriteComponent(Component: TComponent);  function FindAncestor(const Name: string): TComponent;
      var
        I: Integer;
      begin
        for I := 0 to FAncestorList.Count - 1 do
        begin
          Result := FAncestorList[I];
          if SameText(Result.Name, Name) then Exit;
        end;
        Result := nil;
      end;var
      OldAncestor: TPersistent;
      OldRootAncestor: TComponent;
      AncestorComponent: TComponent;
      I: Integer;
    begin
      OldAncestor := Ancestor;
      OldRootAncestor := RootAncestor;
      try
        Include(Component.FComponentState, csWriting);
        for I := 0 to Component.ComponentCount - 1 do
          if csSubComponent in Component.Components[I].ComponentStyle then
            Include(Component.Components[I].FComponentState, csWriting);
        if Assigned(FAncestorList) then
          Ancestor := FindAncestor(Component.Name);
        if Assigned(FOnFindAncestor) and ((Ancestor = nil) or
        (Ancestor is TComponent)) then
        begin
          AncestorComponent := TComponent(Ancestor);
          FOnFindAncestor(Self, Component, Component.Name, AncestorComponent,
            FRootAncestor);
          Ancestor := AncestorComponent;
        end;
        Component.WriteState(Self);
        Exclude(Component.FComponentState, csWriting);
        for I := 0 to Component.ComponentCount - 1 do
          if csSubComponent in Component.Components[I].ComponentStyle then
            Exclude(Component.Components[I].FComponentState, csWriting);
      finally
        Ancestor := OldAncestor;
        FRootAncestor := OldRootAncestor;
      end;
    end;
    希望对楼主有帮助
      

  5.   

      object MyEdit1: TMyEdit
        Left = 8
        Top = 96
        Width = 121
        Height = 21
        TabOrder = 0
        Text = 'MyEdit1'
        LinkLabel = Label1
        Open = True
        Start = True
      end窗体中的顺序是这样。我想怎么的也是先触发FSetLinkLabel的,但就是没有触发。
      

  6.   

    看一下 Delphi 原生 TLabeledEditCreate 中 SetupInternalLabel 就是创建子控件
    Notification 就是 子控件怎么跟 Edit 挂钩消息。
    其他的SetName,SetBounds 稍微留意一下。看一下总共没几行代码。
      

  7.   

    特别的,请注意 TComponent 有 Designing 的 ComponentStatus。
    特殊情况下,需要考虑一下的。
      

  8.   

    狄奥跑题了.
    MyEdit1 持久化自身的属性是由 TMyEdit 调用TReader.ReadProperty 时, 只读了自身定义的属性
      LinkLabel = Label1 不是它读出来的
      

  9.   

    上边说了
    刚刚自己测试了下
    procedure TReader.ReadProperty(AInstance: TPersistent);
    这函数执行在程序启动的时候加载 publish属性的顺序和  object MyEdit1: TMyEdit
      Left = 8
      Top = 96
      Width = 121
      Height = 21
      TabOrder = 0
      Text = 'MyEdit1'
      LinkLabel = Label1
      Open = True
      Start = True
      end
    的顺序是一致的
    只是 读到  LinkLabel = Label1, 并不会立即执行
    其他几个自己定义的属性都是读完后执行