首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用DefineProperties替换TPersistent属性,例如TFont

使用DefineProperties替换TPersistent属性,例如TFont
EN

Stack Overflow用户
提问于 2012-07-02 08:46:33
回答 1查看 1.9K关注 0票数 5

我正在更新组件中的一些属性。为了避免丢失属性错误,我使用DefineProperties从流中读取旧属性。大多数属性运行良好,例如Integer,但我无法使基于TPersistent的属性工作。ReadProperty(TPersistent)过程在TReader中是受保护的,而不是公共的,需要黑客才能访问它。即使这样,ReadFontProperty过程也不会被调用,并且会发生丢失的属性异常。

如何读取TFont属性?

下面是一些示例代码,说明我是如何尝试这样做的。

代码语言:javascript
复制
...

type
  TMyComponent = class(TComponent)
  strict private
    // Removed 
    //FIntegerProperty: Integer;
    //FFontProperty: TFont;

    // New
    FNewIntegerProperty: Integer;
    FNewFontProperty: TFont;

    procedure ReadIntegerProperty(Reader: TReader);
    procedure ReadFontProperty(Reader: TReader);
  protected
    procedure DefineProperties(Filer: TFiler); override;
  published
    // Removed properties
    //property IntegerProperty: Integer read FIntegerProperty write FIntegerProperty;
    //property FontProperty: TFont read FFontProperty write SetFontProperty;

    // New properties
    property NewIntegerProperty: Integer read FNewIntegerProperty write FNewIntegerProperty;
    property NewFontProperty: TFont read FNewFontProperty write SetNewFontProperty;
  end;

implementation

procedure TMyComponent.DefineProperties(Filer: TFiler);
begin
  inherited;

  // This works
  Filer.DefineProperty('IntegerProperty', ReadIntegerProperty, nil, FALSE);

  // This doesn't
  Filer.DefineProperty('FontProperty', ReadFontProperty, nil, FALSE);
end;

procedure TMyComponent.ReadIntegerProperty(Reader: TReader);
begin
  FNewIntegerProperty:= Reader.ReadInteger;
end;

type
  THackReader = class(TReader);

procedure TMyComponent.ReadFontProperty(Reader: TReader);
begin
  { TODO : This doesn't work. How do we read fonts? }
  THackReader(Reader).ReadProperty(FNewFontProperty);
end;

...

更新1

使用以下代码尝试David的建议:

代码语言:javascript
复制
Filer.DefineProperty('Font.CharSet', ReadFontCharSet, nil, False);

..。

代码语言:javascript
复制
procedure TMyComponent.ReadFontCharSet(Reader: TReader);
begin
  Reader.ReadInteger;
end;

我得到一个无效属性值错误。我想这与TFontCharset类型的字符集有关(= System.UITypes.TFontCharset = 0..255)。我如何阅读这种类型的财产?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-07-02 09:44:41

为了做到这一点,您需要使用TFont的每个已发布的属性,并且需要使用完全限定的名称。

代码语言:javascript
复制
Filer.DefineProperty('FontProperty.Name', ReadFontName, nil, False);
Filer.DefineProperty('FontProperty.Height', ReadFontHeight, nil, False);
Filer.DefineProperty('FontProperty.Size', ReadFontSize, nil, False);
// and so on for all the other published properties of TFont

ReadFontNameReadFontHeight等应该将旧属性值读入新命名的组件中。

代码语言:javascript
复制
procedure TMyComponent.ReadFontName(Reader: TReader);
begin
  FNewFontProperty.Name := Reader.ReadString;
end;

// etc. etc.

更新

您将询问如何读取字符集属性。这很复杂,因为可以将其写入文本标识符(请参阅FontCharsets常量Graphics.pas),也可以编写为普通整数值。以下是一些快速破解的代码,将读取您的字符集。

代码语言:javascript
复制
procedure TMyComponent.ReadFontCharset(Reader: TReader);

  function ReadIdent: string;
  var
    L: Byte;
    LResult: AnsiString;
  begin
    Reader.Read(L, SizeOf(Byte));
    SetString(LResult, PAnsiChar(nil), L);
    Reader.Read(LResult[1], L);
    Result := UTF8ToString(LResult);
  end;

  function ReadInt8: Shortint;
  begin
    Reader.Read(Result, SizeOf(Result));
  end;

  function ReadInt16: Smallint;
  begin
    Reader.Read(Result, SizeOf(Result));
  end;

var
  Ident: string;
  CharsetOrdinal: Integer;

begin
  Beep;
  case Reader.ReadValue of
  vaIdent:
    begin
      Ident := ReadIdent;
      if not IdentToCharset(Ident, CharsetOrdinal) then begin
        raise EReadError.Create('Could not read MyFont.Charset');
      end;
      FNewFontProperty.Charset := CharsetOrdinal;
    end;
  vaInt8:
    FNewFontProperty.Charset := ReadInt8;
  vaInt16:
    FNewFontProperty.Charset := ReadInt16;
  else
    raise EReadError.Create('Could not read FontProperty.Charset');
  end;
end;
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11290413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档