通过在 Delphi VCL 中组合两个控件(TEdit 和 TTrackBar)创建一个新组件

Creating a new component by combining two controls (TEdit and TTrackBar) in Delphi VCL

我正在为 Windows 开发 Delphi 10.1 VCL 应用程序。

对于整数或浮点数输入,我需要一个与滑块相连的数字输入字段。当用户更改输入字段中的数字时,滑块位置会相应更改。当用户更改滑块位置时,数字字段中的数字会更新。

我可以通过使用 TEditTTrackBar 并在它们的 OnChange 事件处理程序中添加必要的更新功能来解决这个问题。

问题是我需要许多不同形式的此类输入。因此,我想创建一个新组件,将两个控件 TEditTTrackBar 组合在一个组件中。

  1. 创建新组件是否是多次使用此类滑块输入的最佳策略?

  2. 创建这样一个新组件的最佳方法是什么?

Is the creation of a new component the best strategy for the multiple use of such a slider input?

不一定总是正确的。 (至少按照我的标准)。

What is the best way to create such a new component?

我知道三种方法可以解决你的问题。

方式一:

使用新组件向导创建组件,您可以在其中动态创建 TEditTTrackBar 子组件中的 TGroupBox 子组件。

以下是我的做法。

unit Combindedittrack;

interface

uses
  System.SysUtils,
  System.Classes,
  Vcl.Controls,
  Vcl.comctrls,
  Vcl.StdCtrls;

type
  TCombindEditTrack = class(TGroupBox)
  private
    { Private declarations }
    FEdit: TEdit;
    FTrackBar: TTrackBar;
    procedure EditOnChangeProc(Sender: TObject);
    procedure TrackBaroOnChangeProc(Sender: TObject);
  protected
    { Protected declarations }

  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published declarations }
  end;

procedure Register;

implementation

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

constructor TCombindEditTrack.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  SetBounds(0, 0, 250, 50);
  FEdit := TEdit.Create(Self);
  with FEdit do
  begin
    Text := ''; //<-- you control the appearence here
    Top := 10;
    Left := 10;
    Height := 27;
    Width := 50;
    Parent := Self;
    OnChange := EditOnChangeProc; // your Onchange event handler for the Tedit
  end;

  FTrackBar := TTrackBar.Create(self);
  with FTrackBar do
  begin
    Top := 10; //<-- you control the appearence here
    Left := 60;
    Height := 30;
    Width := 50;
    Parent := self;
    Onchange := TrackBaroOnChangeProc; // your Onchange event handler for the Ttrackbar
  end;
end;

destructor TCombindEditTrack.Destroy;
begin
  FTrackBar.Free;
  FEdit.Free;
  inherited;
end;

procedure TCombindEditTrack.TrackBaroOnChangeProc(Sender: TObject);
begin
  // <-- track bar onchange handling here.
end;

procedure TCombindEditTrack.EditOnChangeProc(Sender: TObject);
begin
  // <-- edit onchange handling here.
end;

end.

方式二:

像这样使用框架(我在 delphi 10 seattle)。

  1. 文件-->新建-->其他-->(在 delphi 个文件上搜索帧)。

  2. 现在添加编辑和轨迹栏并设置它们的 Onchange 事件。

  3. 保存单位。

  4. 在工具面板(标准组件部分)上单击框架组件。

  5. 选择您刚刚创建的框架。

每次使用时您都会得到一个相框的​​副本。

方式3:

像这样使用组件模板(我又在 delphi 10 seattle)

  1. Select 您已经创建和修改了 teditttrackbar.

  2. 在工具栏的“组件”上点击“创建组件模板”。

  3. 为您的模板命名并按确定。

  4. Select 模板调色板,然后是您的模板。

现在请注意,甚至您的代码(事件)也会添加到您的项目中。

终于

以我在 delphi 和 IDE 上的水平,我真的无法给你一个明确的答案,哪个是最好的方法,但我已经分享了我所知道的一切可以帮到你。


