如何在C++Builder中使用Delphi控件

(文/施江杰)

Delphi的出现将一大批程序员带入了Windows下的可视化编程,为一 些C&C++的死党程序员所羡慕、感叹。直到C++Builder的出现 这些Programer 才用到了梦寐以求的编程工具,也将一些不得已" 投 敌"到Delphi下的程序 员又拉回到C++的怀抱。她正真将Windows下的可视化编程和面向对象编程语言有机的融合在一起。但是由于C++Builder面市时间较短固而可用的控件不多,而且控件的使用也只针对某一版本,相互之间的可互用性不好, 除非你有Source Code; 对于Delphi就更不用说了,C++Builder根本不能用,当然如果你有Source Code那么你可以转写成C++Builder的控件, 不过你还得经过n遍的Complie …m遍的Step&Go 

   Delphi拥有强大的控件群, 如何使用这些控件一 直苦恼着我们这些C++Builder 的追随者, 我通过一些项目的实践掌握了一些如何在C++Builder中使用Delphi控件的方法。

   我的使C++Builder使用Delphi VCL类库的方法  基于Windows中较通用的DLL方式。 在实际应用中找到了将VCL控件转化为DLL库, 在C++Builder动态调用DLL。 此法适用于非可视VCL控件。

   假令在Delphi中有一Sample控件,有属性  Actived、Pro1、Pro2,欲将这个控件转到C++Builder中使用。

一:Delphi中DLL的制作

    1.在Delphi 中 新 建 一DLL 项 目SampleDLL,时在此项目中Create 一个新的类TTtempcomp 基类为TComponent即也为一个控件, 在其中加入一个constructor Create1,但不作任何动作;
    2.在DLL中加入要导出的属性的Function(Actived、Pro1、Pro2)&Create、Destroy 的 框 架, Exports 中 加 入 导 出 的Function、Procdure 名 称;

    3.在DLL 的 主 过 程 中 对TTempcomp 的 实 例temp1进行Create1, 另外保存出口和设置ExitProc;
    4.在OpenSample 的函数中加入HwCtrl:= Sample1.Create(temp1)对Sample 进行实例化, 对CloseSample和其它属性加入相应的语句;

二:C++Builder 中DLL的使用

    1.将Delphi 中 生 成 的DLL 用implib 生 成LIB 文件加入 C++Builder 的工程文件;
    2.在头文件中加入  extern "C" __declspec(dllimport) bool _stdcall
                         OpenSample(void);
                         extern "C" __declspec(dllimport) void _stdcall
                         CloseSample(void);
                         extern "C" __declspec(dllimport) bool _stdcall
                         Actived (void);
                         extern "C" __declspec(dllimport) int _stdcall Pro1
                         (void);
                         extern "C" __declspec(dllimport) int _stdcall Pro2
                         (void);
    3.在OpenSample后你就可以使用Delphi中的属性Actived 、Pro1、Pro2

三: 参考DLL Source如下:
                 library SampleDLL;
                 uses
                      SysUtils, Classes, Sample;
                    TYPE
                      TTempcomp = class(TComponent)
                      private
                      public
                         constructor Create1;
                      published
                      end;
                    var
                       Sample1  :Sample;
                       SaveExit  :Pointer;
                       temp1     :TTempcomp;
                    constructor TTempcomp.Create1;
                    begin
                    //    inherited Create(self);
                    end;
                    /==============================================
                    function OpenSample: Boolean; stdcall; export;
                    begin
                       HwCtrl:= Sample1.Create(temp1);
                       If Sample1.Actived  then result:=true;
                    end;
 
                   procedure CloseSample; stdcall; export;
                    begin
                        Sample1.Destroy;
                    end;
 
                   function Actived: Boolean; stdcall; export;
                    begin
                       result:=Sample1.Actived;
                    end;

                    function Pro1: Interger; stdcall; export;
                     begin
                        result:= Sample1.Pro1;
                    end;

                    function Pro2: Interger; stdcall; export;
                    begin
                        result:= Sample1.Pro2;
                    end;
                    /==============================================
                    procedure libexit; far
                    begin
                       if Sample1.Actived =true then
                          Sample1.Destroy;
                       ExitProc:=SaveExit;
                       temp1.Destroy;
                    end;
                    exports
                       OpenSample,CloseSample,Actived ,Pro1,Pro2;
                    begin
                      temp1:=TTempcomp.Create1;
                      SaveExit:=ExitProc;
                      ExitProc:=@libexit;
                    end.

   解 释:
   因为VCL控件都继承于TComponent,TComponent的构造函数需要一个AOwner并且也是Component,VCL控件的Create、Destroy 都由控件的拥有者来动作,也就是AOwner; 所以我在此DLL中新设置了一个TTempcomp 类继承于Tcomponent且性设置了一个constructor(构造函数)Create1, 而实际构造时什么都不做,以次作为要Create的Aowner;

   其他还有一种办法就是用Application 作为Aowner但是它是基于Tform的作出来的DLL太大;

   其实,Inprise( 原Borland)尽可以象MicroSoft一样用一些象DCOM类似的组件形式使得产品在同一产品时代保持一定的互用性,来增加产品群的生命力.