Delphi自定义图形控件的自定义字体属性在设计期报错的解决办法

背景

自定义一个图形控件(继承自TGraphicControl类),须要在不一样区域显示不一样字体的内容,此时会须要在设计器中加入多个字体,方法是在控件的published区增长对应的字体属性便可(使用Ctrl+Shift+C可快速生成),如:ide

TMyGraphicControl = class(GraphicControl)
  private
    FText1Font: TFont;
    FText2Font: TFont;
    procedure SetText1Font(const Value: TFont);
    procedure SetText2Font(const Value: TFont);
  protected
    procedure Paint; override;
  public
    { public declarations }
  published
    property Text1Font:TFont read FText1Font write SetText1Font;
    property Text2Font:TFont read FText2Font write SetText2Font;
  end;

这样就能够在设计器里像使用原生控件同样使用本身的控件了。字体

问题

可是,若是在设计期选择了弹出字体对话框进行设置字体,IDE就会报错(大意是读或写某个地址异常),而在运行期则正常!设计

缘由

对比查看Delphi自带的控件源码,终于找到了缘由。指针

//Delphi TControl类设置字体属性的方法
procedure TControl.SetFont(Value: TFont);
begin
  FFont.Assign(Value);
end;
//本身设置字体属性的方法
procedure TMyGraphicControl.SetText1Font(const Value: TFont);
begin
  FText1Font := Value;
end;

由此,真相大白!code

TFont是类,其实例使用:=赋值时,实例上是把实例的指针指向了值的来源;而使用Assign方法,则是把各字段值复制了一份存放在实例的字段中。在运行期,对字体赋值,值的来源在上下文环境中是肯定且存在的;在设计期经过设计器直接对字体各子项赋值,其实是在逐一对其字段赋值;而在设计期经过字体对话框进行赋值,实际是产生了一条Windows消息,消息传递完成以后内容就会销毁,因此使用:=赋值就会产生地址读写的异常。继承

总结

对类的实例进行赋值时,必定要想清楚最终想要的效果是什么,由此来肯定是使用:=仍是Assign方法。源码

相关文章
相关标签/搜索