Delphi 自定义属性流读取错误

Delphi 自定义属性流读取错误,delphi,properties,delphi-2010,custom-component,dfm,Delphi,Properties,Delphi 2010,Custom Component,Dfm,我是德尔福2010的法国用户,请原谅我英语不好 我已经从TCustomControl创建了一个控件。此控件具有由TCollectionItem子代填充的TOwnedCollection。 这些项具有已发布的自定义列表属性。这个列表是我制作的一对整数的列表。 我已经为此属性编写了一个自定义设计时编辑器,它工作得非常好。 现在,我想将列表数据写入dfm,这变得有点困难 以下是我所做的: TPedroGraphLineCollectionIem = class(TCollectionItem) p

我是德尔福2010的法国用户,请原谅我英语不好

我已经从TCustomControl创建了一个控件。此控件具有由TCollectionItem子代填充的TOwnedCollection。 这些项具有已发布的自定义列表属性。这个列表是我制作的一对整数的列表。 我已经为此属性编写了一个自定义设计时编辑器,它工作得非常好。 现在,我想将列表数据写入dfm,这变得有点困难

以下是我所做的:

TPedroGraphLineCollectionIem = class(TCollectionItem)
  published
    property PointList: TPedroIntegerCoupleList read FList write SetList
      stored GetStored;

...
procedure TPedroGraphLineCollectionIem.DefineProperties(Filer: TFiler);
begin
  inherited;
  //'PointList' : the property name
  //FList.Count > 0 : Is the list empty ?
  Filer.DefineProperty('PointList', ReadListData, WriteListData,
    (FList.Count > 0));
end;
...
procedure TPedroGraphLineCollectionIem.ReadListData(Reader: TReader);
var
  Val1, Val2: Integer;
begin
  with Reader do
  begin
    ReadListBegin;
    while not EndOfList do
    begin
      Val1 := ReadInteger;
      Val2 := ReadInteger;
      FList.AddCouple(Val1, Val2);
    end;
    ReadListEnd;
  end;
end;
...
procedure TPedroGraphLineCollectionIem.WriteListData(Writer: TWriter);
var
  I: Integer;
begin
  with Writer do
  begin
    WriteListBegin;
    for I := 0 to Count - 1 do
    begin
      WriteInteger(FList[I].Value1);
      WriteInteger(FList[I].Value2);
    end;
    WriteListEnd;
  end;
end;
WriteListData过程工作正常,并将值写入dfm。但是当我尝试加载表单时,它总是崩溃,并且一个对话框告诉我该属性上存在读取流错误

FList是在类的构造函数中创建的

以下是.dfm:

object MainFrm: TMainFrm
  Left = 0
  Top = 0
  Caption = 'MainFrm'
  ClientHeight = 425
  ClientWidth = 689
  Color = clBtnFace
  ParentFont = True
  OldCreateOrder = False
  Position = poScreenCenter
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object PedroGraph1: TPedroGraph
    Left = 120
    Top = 136
    Width = 313
    Height = 209
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
    Lines = <
      item
        LinePen.Color = clRed
        PointList = (
          1
          2
          3
          4)
      end>
    MarksFont.Charset = DEFAULT_CHARSET
    MarksFont.Color = clWindowText
    MarksFont.Height = -11
    MarksFont.Name = 'Tahoma'
    MarksFont.Style = []
  end
end
二,

这是一个关于摄影作品收藏项目的讲座。□□: 固有的□□ 不存在。忽视者和接班人?Remarque:ceci peut provoquer对公司的固有价值进行压制

注:"□' char实际上是这样显示的

三,

这是一个关于摄影作品收藏项目的讲座。□□

四,

这句话的意思是:不正确。忽视者和接班人?Remarque:ceci peut provoquer对公司的固有价值进行压制

五,

费切的悲剧:通量讲座的悲剧

TPedroIntegerCoupleList声明:

TPedroIntegerCouple = record
  Value1: Integer;
  Value2: Integer;
end;

TPedroGenericList<T> = class(TList<T>)
private
  FOnChange: TNotifyEvent;
  FUpdating: Boolean;
protected
  procedure Notify(const Item: T; Action: TCollectionNotification); override;
  procedure DoChange;
published
public
  constructor Create;
  procedure SortCustom; virtual; abstract;
  procedure Assign(const Source: TPedroGenericList<T>);
  property OnChange: TNotifyEvent read FOnChange write FOnChange;
end;

TPedroIntegerCoupleList = class(TPedroGenericList<TPedroIntegerCouple>)
private
  function GetString: String;
  procedure SetString(const Value: String);
public
  procedure SortCustom; override;
  function AddCouple(const Value1, Value2: Integer): Integer;
  procedure InsertCouple(const Index, Value1, Value2: Integer);
  property AsString: String read GetString write SetString;
end;
tpedroointegercouple=记录
值1:整数;
值2:整数;
结束;
TPedroGenericList=类(TList)
私有的
FOnChange:TNotifyEvent;
FUpdating:布尔;
受保护的
程序通知(const项:T;Action:T收集通知);推翻
程序改变;
出版
公众的
构造函数创建;
程序分类;事实上的摘要
程序分配(常数源:TPedroGenericList);
属性OnChange:TNotifyEvent read FOnChange write FOnChange;
结束;
TPedroIntegerCoupleList=类(TPedroGenericList)
私有的
函数GetString:String;
过程设置字符串(常量值:字符串);
公众的
程序分类;推翻
函数AddCouple(const Value1,Value2:Integer):整数;
过程插入耦合(常量索引,值1,值2:整数);
属性AsString:String read GetString write SetString;
结束;

我错在哪里?

我想你没有抓住
DefineProperty
published
它们是相互排斥的

  • 发布
    意味着VCL将以自己的方式存储不动产
  • DefineProperty
    意味着不存在这样的不动产,但如果存在虚拟不动产,你会假装存在
你的DFM是什么?可能是“点列表”在那里存储了两次-作为列表和组件

如果是,则应仅选择一种保存方法,例如,将属性公开而不是发布

或者你可以试着用不冲突的名字,比如

property PointList: TPedroIntegerCoupleList read FList write SetList stored FALSE;

Filer.DefineProperty('PointList_Virtual_DATA', ....

转到项目选项,设置“使用调试DCU”复选框,然后在
TPedroGraphLineCollectionIem.ReadListData
TPedroGraphLineCollectionIem.DefineProperties
中放置断点,并与调试其他所有内容一样调试DFM加载过程。然后返回并说出哪一行导致了错误。包括复制异常的逐字文本(它可以作为文本从异常对话框复制粘贴),我已经尝试过了,没有任何改变。当我谈论加载表单时,我的意思是在EDI中不使用断点。您可以从一个IDE运行另一个IDE来调试组件-阅读有关使用“主机应用程序”(这将是IDE的另一个副本)调试DLL和BPL(您的组件是BPL)的内容//此外,异常文本的逐字复制无论如何都是问题的一部分,DFM源代码也是如此-只需将它们作为您的组件,而无需更多//此外,您不需要在IDE中打开表单来编译、运行和调试程序。只需在不打开表单的情况下调试它。@Pedrault,那么出了什么问题,以及您是如何修复的?是的!它起作用了!我已将已发布的存储属性修改为false,并定义了一个InternalPointList属性,它可以正常工作!尽管如此,我还是考虑了您所说的:已发布的属性是自动编写的。但是使用WriteListData将数据正确写入dfm。。。好吧,它起作用了!非常感谢@佩德劳特:你是否亲自阅读了DFM的资料来源?你没有在这里复制DFM,所以我不能为你做。我只能重复一次:你们的DFM是什么?可能是“PointList”在那里存储了两次-作为列表和组件?这是.dfm:InternalPointList=(1 2 3 4)和否,PointList属性从未存储过两次;)这是新dfm的一部分,我说的是整个旧dfm,在那里你可能会看到错误,而它还没有修复(嗯,你也没有报告错误文本)。我很幸运地猜到了您的问题,但下次请提供详细的信息进行调试。和
property PointList: TPedroIntegerCoupleList read FList write SetList stored FALSE;

Filer.DefineProperty('PointList_Virtual_DATA', ....