关于把设计时代码从运行时代码中分离出来的问题

        自从Delphi6出来以后,一个经常被提到的问题是Proxies.pas文件从源文件中消失了。
  
  这个改变是大趋势的一个部分。Borland在Delphi   5中没有装载DsgnIntf.dcu,这显然是要强迫迎合Delphi和C++Builder的许可协议。运行时代码在很多控件中常被不经意地用到。在某些方面Borland鼓励:如果你运用新的控件向导,你将发现这个向导只创建了一个单元,它把控件运行时的框架代码和注册函数放在同一个单元中。

  在Delphi6中Borland更进一步,不仅用DesignIntf替换了DsgnIntf,而且属性编辑器也被放进了DesignEditors,DesignMenus,DesignWindows和其它的一些设计文件里。特别是DesignEditors使用了其它的一个名叫Proxies的IDE文件。(Proxies代码放在DesignIDE.bpl文件中。)不用说这些改变将会产生编译时的错误。

  如果你的运行时代码已经与设计时代码分开了,那么就很容易修改。打开设计时包,然后选择一个目录,点击Add按钮。填写designide.dcp和点击确定。重新编译你的包,这时错误已经没有了。

  如果你的设计时代码和运行时代码已经混合在一起了,那应该怎么解决呢?在Delphi里DesignIDE.bpl不是一个可以再分发的包。因此,即使是只是设计时包使用了组件的运行时代码或是只是控件dcu用了都将产生问题。

  99.99%的情况事实上很容易解决。你的运行时代码事实上没有使用设计时代码;问题是没有合适的分开。

  设计时包应该包括:

  1、所有的注册声明。
  2、所有的属性编辑器。
  3、所有的组件编辑器。
  4、将需要DesignIDE和每一个保存组件自己的运行时包。

  运行时包应该包括:

  1、组件自己。
  2、任何编辑器也许会用到的组件可能自己在运行时调用的窗体。

  维一有点混惑的地方是:属或组件是否使用了一个窗体。假如这个窗体在运行时对于组件是可用的,那么它应该包含在运行时包里。如果它只是在设计时可使用,那它就应该包含在设计时包里。一个常见的错误是误认这个窗体本身是一个编辑器,但事实上它不是。而是组件编辑器调用了这个窗体,它是设计时编辑器。

  你应该养成一个把组件分开成两个包的习惯,即使是你只在程序中静态地进行链接,因为混合运行时和设计时代码将使你的代码膨胀。你的设计时代码在运行时不会被执行,但是链接器不会知道,所以把它也一起链接进去了。(这就是为什么DsgnIntf要设法链接进去的原因。)

  让我们看一个简单的例子,了解如何把设计时代码从运行时代码中分离出去:

{   TMixedComponent   }
TMixedComponent   =   class(TComponent)
    private
        FFileName:   String;
    published
        property     FileName   :   String   read   FFileName   write   FFileName;
        {   Published   declarations   }
    end;
    {   TMixedFileNameProperty   }
    TMixedFileNameProperty   =   class(TPropertyEditor)
        function         AllEqual:   boolean;   override;
        procedure       Edit;   override;
        function         GetAttributes:   TPropertyAttributes;   override;
        function         GetValue:   string;   override;
        procedure       SetValue   (const     Value:   string);   override;
    end;
procedure     Register;

implementation

procedure     Register;
begin
    RegisterPropertyEditor(TypeInfo(string),   TMixedComponent,   ’FileName’,  

TMixedFileNameProperty);
    RegisterComponents(’Samples’,   [TMixedComponent]);
end;

function     TMixedFileNameProperty.AllEqual:   boolean;
var
    FirstVal:   string;
    i:   Integer;
begin
    FirstVal   :=   GetStrValue;
    Result   :=   True;
    i   :=   1;
    while     Result   and     (i   <   PropCount)   do
    begin
        Result   :=   Result   and     (GetStrValueAt(i)   =   FirstVal);
        Inc(i);
    end;
end;

procedure     TMixedFileNameProperty.Edit;
var
    Dlg:   TOpenDialog;
begin
    Dlg   :=   TOpenDialog.Create(Application);
    try
        with     Dlg   do
        begin
            Title   :=   ’File   for   ’   +   TComponent(GetComponent(0)).Name;
            FileName:=   Value;
            if     Execute   then     Value   :=   FileName;
        end;
    finally
        FreeAndNil(Dlg);
    end
end;

function     TMixedFileNameProperty.GetAttributes:   TPropertyAttributes;
begin
    Result   :=   [paDialog]
end;

function     TMixedFileNameProperty.GetValue:   string;
begin
    Result   :=   GetStrValue;
end;

procedure     TMixedFileNameProperty.SetValue(const     Value:   string);
begin
    SetStrValue(Value);
end;

