35

我需要将一个包中定义的大量 Delphi 组件更改为另一个包中的类似组件。大部分繁重的工作可以通过替换 DFM 文件中的文本(组件类型和属性)来完成 - 当然保存为文本。

我已经搜索了 Stackoverflow 和 Google,现在正在从http://www.felix-colibri.com/papers/colibri_utilities/dfm_parser/dfm_parser.html改编 Felix Colibri DFM 解析器

我在解析器阻塞的 DFM 文件中遇到了一个“功能”:在类型规范之后的 [number]s,如下所示:

inherited DialoogEditAgenda: TDialoogEditAgenda
  ActiveControl = PlanCalendar
  Caption = 'Agenda'
  [snip]
  inherited PanelButtons: TRzPanel
    Top = 537
    [snip]
    inherited ButtonCancel: TRzBitBtn [0]  <== *here*
      Left = 852
      [snip]
    end
    object CheckBoxBeschikbaarheid: TRzCheckBox [1]  <== *here*
      Left = 8
      [snip]
    end
    inherited ButtonOK: TRzBitBtn [2]  <== *here*
      Left = 900
      [snip]
    end
  end
  inherited PageControl: TRzPageControl
    Left = 444
    [snip]
  end
  object PanelBeschikbaarheid: TRzSizePanel [2]  <== *here*
    Left = 967
    [snip]
  end
  object PanelScheduler: TRzPanel [3]  <== *here*
    Left = 23
    Top = 22
    [...]

这些 DFM 中的许多都被大量继承(我已经为此调整了 Colibri 的代码),但是一个带有继承的小型测试应用程序未能在 DFM 中生成 [number] 个。

在扩展解析器代码之前我的问题是:有谁知道这些 [number] 来自哪里,因此,我可以在解析 DFM 文件之前删除它们吗?

谢谢

4

2 回答 2

37

这些数字并非完全没用。假设你有类TA, TBand TC, TBandTC都派生自TA. DFM 看起来像:

object A: TA
  object X: TX
  end
end

inherited B: TB
  object Y: TY
  end
end

inherited C: TC
  object Y: TY [0]
  end
  inherited X: TX [1]
  end
end

BC不同之处在于它们和子组件的顺序是X相反Y的。子组件顺序的确切含义取决于组件(见下文),但最值得注意的是,如果它们是TWinControl后代,或者它们都是TControl不派生自的后代TWinControl,这意味着它们在是否X显示 overYYover方面有所不同X

删除这些数字可能会改变形式,所以你不应该盲目地这样做。但是,根据您的目标,您可以修改解析器(源代码似乎可用)以简单地跳过数字。

组件的相对顺序通常并不重要,但也有一些例外。更详细地解释一下:

对于普通控件,子组件以 (1)TControl不是从 派生的后代开始TWinControl,然后是 (2)TWinControl后代,最后是 (3) 任何非TControl组件。在每一个中,组件的相对顺序是可调整的:对于控件,“放在前面”和“放在后面”尽可能地移动控件,但限制是 non-TWinControl永远不能放在 a 之后TWinControl。对于非控件,(名称略有错误)“创建顺序”选项允许您更改顺序。因此,假设您有两个标签(A 和 B),两个编辑控件(C 和 D),以及一个数据集和数据源(E 和 F),您可以得到例如 ABCDEF、BACDEF、ABDCFE 的顺序,但不是 ACBDEF。

保存到 DFM 文件时会保留该顺序:当不使用视觉继承时,组件只会按顺序保存并重新加载。当您使用继承时,DFM 文件会从基础处理到派生,因此在上述情况下,TC创建时,其X成员始终在其Y成员之前创建。在组件顺序很重要的情况下,需要[0]and[1]来告诉 Delphi RTL 之后修复顺序。

组件订单的实际作用取决于组件类型。正如“放在前面”/“放在后面”的名称所暗示的那样,控件使用组件顺序来指定 Z 顺序。对于其他组件类型,它意味着组件想要的任何含义。例如,菜单可以使用组件顺序来指定其菜单项的顺序(从上到下)。工具栏控件可以使用组件顺序来指定工具栏按钮的顺序,即使这些工具栏按钮本身不是控件。数据集使用组件顺序来指定字段顺序,因此也是 a 中列的默认顺序TDBGrid

于 2012-06-06T14:41:00.867 回答
0

我最近写了一个 DFM 解析器,它支持这些类型的索引。它是用 Go 编写的,生成的 DFM 文件看起来就像 Delphi 的一样。

https://github.com/gonutz/dfm

它针对 RAD Studio 源文件和我们自己的生产代码进行了测试,它解析所有文件并逐字节生成文件。目的是提供一种简单的方法来更改 DFM 树并生成看起来像是由 RAD Studio 创建的输出。

于 2020-06-21T14:06:24.430 回答