Delphi组件:如何使用父字体?

时间:2011-02-14 20:53:59

标签: delphi fonts components delphi-5

我有一个使用ParentFont的自定义组件。

在构建组件的过程中,我可以看到组件的字体最初设置为默认的MS Sans Serif

constructor TCustomWidget.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);

   ...
end;

检查节目Self.Font.Name: 'MS Sans Serif'

一段时间后,我的组件的字体会更新以反映父母的字体:

TReader.ReadComponent(nil)
   SetCompName
      TControl.SetParentComponent
         TControl.SetParent
            TWinControl.InsertControl
               AControl.Perform(CM_PARENTFONTCHANGED, 0, 0);

之后一切都很棒,我的组件字体已更改为父级字体(例如“MS Shell Dlg 2”)。

问题是我的孩子控件与父母的字体(即我的组件)没有保持同步。

在我的组件构造函数中,我创建了子控件:

constructor TCustomWidget.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);

   ...
   CreateComponents;
end;

procedure TCustomWidget.CreateComponents;
begin
   ...
   FpnlBottom := TPanel.Create(Self);
   FpnlBottom.Caption := '';
   FpnlBottom.Parent := Self;
   FpnlBottom.Align := alBottom;
   FpnlBottom.Height := 46;
   FpnlBottom.ParentFont := True;
   ...
end;

最初我的FpnlBottom也有默认字体MS Sans Serif

稍后,当我的组件的字体已更新为父级的字体(例如MS Shell Dlg 2)时,子控件没有更新其字体,并且仍在保留{{1 }}

  • 为什么我的孩子控制MS Sans Serif财产不被尊重?
  • 如何让我的孩子控制ParentFont属性工作?

示例代码

工具两小时将其修剪为易于管理,可重现的代码:

ParentFont

2 个答案:

答案 0 :(得分:5)

看到示例代码后,您使用的FontChange事件处理程序都是错误的。你根本不应该使用它。您绕过了触发TControl.FontChanged()CM_FONTCHANGED通知的原生CM_PARENTFONTCHANGED事件处理程序,因此您实际上违反了ParentFont逻辑。完全摆脱你的TWidget.FontChanged()事件处理程序。如果您需要对已更改为组件的Font属性做出反应,则需要截取CM_FONTCHANGED消息,例如:

unit WinControl1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls;

type
  TWidget = class(TWinControl)
  private
    FTitleLabel: TLabel;
    FpnlBottom: TPanel;
    procedure CreateComponents;
    procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
  public
    constructor Create(AOwner: TComponent); override;
  published
    {Inherited from TWinControl}
    property Align;
    property Font;
    property ParentFont;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples',[TWidget]);
end;

{ TCustomWidget }

constructor TWidget.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csAcceptsControls, csNoDesignVisible];
  Self.Width := 384;
  Self.Height := 240;
  CreateComponents;
end;

procedure TWidget.CreateComponents;
begin
  FpnlBottom := TPanel.Create(Self);
  FpnlBottom.Parent := Self;
  FpnlBottom.Align := alBottom;
  FpnlBottom.Color := clWindow;
  FpnlBottom.Caption := 'FpnlBottom';
  FpnlBottom.Height := 45;

  FTitleLabel := TLabel.Create(Self);
  FTitleLabel.Parent := FpnlBottom;
  FTitleLabel.Left := 11;
  FTitleLabel.Top := 11;
  FTitleLabel.Caption := 'Hello, world!';
  FTitleLabel.AutoSize := True;
  FTitleLabel.Font.Color := $00993300;
  FTitleLabel.Font.Size := Self.Font.Size+3;
  FTitleLabel.ParentFont := False;
end;

procedure TWidget.CMFontChanged(var Message: TMessage);
begin
  inherited; // let TControl and TWinControl react first
  //title label is always 3 points larger than the rest of the content
  FTitleLabel.Font.Name := Self.Font.Name;
  FTitleLabel.Font.Size := Self.Font.Size + 3;
  OutputDebugString(PChar('New font ' + Self.Font.Name));
end;

end. 

答案 1 :(得分:4)

每次更新组件的Font属性时,组件会自动向其每个子控件发送CM_PARENTFONTCHANGED个消息,此时每个控件都会检查其ParentFont属性是否为True或不。您是否检查过以确保您的子控件的ParentFont属性仍设置为True?也许在他们自己的DFM流媒体中,子控件正在设置他们的Font属性,这些属性会将ParentFont重置为False。