4

在 Delphi 2009 中,在我的一个项目中,我有一个自定义框架,上面有一些控件,我想将其用作其他一些控件的基类。我想将此框架注册为 IDE 向导,以便在新项目列表中可用。当我将新添加的项目(我的自定义框架)添加到项目时,我希望它:

  1. 在对象检查器中显示我添加到自定义框架的所有属性和事件。
  2. 从我的自定义框架而不是 TFrame 派生新创建的框架。

好的,为了让它在 Object Inspector 中显示我的属性和事件,我在 IDE 中注册了一个自定义模块。它不适用于框架。幸运的是,有人在 StackOverflow 上提到了这一点,并给出了答案:

在对象检查器上显示 TFrame 后代的附加属性

然后,为了让它加载我的自定义框架的 DFM,我将 InitInheritedComponent 添加到我的自定义框架的构造函数中。像这样的东西:

constructor TMyFrame.Create(AOwner: TComponent); override;
begin
  inerited;
  if (ClassType <> TMyFrame) and not (csDesignInstance in ComponentState) then
  begin
    if not InitInheritedComponent(Self, TMyFrame) then
      raise EResNotFound.CreateFmt('Resource %s not found', [ClassName]);
  end;
end;

它不起作用!它仍然在设计器中创建一个空框架,而不是我自己的框架。如果我没有将自定义模块注册到 IDE 中,即使不需要 InitInheritedComponent,它也会正确显示我的框架,但对象检查器中不会显示其他属性!

如果我将构造函数源更改为此(用 TFrame 替换 TMyFrame):

constructor TMyFrame.Create(AOwner: TComponent); override;
begin
  inerited;
  if (ClassType <> TFrame) and not (csDesignInstance in ComponentState) then
  begin
    if not InitInheritedComponent(Self, TFrame) then
      raise EResNotFound.CreateFmt('Resource %s not found', [ClassName]);
  end;
end;

框架已正确添加到设计器中,并且在 Object Inspector 中可以看到其他属性,但运行应用程序失败,因为它抱怨框架上的组件已经存在。

所以,我的问题是:让 Delphi IDE 向导使用 DFM 从自定义框架(不是表单)创建派生框架并在 Object Inspector 中显示其附加属性的解决方案是什么?

顺便说一句,我不想​​在运行时在框架中构建控件,因为我也需要它们在设计时可用。

我希望有人能把这件事告诉我。

问候

编辑:

这些框架实际上用作向导组件的页面。我的向导组件在运行时创建它们。我希望用户在“新建项目”菜单中有一个选项,可以将向导页面添加到项目中,并在 IDE 设计器中设计其布局,并将其注册到我的向导组件中以显示在向导中。我从 TFrame 继承了一个基类,因为我的向导页面应该有一些强制控件和一些自定义属性和事件。

4

5 回答 5

4

我已经相当广泛地探索了使用 TFrames(及其相关继承)作为组件开发的基础,并且可以详细说明我发现的内容是否有用,但我从来不需要使用 RegisterCustomModule——我只是从直接使用 TFrame,使用正常的帧继承,然后在标准组件注册单元中注册生成的“最终”版本。这似乎允许两全其美(可视化开发+继承,加上组件调色板+对象检查器功能)。

不过,它有一些小技巧,还有一些需要注意的问题,例如如何命名 TFrame 本身,确保 DFM 文件在第一行正确使用“对象”或“继承”,而且,一般来说,我已经发现创建一个从 TFrame 继承但不添加任何内容的“基本框架”对于复杂继承树的稳定性非常有益……然后从那里继承所有其他的。(在添加已发布的属性等时尤其如此)。

告诉我更多关于您为什么特别想要使用 IDE 向导的信息,也许如果这不是一成不变的方法,我可以提供更多帮助。

于 2009-06-01T22:06:36.333 回答
2

是的,它可以做到!

我已经完成了您在 Delphi 2007 和 2009 中的要求,并且可以说无论更新级别如何,它都适用于两个版本。在此过程中我确实遇到了一些有趣的问题,但最终的解决方案在事后看来非常直接(在我的头撞到墙上一天之后)。在我的回答中对此有更多的了解。

我将自定义框架放入组件的设计时包引用的运行时包中。这对于允许在使用运行时包的应用程序中使用框架以及允许在其他自定义组件包中使用相同的框架是必要的。设计时包还包含一个自定义模块专家,用于将框架添加到文件 -> 新建 -> 其他... -> “新项目”图库并生成自定义默认模块代码。后面的部分主要是为了在实际使用过程中节省编码时间,而且要做好是一件非常痛苦的事情。我将其归结为学习曲线,因为我找不到与我的情况相匹配的完整示例。