编辑: 因为很多评论都坚持认为答案应该说明这是最好的方法。这是基于以下的最佳方式。

放一些选择时应该考虑的重点

1. 如果您愿意,可以轻松修改组合控件(根据我的经验,您会的)。

2.完成这个任务所需要的时间(意思是将要花费的时间 您只需最少的调试和编码即可完全完成任务。

3. 一般源代码可读性。

4. 对您的项目的未来有用。

现在让我们开始根据这些标准批评这三种方法。

方式一:

C1(条件编号 1):只需修改组件的源代码实现,每个 replica/use 将具有相同的效果和属性。然而,方式 3 并非如此。

C2: 这取决于你对组件编写的了解,但是对于这个组件,我花了 5 分钟来创建它,我只是 delphi 的初学者.对于调试,如果出现问题并且问题出在组件实现中,那么您只需修复一次(参见 C1)

C3: 他们在你的表单中没有实现你的组件的源代码只需将它添加到你的表单中,所有的东西都是隐藏的(例如添加一个 tedit 然后去查看表单源代码中的实现)。

C4: 你正在创建一个组件,毕竟这将为你创建自己的组件集打开大门,如 Flatstyle 或 Indy 开源组件。所以下次您需要这样的东西时,只需将它放入您的表单设计器中即可。

方式2:

C1: 这就像方法 1,因为您正在创建一个组件,但这次是视觉上的。修改源帧将改变副本的效果和属性,您还可以对副本添加额外的处理。

副本的Onchange事件的事件处理程序是这样的

procedure TForm1.Frame2Edit1Change(Sender: TObject);
begin
  Frame2.Edit1Change(Sender); //<-- this is the original onchange event you setup at the beginning 
  //<-- you can extra handling here if you want one of the replicas to behave differently than the original  
end;

C2: 时间相同,可能比第 1 条路更快。

C3: 总的来说,它的结果与方法 1 相同。

C4: 与方法 1 不同,您不能在项目 B 中使用在项目 A 中创建的框架。因此您的编码和调试将留在项目 A 中。

方式3:组件模板。

C1: 您不是在创建一个组件,而是在创建一个 repleca/macro 您在上一个项目中执行的确切步骤。改变一个不会改变其他的,它们是分开的。

C2: 时间相同,可能比第 1 条路更快。

C3: 每次您向表单添加模板时,都会添加事件代码(如果它是一个长的 Onchange 代码则不是一个好的视图)。

C4:您可以在项目B中使用在项目A中创建的模板。但是您在项目A中编写的内容将在项目B中(参见c1)甚至变量的引用在项目 B 中不存在(考虑到每次使用模板之间的时间间隔,这可能很难调试和误导)。

结论:提出的每一种方式都将花费时间来编码和调试,并且所有这些方式都将完成任务,但是为了简单性和最小的重用性风险 方法 1 是这里的安全选择,因为它会给您安全更新和升级的机会。调试也更快。

方式 1 的另一个好处是,过一段时间后您会忘记实现以及内部工作方式。唯一应该记住的是组件的用途,因为它将成为您使用的各种组件之一(您不知道 Tedit 是如何实现的,您不需要,但您使用它在您创建的每个项目中)。

根据给定的标准,方式 1 是最好的

也许使用包含这两个控件的容器控件是一种更简单的替代方法。我正在为此使用 ccpack。

https://sourceforge.net/projects/ccpack/

Custom Containers Pack (CCPack) is an integrated tool and component mini- library to produce and maintain composite controls (or simply “composites”) and other containers (forms, data modules and frames). The process of building composite components looks like ActiveForm and Frame creating, but the result is the native VCL component. You can create new composites just as usual forms.

您可以创建一个框架,然后将该框架注册为一个组件。最终结果与创建仅代码组件非常相似,其中子组件是在构造函数中创建的(Nasreddine 的第一个选项)。但是,此方法允许您直观地设计组件并使用对象检查器创建事件处理程序。

这是一个 Stack Overflow 问题,显示了如何注册框架: How to Improve the Use of Delphi Frames