覆盖组件在单独的Design-Time包中创建构造函数

时间:2012-02-10 13:40:59

标签: delphi components

编程环境:Delphi 6及更高版本

我知道自Delphi 6以来,自定义组件必须具有单独的设计和运行时包。因此,组件的所有运行时功能必须位于单独的单元中,并单独打包到组件的设计时包中。

我的问题如下:我的组件具有在运行时在表单上创建时需要运行的代码,以及需要在设计时运行的其他代码,当组件放在形成。我已设法将运行时代码放入单独的运行时单元,打包并成功部署它。

但是,在单独的设计时模块单元中,当组件放置到表单上时,如何在设计时引用和添加需要包含在组件的创建构造函数中的设计时代码?< / p>

4 个答案:

答案 0 :(得分:4)

您可以使用

将设计时行为与运行时行为分开
if [not] (csDesigning in ComponentState) then

但是,如果您的构造函数代码需要DesignIDE设计时包,例如来自单位DesignEditorsDesignIntf等......,我认为你被卡住了。也许一些IOTA参与可以提供帮助。但由于似乎不存在用于创建组件的通知程序接口,因此需要自定义IOTAFormEditor。不是那么容易,如果不是不可能的话。

答案 1 :(得分:2)

确保您的DPK定义了您选择的符号,例如DESIGNTIME。然后你就可以使用这样的东西,只在需要时包含设计时单位:

uses Windows, Whatever, Something
  {$IFDEF DESIGNTIME}
  ,DesignIntf
  {$ENDIF}
  ;

然后在构造函数代码中使用相同的代码:

constructor TMyClass.Create(aOwner:TComponent);override;
begin
  inherited;
  {$IFDEF DESIGNTIME}
  // I'm at design time.
  {$ENDIF}
end;

使用此技术时,您应该为pacakge和普通可执行文件使用单独的DCU目录,或者每次从设计时包转换到其他项目时都执行build。这是因为如果DCU发生了变化,Delphi只会重新构建PAS,在这种情况下,PAS并不能说明整个故事,定义的符号也很重要。如果在构建设计时项目时由Delphi编译的磁盘上有DCU,则在尝试编译正常项目时可能会看到ToolsApi.DCU not found。重建会重新编译DCU并使消息消失。同样,如果在构建正常项目后重新编译(而不是重新构建)设计时项目,则DCU可能会陷入非DESIGNTIME状态,从而使您没有特殊的设计时行为。

答案 2 :(得分:2)

为什么不使用回调?

从你的designtime包初始化代码执行以下操作:

unit MyDsgnUnit;

interface

  //TMyHook defined in AnImplUnit

  TMyDesignHandlerObject = class
      procedure MyMethod(Sender:TObject;ParentForm:TObject); { must match TMyHook }
  end;

implementation

uses AnImplUnit, DesignUnitNamesHere;

procedure TMyDesignHandlerObject.MyMethod(Sender:TObject);
var
  newObject:TMyComponent;
begin
   newObject := TMyComponent(Sender);
   DoSomethingThatneedsDesigntimeStuff(newObject);
end;

finalization
   ADesignHandlerObject.Free;
initialization
   ADesignHandlerObject := TMyDesignHandlerObject.Create;
   AnImplUnit.AfterConstructionHook := TDesignHandlerObject.MyMethod;

并在您的组件中执行以下操作:

unit AnImplUnit;
interface

type
   TMyHook = procedure(Sender:TObject;ParentForm:TObject) of object;
var

  AfterConstructionHook:TMyHook;

implementation

...

procedure TMyComponent.Create(AOwner:TComponent);
begin
   inherited Create(AOwner);
   DOMyStuff;
   if Assigned(AfterConstructionHook)
       AfterConstructionHook(Sender,Parent);
end;

更新刷新示例更多。没有理由你不能向AfterConstructionHook添加更多参数,但由于你对Sender的引用已经是TMyComponent类型,所以当你可以在TMyComponent(Sender)中访问所有公共或受保护的内容时,我看不出这一点。从你的钩子函数中,如果你在本地继承(称为受保护的访问类),你也可以访问受保护的东西。

答案 3 :(得分:0)

只要你的代码不需要IDE工具,比如设计界面等,那么你需要做的就是检查组件标志,你可以在组件的任何地方使用它,如下所示......

procedure TNewEdit.Loaded;
begin
  inherited;
  if (csDesigning in ComponentState) then
    ShowMessage('Designing')
  else
    ShowMessage('Running');
end;

然而,如果不知道你想要做什么,就会有几个门打开...例如,如果你想在设计时改变一个属性值,在运行时改变一个不同的值,那么就有流你必须处理的问题。