来自设计时 DPK 的代码:

requires
  DesignIDE,
  FramePageListD11R,
...
contains
  FramePageListPkgReg in 'FramePageListPkgReg.pas',

并来自 FramePageListPkgReg

implementation

{$R FramePageListIcons.res}

procedure Register;
  begin
    ...
    RegisterCustomModule(TBaseDisplayFrame, TCustomModule);
    RegisterPackageWizard(TDisplayFrameModuleExpert.Create);
  end;

我的框架实现在框架上没有可视组件,因为我的目标是引入虚拟方法、发布的属性、事件并为我的动态框架处理逻辑实现自定义接口。这里是DFM文件的内容和部分PAS文件供参考。请忽略 IDisplayFrameEvent 接口,因为它与当前讨论的主题无关。

object BaseDisplayFrame: TBaseDisplayFrame
  Left = 0
  Top = 0
  Width = 500
  Height = 300
  HorzScrollBar.Smooth = True
  HorzScrollBar.Style = ssHotTrack
  HorzScrollBar.Tracking = True
  VertScrollBar.Smooth = True
  VertScrollBar.Style = ssHotTrack
  VertScrollBar.Tracking = True
  TabOrder = 0
end

TBaseDisplayFrame = class(TFrame, IDisplayFrameEvent)
private
  FOnPageShow : TDisplayFrameEvent;
  FOnPageHide : TDisplayFrameEvent;
  ...
published
  ...
  property OnPageShow: TDisplayFrameEvent read FOnPageShow write FOnPageShow;
  property OnPageHide: TDisplayFrameEvent read FOnPageHide write FOnPageHide;
end;

至于让 DFM 加载,我不需要任何特殊编码。我确实发现 Delphi IDE 中存在一个错误,即 foo 禁止将表单包含到包中。我不记得所有的细节,但是通过手动编辑生成的 DPK 代码很容易解决这个问题。这里是DPK的相关部分供参考。我怀疑这是你的主要问题。请特别注意该行的注释部分,因为这对于将 DFM 包含在包中至关重要。

contains
  BaseDisplayFrameModule in 'BaseDisplayFrameModule.pas' {BaseDisplayFrame: TFrame};

一切正常后,您可以照常创建框架,然后修改 PAS 文件和 DFM 以从框架继承。正如 Jamo 所指出的,不要忘记在 DFM 的第一行中将“object”更改为“inherited”。我看到的唯一怪癖是继承框架上的事件处理程序的名称不符合典型的 Delphi 命名约定,而是派生自基框架类。这纯粹是装饰性的,我还没有花时间弄清楚是否有一个简单的修复方法。

祝你好运!

于 2009-06-02T04:03:34.290 回答
1

鉴于您的实际目标,您是否考虑过可能使用嵌入式表单?我已经使用 AppControls TacEmbeddedForm与Greatis Form Designer (现在也以与TMS Scripter Studio略有不同的形式提供)结合使用AppControls TacEmbeddedForm来完成与您尝试完成的类似的事情,并取得了积极的成果。还没有完成,但它看起来像是提供您正在寻找的一些运行时自定义功能的有希望的途径。

于 2009-06-02T19:25:03.040 回答
1

怀疑这可能已通过Update 3修复,因为我按照您的描述没有问题。我刚刚创建了一个 TFrame 后代,添加了两个属性(布尔值和一个事件),添加了一个面板等。创建了一个新包,其中注册了所述框架,安装了包,将包路径添加到搜索路径。

然后我创建了一个新的 vcl 应用程序,创建了新表单,添加了我的新框架组件,它可以正常编辑,并且两个新属性都可以在 Object Inspector 中使用。

如果这不起作用,我看到了QC 5230中列出的解决方法

于 2009-06-01T16:27:11.097 回答
0

从我的角度来看,框架对于 Delphi 开发人员来说是非常有用的工具。但是——我强烈建议您动态地将框架放置在表单(或其他框架上)(例如来自代码而不是来自表单设计器)。表单上的框架被放入信息 DFM 中,如果您不小心在这种静态放置的框架中移动了一些按钮,Delphi 会将有关更改的信息放入表单 DFM 中。稍后对该按钮在实际框架上的位置的更改有时不会转移到放置的框架上。

于 2009-06-01T22:22:19.513 回答