11

Delphi 对象检查器没有按设计显示 TFrame 后代的附加属性。人们倾向于建议使用通常用于在对象检查器上显示 TForm 后代属性的已知技巧。诀窍是:通过设计时包将 TForm 后代的自定义模块注册到 Delphi IDE,例如:

RegisterCustomModule(TMyFrame, TCustomModule);

对象检查器可以通过这种方式显示 TFrame 后代实例的其他属性,但它在嵌入表单时会丢失其帧行为。不可重新设计,无法为其子组件实现事件,并且它接受子控件(它不能)。但它在自己的设计区域中表现正常。

看起来,Delphi IDE 专门为 TFrame 提供的那些行为。它们可能不是一种通用设施。

有没有其他方法可以在不丢失帧行为的情况下做到这一点?

我正在使用德尔福 2007


@Tondrej,

阅读问题的评论,在此先感谢。

框架单元.dfm:

object MyFrame: TMyFrame
  Left = 0
  Top = 0
  Width = 303
  Height = 172
  TabOrder = 0
  object Edit1: TEdit
    Left = 66
    Top = 60
    Width = 151
    Height = 21
    TabOrder = 0
    Text = 'Edit1'
  end
end

unit frameunit;

interface

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

type
  TBaseFrame = Class(TFrame)
  protected
    Fstr: string;
    procedure Setstr(const Value: string);virtual;
  published
    Property str:string read Fstr write Setstr;
  End;

  TMyFrame = class(TBaseFrame)
    Edit1: TEdit;
  private
    // This won't be called in designtime. But i need this to be called in designtime
    Procedure Setstr(const Value: string);override;
  end;

implementation

{$R *.dfm}

{ TBaseFrame }

procedure TBaseFrame.Setstr(const Value: string);
begin
  Fstr := Value;
end;

{ TMyFrame }

procedure TMyFrame.Setstr(const Value: string);
begin
  inherited;
  Edit1.Text := Fstr;
  // Sadly this code won't work and Edit1 won't be updated in designtime.
end;

end.

unit RegisterUnit;

interface

procedure Register;

implementation

uses
  Windows, DesignIntf, frameunit;

procedure Register;
var
  delphivclide: THandle;
  TFrameModule: TCustomModuleClass;
begin
  delphivclide := GetModuleHandle('delphivclide100.bpl');
  if delphivclide <> 0 then
  begin
    TFrameModule := GetProcAddress(delphivclide, '@Vclformcontainer@TFrameModule@');
    if Assigned(TFrameModule) then
    begin
      RegisterCustomModule(frameunit.TBaseFrame, TFrameModule);
      // Just registering that won't cause Tmyframe to loose its frame behaviours
      // but additional properties won't work well.

      //RegisterCustomModule(frameunit.TMyFrame, TFrameModule);  
      // That would cause Tmyframe to lose its frame behaviours
      // But additional properties would work well.

    end;
  end;
end;


end.
4

4 回答 4

4

您正在为您的框架注册哪个自定义模块类?您使用的是哪个版本的 Delphi?

从我对 Delphi 2007 的实验来看,似乎可以工作的自定义模块类是 TFrameModule。该类包含在 delphivclide100.bpl 中。由于没有相应的 delphivclide.dcp,您必须手动加载它:

unit FrameTestReg;

interface

procedure Register;

implementation

uses
  Windows, DesignIntf,
  FrameTest;

procedure Register;
var
  delphivclide: THandle;
  TFrameModule: TCustomModuleClass;
begin
  delphivclide := GetModuleHandle('delphivclide100.bpl');
  if delphivclide <> 0 then
  begin
    TFrameModule := GetProcAddress(delphivclide, '@Vclformcontainer@TFrameModule@');
    if Assigned(TFrameModule) then
      RegisterCustomModule(TTestFrame, TFrameModule);
  end;
end;

end.

我的 FrameTest 单元很简单,它没有 FrameTest.dfm,只有新 TFrame 后代的声明:

unit FrameTest;

interface

uses
  Forms;

type
  TTestFrame = class(TFrame)
  private
    FHello: string;
  published
    property Hello: string read FHello write FHello;
  end;

implementation

end.

使用 TFrameModule 类,到目前为止一切似乎都运行良好。我可以创建 TTestFrame 的新后代以包含在项目中并在 Object Inspector 中编辑其发布的属性,将这个新后代的实例放在 IDE 中的表单上,在 Object Inspector 中编辑它们新发布的属性,编写事件处理程序他们的子组件等。在 .dfm 资源中,我可以看到实例的预期“内联”指令。到目前为止,我还没有遇到任何问题,所以也许这就是解决方案。

于 2008-11-14T12:32:49.693 回答
1

没有必要以“黑客方式”做

uses
...
  DMForm,
  VCLFormContainer,
...

procedure Register;
begin
...
  RegisterCustomModule(TYourFrameClass, TFrameModule);   // for frames
  RegisterCustomModule(TYourModuleClass, TDataModuleCustomModule);   // for data modules
...
end;

还有另一种添加框架的方法

type
  TNestableWinControlCustomModule = class (TWinControlCustomModule)
  public
    function Nestable: Boolean; override;
  end;

function TNestableWinControlCustomModule.Nestable: Boolean;
begin
  Result := True;
end;

+

  RegisterCustomModule(TYourFrameClass, TNestableWinControlCustomModule);

单位名称(在 XE7 中测试):

TCustomModule =>设计编辑器

TDataModuleCustomModule => DMForm (designide.dcp)

TWinControlCustomModule => WCtlForm (designide.dcp)

TFrameModule => VCLFormContainer (vcldesigner.dcp)

我想对于FireMonkey应该可以以类似的方式进行(查找fmxdesigner.dcp并检查 Notepad++ 中的内容)

PS。在较旧的 Delphi 版本中,单元 DMDesigner 中有 TDataModuleDesignerCustomModule 元类而不是TDataModuleCustomModule

聚苯乙烯。其他现有的元类名称:

TCustomFormCustomModule

TIDESourceModuleCustomModule

于 2016-06-23T10:28:35.523 回答
0

不,我不认为这是完全可能的。

当我有类似需求时,我通常会做的就是简单地将框架后代安装为它自己的组件。但是,是的,这样你会失去很多典型的框架行为(尤其是在设计时),例如你不能再直接操作子组件并且对框架的​​更改不再自动传播到在设计时使用它的表单 - 你有首先重新编译包含框架的运行时包。

再说一次,从 OOP 的角度来看,这还不算太糟糕。它实际上强化了实现隐藏的概念。您仍然可以通过框架本身的新属性和方法公开子组件的各个属性和功能。

于 2008-11-14T12:27:24.060 回答
0
procedure TMyFrame.Setstr(const Value: string);
begin
  inherited;
  Edit1.Text := Fstr;
  // Sadly this code won't work and Edit1 won't be updated in designtime.
end;

我认为这是因为它不应该在设计时工作。您将 TBaseFrame 注册为自定义模块,因此 TBaseFrame 的(不是它的后代!!!)属性在设计时应该是可编辑的。Delphi IDE 只知道您注册的类的已发布属性;它对您在项目中所做的任何后代和覆盖一无所知。要使代码在设计时工作,您应该将其包含在 TBaseFrame 定义中:

procedure TBASEFrame.Setstr(const Value: string);
begin
  inherited;
  Edit1.Text := Fstr; 
end;

或者(除了 TBaseFrame)将 TMyFrame 定义注册为自定义模块。

试着理解:设计时的 Delphi IDE 只知道已经在其中注册的东西。这不是障碍;这是合乎逻辑的行为。

于 2012-03-11T04:22:36.760 回答