加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 04:13:23 所属栏目:大数据 来源:网络整理
导读:我正在更新组件中的一些属性.为了避免遗漏属性错误,我使用DefineProperties从流中读取旧属性.大多数属性很好,例如整数,但我无法获得基于TPersistent的属性来工作. TReader中的ReadProperty(TPersistent)过程受到保护,而不是公共过程,需要黑客才能访问它.即使
我正在更新组件中的一些属性.为了避免遗漏属性错误,我使用DefineProperties从流中读取旧属性.大多数属性很好,例如整数,但我无法获得基于TPersistent的属性来工作. TReader中的ReadProperty(TPersistent)过程受到保护,而不是公共过程,需要黑客才能访问它.即使这样,也永远不会调用ReadFontProperty过程,并且会发生缺失的属性异常.

我如何阅读TFont属性?

这是我试图做的一些示例代码.

...

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,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的建议:

Filer.DefineProperty('Font.CharSet',ReadFontCharSet,False);

procedure TMyComponent.ReadFontCharSet(Reader: TReader);
begin
  Reader.ReadInteger;
end;

我收到无效的属性值错误.我想这与Charset属于TFontCharset类型(= System.UITypes.TFontCharset = 0..255)有关.我如何阅读这种类型的财产?

解决方法

为此,您需要使用TFont的每个单独发布的属性,您需要使用完全限定的名称.
Filer.DefineProperty('FontProperty.Name',ReadFontName,False);
Filer.DefineProperty('FontProperty.Height',ReadFontHeight,False);
Filer.DefineProperty('FontProperty.Size',ReadFontSize,False);
// and so on for all the other published properties of TFont

ReadFontName,ReadFontHeight等应该将旧属性值读入新命名的组件中.

procedure TMyComponent.ReadFontName(Reader: TReader);
begin
  FNewFontProperty.Name := Reader.ReadString;
end;

// etc. etc.

更新

您询问如何阅读Charset属性.这很复杂,因为它可以作为文本标识符(参见Graphics.pas中的FontCharsets常量)或纯整数值编写.以下是一些快速入侵的代码,可以读取您的Charset.

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;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读