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方法。源碼

相關文章
相關標籤/搜索