Delphi 2009 - 在自定义 Delphi 组件中设置默认属性值

发布于 2024-08-03 23:53:23 字数 1198 浏览 5 评论 0原文

这应该很简单,但我找不到我想要的确切答案。我有一个基于 TSpeedButton 的自定义 delphi 控件。我希望 SpeedButton 的 Caption 属性始终为“注释”,但我不想在运行时设置它,我想在组件本身中设置它,这样当我将它放在表单上时,它已经填充了这个文本。我还想设置按钮的高度和宽度,但我想这样做的方法与设置标题相同。

为了完整起见,以下是组件代码:

unit CustomSpeedButton;

interface

uses
  SysUtils, Classes, Controls, Buttons;

type
  TCustomSpeedButton = class(TSpeedButton)
  private
    FCommentText: string;
    FCommentTitle: string;

    procedure SetCommentText(const Value: string);
    procedure SetCommentTitle(const Value: string);

    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }

  published
    { Published declarations }
    property CommentTitle: string read FCommentTitle write SetCommentTitle;
    property CommentText: string read FCommentText write SetCommentText;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TCustomSpeedButton]);
end;

{ TCustomSpeedButton }

procedure TCustomSpeedButton.SetCommentText(const Value: string);
begin
  FCommentText := Value;
end;

procedure TCustomSpeedButton.SetCommentTitle(const Value: string);
begin
  FCommentTitle := Value;
end;

end.

This should be very simple but I can't find the exact answer I want. I have a custom delphi control based on TSpeedButton. I want the Caption Property of the SpeedButton to always be 'Comments' but I don't want to set it at run-time I want to set it in the component itself so that when I place it on my form it's already populated with this text. I also want to set the height and width of the button but I imagine the method for doing this will be the same as for setting the caption.

For the sake of completeness, here is the component code:

unit CustomSpeedButton;

interface

uses
  SysUtils, Classes, Controls, Buttons;

type
  TCustomSpeedButton = class(TSpeedButton)
  private
    FCommentText: string;
    FCommentTitle: string;

    procedure SetCommentText(const Value: string);
    procedure SetCommentTitle(const Value: string);

    { Private declarations }
  protected
    { Protected declarations }
  public
    { Public declarations }

  published
    { Published declarations }
    property CommentTitle: string read FCommentTitle write SetCommentTitle;
    property CommentText: string read FCommentText write SetCommentText;
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Standard', [TCustomSpeedButton]);
end;

{ TCustomSpeedButton }

procedure TCustomSpeedButton.SetCommentText(const Value: string);
begin
  FCommentText := Value;
end;

procedure TCustomSpeedButton.SetCommentTitle(const Value: string);
begin
  FCommentTitle := Value;
end;

end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夕嗳→ 2024-08-10 23:53:23

由于您希望 Caption 属性正确完成,Mason 的答案将不起作用,因为他错过了“csSetCaption”的事情,并且他关于“default”的建议也不起作用,因为 Caption 和您的属性都是字符串类型。

以下是您想要的单位。

行为如下:

  1. 最初 Caption 属性的值将为“Comments”,
  2. 用户可以在设计时通过设置新值来覆盖该值

(如果您不想要 2.,则需要在覆盖的像 Ken 提到的加载方法;但是,从您的问题中不清楚您是否想要这样,请重新表述您的问题。)

这就是代码的工作原理。

对于字符串属性,您无法向流系统暗示任何默认
但是您可以在构造函数中设置设计时的初始值: Caption := DefaultCustomSpeedButtonCaption;

对于 Caption 属性,您还必须禁用 Caption 属性的默认分配(否则您的组件将自动获取类似“CustomSpeedButton1”的标题)。
此行为您完成此操作: ControlStyle := ControlStyle - [csSetCaption];

最后,最好将组件注册拆分为单独的单元。
这使您可以拥有一个在 IDE 中注册组件的设计时包,以及一个在应用程序中使用组件的运行时包(或根本没有包)。

