简体   繁体   English

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

[英]Use DefineProperties to replace TPersistent properties e.g. TFont

I'm updating some properties in a component. 我正在更新组件中的某些属性。 In order to avoid missing property errors I'm using DefineProperties to read the old properties from the stream. 为了避免丢失属性错误,我正在使用DefineProperties从流中读取旧属性。 Most properties work fine eg Integer , but I can't get properties based on TPersistent to work. 大多数属性都可以正常工作,例如Integer ,但是我无法基于TPersistent获得属性。 The ReadProperty(TPersistent) procedure in TReader is protected, not public and requires a hack to access it. 行者读属性(TPersistent)程序的保护,不公开,需要一个黑客来访问它。 Even then, the ReadFontProperty procedure is never called and the missing property exception occurs. 即使这样,也永远不会调用ReadFontProperty过程,并且会发生缺少的属性异常。

How do I read the TFont property? 如何阅读TFont属性?

Here's some sample code of how I'm trying to do it. 这是一些有关我如何尝试的示例代码。

...

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;

...

Update 1 更新1

Tried David's suggestion using the following code: 使用以下代码尝试了David的建议:

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

... ...

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

I get an Invalid Property Value error. 我收到无效的属性值错误。 I guess it's something to do with Charset being of type TFontCharset (= System.UITypes.TFontCharset = 0..255). 我想这与Charset类型为TFontCharset (= System.UITypes.TFontCharset = 0..255)有关。 How do I read this type of property? 我如何阅读这种类型的财产?

In order to do this you need to work with each individual published property of TFont and you will need to use fully qualified names. 为此,您需要使用TFont每个单独发布的属性,并且需要使用完全限定的名称。

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

ReadFontName , ReadFontHeight etc. should read the old property values into the newly named component. ReadFontNameReadFontHeight等应将旧的属性值读入新命名的组件中。

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

// etc. etc.

Update 更新资料

You ask how to read the Charset property. 您询问如何读取Charset属性。 This is complex because it can be written either as a textual identifier (see the FontCharsets constant in Graphics.pas), or as a plain integer value. 这很复杂,因为它既可以写为文本标识符(请参见Graphics.pas中的FontCharsets常量),也可以写为纯整数值。 Here is some rapidly hacked together code that will read your Charset. 这是一些快速被黑客入侵的代码,它们将读取您的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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在TForm的边界之外显示控件(例如TListbox) - How to display a control (e.g. TListbox) beyond the borders of a TForm 计算开工率? 例如每秒检查X - Calculating a operational rate? E.g. Checking X per second 如何调用网络服务方法进行测试,例如从浏览器 - How to call a webservice method for testing, e.g. from a browser 编译器定义(例如$ CPUX86)在哪里定义? 哪个文件夹/文件? - Where do compiler defines (e.g. $CPUX86) get defined? Which folder/file? 是否可以避免单击按钮(例如,粗体)时TRichEdit失去焦点? - Is it possible to avoid a TRichEdit losing its focus when clicking a button (e.g. Bold)? WebView2 (TEdgeBrowser) 更新了 Delphi 接口(例如 ICoreWebView2Controller2) - WebView2 (TEdgeBrowser) updated Delphi interface (e.g. ICoreWebView2Controller2) RTTI访问VCL的私有方法,例如TCustomForm.SetWindowState - RTTI access to private methods of VCL, e.g. TCustomForm.SetWindowState 如何将只有十个字符的字符串(例如“ 12345 * 45688”)拆分为数组 - How to split a string of only ten characters e.g.“12345*45688” into an array 如何使用SuperObject序列化包含点(例如IP地址)的JSON密钥? - How to serialize JSON key containing dots (like e.g. IP address) with SuperObject? 如何在每个项目文件夹中保存dcu文件(例如:。\ $(平台)\ $(配置)\ $(ProjectFilename)? - How to keep dcu files in per project folder (e.g.: .\$(Platform)\$(Config)\$(ProjectFilename)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM