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这个方法。有没有办法按我所想的顺序来触发。
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这个方法。有没有办法按我所想的顺序来触发。
解决方案 »
- IdUDPClient接收字符串的问题
- 用Delphi+GLScene轻松打造3D场景、动画之GLScene基础
- 一个简单回调函数问题?怎么编译时提示"Variable required"?请大家帮忙解决!
- 请问哪有Delphi各控件的使用说明
- 怎样实现信息的自动跳出的效果?
- 同一个表(sqlserver),用Table1.fieldbyaname('a').Assting:=datetostr(dtpicker1.date)和update得到了不同的日期?
- 求《Delphi7从入门到精通》这么书,不要电子版的! 二手就可以!
- Delphi前景如何???
- 请问用什么工具开发ERP,哪里有示例或资料?
- 如何动态打开一个窗口?
- 打开一个Excel并显示在指定显示器上
- Delphi中DBGrid改数据的问题?
FOpen:Boolean;
上面两个变量的上下顺序换一下试试。 if Value<>FOpen then
FOpen:=Value;
上两句代码无意义,直接FOpen:=Value;即可。
目前顺下的问题是FSetLinkLabel 这个方法无论是在dfm中为第一位置,还是最后一位置,都是最后引发的。
为什么Boolean的比对象连接的要快呢?
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 <> 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;
希望对楼主有帮助
Left = 8
Top = 96
Width = 121
Height = 21
TabOrder = 0
Text = 'MyEdit1'
LinkLabel = Label1
Open = True
Start = True
end窗体中的顺序是这样。我想怎么的也是先触发FSetLinkLabel的,但就是没有触发。
Notification 就是 子控件怎么跟 Edit 挂钩消息。
其他的SetName,SetBounds 稍微留意一下。看一下总共没几行代码。
特殊情况下,需要考虑一下的。
MyEdit1 持久化自身的属性是由 TMyEdit 调用TReader.ReadProperty 时, 只读了自身定义的属性
LinkLabel = Label1 不是它读出来的
刚刚自己测试了下
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, 并不会立即执行
其他几个自己定义的属性都是读完后执行