如果您有组件图标,那么您也可以将其加载到注册单元中(因为仅在设计时需要它)。

Ray Konopka 写了一本关于组件编写的优秀书籍,至今仍然非常有效:开发自定义 Delphi 3组件
与许多优秀的 Delphi 书籍一样,它已经绝版,但您可以 订购 PDF 副本他的网站

我不确定您的 CommentTitle 和 CommentText 属性的用途,因此我将它们保留在下面的源代码中。

清单 1:实际组件

unit CustomSpeedButtonUnit;

interface

uses
  SysUtils, Classes, Controls, Buttons;

const
  DefaultCustomSpeedButtonCaption = 'Comments';

type
  TCustomCustomSpeedButton = class(TSpeedButton)
  strict private
    FCommentText: string;
    FCommentTitle: string;
  strict protected
    procedure SetCommentText(const Value: string); virtual;
    procedure SetCommentTitle(const Value: string); virtual;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property CommentTitle: string read FCommentTitle write SetCommentTitle;
    property CommentText: string read FCommentText write SetCommentText;
  end;

  TCustomSpeedButton = class(TCustomCustomSpeedButton)
  published
// note you cannot use 'default' for string types; 'default' is only valid for ordinal ordinal, pointer or small set type
// [DCC Error] CustomSpeedButtonUnit.pas(29): E2146 Default values must be of ordinal, pointer or small set type
//    property Caption default DefaultCustomSpeedButtonCaption;
    property CommentTitle;
    property CommentText;
  end;

implementation

constructor TCustomCustomSpeedButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Caption := DefaultCustomSpeedButtonCaption;
  ControlStyle := ControlStyle - [csSetCaption];
end;

destructor TCustomCustomSpeedButton.Destroy;
begin
  inherited Destroy;
end;

procedure TCustomCustomSpeedButton.SetCommentText(const Value: string);
begin
  FCommentText := Value;
end;

procedure TCustomCustomSpeedButton.SetCommentTitle(const Value: string);
begin
  FCommentTitle := Value;
end;

end.

清单 2:组件注册

unit CustomSpeedButtonRegistrationUnit;

interface

procedure Register;

implementation

uses
  CustomSpeedButtonUnit;

procedure Register;
begin
  RegisterComponents('Standard', [TCustomSpeedButton]);
end;

end.

Since you wanted the Caption property to be done properly, Mason's answer is not going to work because he missed the 'csSetCaption' thing, and his suggestion about 'default' will not work either because both the Caption and your properties are string types.

Below are the units as you want them.

The behaviour is as follows:

  1. intially the value of the Caption property will be 'Comments'
  2. users can override that at design time by setting a new value

(If you do not want 2., then you need to assign the Caption property in an overrided Loaded method like Ken mentioned; however, it was not clear from your question if you wanted that. If you do, then please rephrase your question.)

This is how the code works.

For string properties, you cannot hint the streaming system of any default.
But you can set an initial value for design time in the constructor: Caption := DefaultCustomSpeedButtonCaption;

For the Caption property, you must also disable the default assignment of the Caption property (otherwise your component would be automatically get a caption like 'CustomSpeedButton1').
This line does that for you: ControlStyle := ControlStyle - [csSetCaption];

Finally it is good practice to split your component registration into a separate unit.
That allows you to have a design-time package that registers your components in the IDE and a run-time package (or no package at all) for using your components in your applications.

If you have a component icon, then you load that in the registration unit as well (since it is only needed at design time).

Ray Konopka has written an excellent book on component writing which is still very valid: Developing Custom Delphi 3 Components
Like many good Delphi books, it is out of print, but you can order a PDF copy on his site.

I'm not sure what your CommentTitle and CommentText properties are for, so I have kept them in the source below.

Listing 1: actual component

unit CustomSpeedButtonUnit;