end.

  把设计时代码从运行时代码中分离出去的最简单方法是,把所有需要DesignIntf   和DesignEditors   代码放入它们自己的单元中去,那个单元将要添加使用组件单元的声明。组件自己不需要知道那个自己运作的IDE编辑器。首先,把DesignIntf   和   DesignEditors   单元从组件单元的Uses部分删除掉,然后让编译/链接器告诉你哪些类需要移到它们自己的单元中去:

[Error]   MixedComponent.pas(23):   Undeclared   identifier:   ’TPropertyEditor’  
[Error]   MixedComponent.pas(23):   Class   type   required  
[Error]   MixedComponent.pas(24):   Method   ’AllEqual’   not   found   in   base   class  
[Error]   MixedComponent.pas(25):   Method   ’Edit’   not   found   in   base   class  
[Error]   MixedComponent.pas(26):   Undeclared   identifier:   ’TPropertyAttributes’  
[Error]   MixedComponent.pas(27):   Method   ’GetValue’   not   found   in   base   class  
[Error]   MixedComponent.pas(28):   Method   ’SetValue’   not   found   in   base   class  
[Error]   MixedComponent.pas(35):   Undeclared   identifier:   ’RegisterPropertyEditor’  
[Error]   MixedComponent.pas(35):   Undeclared   identifier:   ’TMixedFile’  
[Error]   MixedComponent.pas(46):   Undeclared   identifier:   ’GetStrValue’  
[Error]   MixedComponent.pas(49):   Undeclared   identifier:   ’PropCount’  
[Error]   MixedComponent.pas(51):   Undeclared   identifier:   ’GetStrValueAt’  
[Error]   MixedComponent.pas(51):   Operator   not   applicable   to   this   operand   type  
[Error]   MixedComponent.pas(64):   Undeclared   identifier:   ’GetComponent’  
[Error]   MixedComponent.pas(65):   Undeclared   identifier:   ’Value’  
[Error]   MixedComponent.pas(75):   Undeclared   identifier:   ’paDialog’  
[Error]   MixedComponent.pas(80):   Undeclared   identifier:   ’GetStrValue’  
[Error]   MixedComponent.pas(85):   Undeclared   identifier:   ’SetStrValue’  
[Fatal   Error]   JOComponents.dpk(33):   Could   not   compile   used   unit  

’MixedComponent.pas’  

  下一步是创建一个新的单元存放这些代码。可以命名为类似MixedComponentReg的名子。把Register函数也移到那个单元中去。下面我们可以从错误信息中得知哪些需要移走。第一个错误信息是[Error]   MixedComponent.pas(23):   Undeclared   identifier:   ’TPropertyEditor’,这个信息指出了一个继承自那个设计时单元的类。这是个很清楚的指示,它指明了它是设计时代码和这个类要被移到一个新创建的单元。

  到此,运行时包将会被成功编译(如果还不行,继续把设计时代码从单元中移去,直到没有错误产生)。现在组件在你的应用程序运行时已不再需要Proxies.pas和其它设计时单元了。这个运行时组件非常简单,如下:

unit   MixedComponent;

interface

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

type
    {   TMixedComponent   }
    TMixedComponent   =   class(TComponent)
    private
        FFileName:   String;
    published
        property   FileName   :   String   read   FFileName   write   FFileName;
        {   Published   declarations   }
    end;

implementation

end.

  这最后一步就是把你的组件和它的属性编辑器编译到一个设计时包中,然后安装到IDE中去。

  通过File   |   New   |   Other   选择   package创建一个新的包。调出包选项,选择design-time   only,给Description   项填一个描述文字。选择Requires   folder,点击Add按钮。在Requires   Package   编辑对话框填写Designide.dcp,点击OK。同样,为你的组件运行时包添加dcp。在这种情况下,它放在了JOComponents.dpk,因此JOComponents.dcp被添加到requires项。在requires里有:JOComponents,   designide   和   rtl。最后,选择包含目录,添加MixedComponentReg.pas   到包里。

  到现在我们已经基本完成了!打开MixedComponentReg.pas   添加一对单元到uses部分,这要看你的组件或属性编辑器是否要在声明中使用这个组件(一些复杂的编辑器有时需要知道这个组件的存在)。如果是这样,把它加到Interface的uses部分。否则,加到implementation的uses部分。DesignIntf和DesignEditors就放到Interface的uses里。SysUtils,   Forms,   Dialogs,   和   Classes   在内部的属性编辑器的不同地方使用,因此就放到implementation部分。最后的MixedComponentReg应该象下面这样:

unit   MixedComponentReg;

interface

uses   DesignIntf,   DesignEditors;

type
    {   TMixedFileNameProperty   }
    TMixedFileNameProperty   =   class(TPropertyEditor)
        function     AllEqual:   boolean;   override;
        procedure   Edit;   override;
        function     GetAttributes:   TPropertyAttributes;   override;
        function     GetValue:   string;   override;
        procedure   SetValue   (const   Value:   string);   override;
    end;

procedure   Register;

implementation

uses   MixedComponent,   SysUtils,   Forms,   Dial
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值