interface

uses
  SysUtils, Classes, Controls, Buttons;

const
  DefaultCustomSpeedButtonCaption = 'Comments';

type
  TCustomCustomSpeedButton = class(TSpeedButton)
  strict private
    FCommentText: string;
    FCommentTitle: string;
  strict protected
    procedure SetCommentText(const Value: string); virtual;
    procedure SetCommentTitle(const Value: string); virtual;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property CommentTitle: string read FCommentTitle write SetCommentTitle;
    property CommentText: string read FCommentText write SetCommentText;
  end;

  TCustomSpeedButton = class(TCustomCustomSpeedButton)
  published
// note you cannot use 'default' for string types; 'default' is only valid for ordinal ordinal, pointer or small set type
// [DCC Error] CustomSpeedButtonUnit.pas(29): E2146 Default values must be of ordinal, pointer or small set type
//    property Caption default DefaultCustomSpeedButtonCaption;
    property CommentTitle;
    property CommentText;
  end;

implementation

constructor TCustomCustomSpeedButton.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  Caption := DefaultCustomSpeedButtonCaption;
  ControlStyle := ControlStyle - [csSetCaption];
end;

destructor TCustomCustomSpeedButton.Destroy;
begin
  inherited Destroy;
end;

procedure TCustomCustomSpeedButton.SetCommentText(const Value: string);
begin
  FCommentText := Value;
end;

procedure TCustomCustomSpeedButton.SetCommentTitle(const Value: string);
begin
  FCommentTitle := Value;
end;

end.

Listing 2: component registration

unit CustomSpeedButtonRegistrationUnit;

interface

procedure Register;

implementation

uses
  CustomSpeedButtonUnit;

procedure Register;
begin
  RegisterComponents('Standard', [TCustomSpeedButton]);
end;

end.
顾铮苏瑾 2024-08-10 23:53:23

您需要在组件的构造函数中设置原始值。

编辑:您还需要将 add ControlStyle := ControlStyle - [csSetCaption]; 添加到构造函数中。

You need to set the original values in the component's constructor.

EDIT: You'll also want to put add ControlStyle := ControlStyle - [csSetCaption]; to the constructor.

余生再见 2024-08-10 23:53:23

@Etherman:如果您想要一个具有默认值的字符串属性并且想要将其保存到 DFM - 即使它是空白的 - 您必须自己完成。幸运的是,Delphi 为您提供了做到这一点的方法。看一下这段代码:

type
  TMyComp = class(TControl)
  private
    FMyStringProperty: string;
    procedure WriteMyStringProperty(Writer: TWriter);
    procedure DefineProperties(Filer: TFiler);  override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MyStringProperty: string read FMyStringProperty write FMyStringProperty stored False;
  end;


implementation


constructor TMyComp.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FMyStringProperty := 'my default value';
end;

procedure TMyComp.WriteMyStringProperty(Writer: TWriter);
begin
  Writer.WriteString(FMyStringProperty);
end;

procedure TMyComp.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineProperty('MyStringProperty', nil, WriteMyStringProperty, True);
end;

@Etherman: In case you want to have a string property with default value AND you want to save it to DFM - even if it is BLANK - you have to do it yourself. Fortunately, Delphi gives you methods to do that. Take a look at this code:

type
  TMyComp = class(TControl)
  private
    FMyStringProperty: string;
    procedure WriteMyStringProperty(Writer: TWriter);
    procedure DefineProperties(Filer: TFiler);  override;
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MyStringProperty: string read FMyStringProperty write FMyStringProperty stored False;
  end;


implementation


constructor TMyComp.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FMyStringProperty := 'my default value';
end;

procedure TMyComp.WriteMyStringProperty(Writer: TWriter);
begin
  Writer.WriteString(FMyStringProperty);
end;

procedure TMyComp.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineProperty('MyStringProperty', nil, WriteMyStringProperty, True);
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文