要求:
主调程序动态调用dll,把各个业务dmi子窗体都封装成不同的dll,用同一个数据模块,主调程序通过传递句柄和数据模块给dll,dll实现业务功能,
常做数据库开发的朋友一定清楚吧,求这样的一个例子,谢谢。

解决方案 »

  1.   

      一.在DLL中创建Form   
      1.一步,创建DLL工程,及加入设置好的Form   
      library   MGRPERSN;   
      uses       SysUtils,   Classes,   
        MGRPERFM   in   'MGRPERFM.pas'   {FormPERSON};//1.Form的代码(与一般的Form一样)   
      {$R   *.RES}   
      exports   
          ShowPerSN;//2.函数输出口定义   
      begin   
      end.   
      2.   在DLL设定的Form的设置     
      unit   MGRPERFM;   
      interface   
      uses   Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   Forms,   Dialogs,   
        ComCtrls,   ToolWin,   ImgList;   
      type   
        TFormPERSON   =   class(TForm)   
        private   
            {   Private   declarations   }   
        public   
            {   Public   declarations   }   
        end;   
      //些处的变量不再用,给其改个地方,如下(改变之一)   
      //var     FormPERSON:   TFormPERSON;   
      {   Declare   the   export   function   宣布Form函数出口}//改变之二   
      function   ShowPerSN(AHandle:   THandle;   ACaption:   String):BOOL;   StdCall;   
      implementation   
      {$R   *.DFM}       //函数据过程定义   
      function   ShowPerSN(AHandle:   THandle;   ACaption:   String):BOOL;   
      var       FormPERSON:   TFormPERSON;   //定义窗体类(上面的放到了此处)   
      begin   
      //拷贝应用程式句柄给DLL的应有程式对象   
        Application.Handle   :=   AHandle;   
        FormPERSON   :=   TFormPERSON.Create(Application);//创建控件TForm   
        try   
            FormPERSON.Caption   :=   ACaption;   
            FormPERSON.ShowModal;//显示此Form               
            Result   :=   False;   //反回成功值   
        finally   
            FormPERSON.Free;   
        end;   
      end;   
      二.DLL中函数及窗体的调用   
      1.调用方法一   
      implementation   //在此的下方写明调用函数的DLL   
      {$R   *.DFM}//DLL内函数调用   
      function   PenniesToSoins(SourceResult:Integer):Integer;     StdCall   external   'FIRSTDLL.DLL';   
      2.调用方法二   
      type     //在此创建一个函数类   
      {   First,   define   a   procedural   data   type,   this   should   reflect   the   procedure   that   is   exported   from   the   DLL.   }   
        {   Create   a   new   exception   class   to   reflect   a   failed   DLL   load   }   
        TShowPerSN   =   function   (AHandle:   THandle;   ACaption:   String):   BOOL;   StdCall;   
        EDLLLoadError   =   class(Exception);//同时创建一个出错记录类   
      TMAINCLTR   =   class(TForm)   //这里不变,系统自动生成   
      procedure   TMAINCLTR.ToolButton1Click(Sender:   TObject);   
      var     //按钮的调用事件:调用过程   
        LibHandle:   THandle;       ShowPerSN:   TShowPerSN;   
      begin   
        Application.Title:='Title';   
        LibHandle   :=   LoadLibrary('MGRPERSN.DLL');   {   Attempt   to   load   the   DLL   尝试装入DLL文件}   
        try   
            if   LibHandle   =   0   then   
                raise   EDLLLoadError.Create('Unable   to   Load   DLL(无法成功装入MGRPERSN.DLL)');   
            @ShowPerSN   :=   GetProcAddress(LibHandle,   'ShowPerSN');   
            if   not   (@ShowPerSN   =   nil)     then     ShowPerSN(Application.Handle,   'Title')//呼叫出窗体   
            else           RaiseLastWin32Error;   
        finally   
            FreeLibrary(LibHandle);   //   Unload   the   DLL.   
        end;   
      end; 
      

  2.   

    楼上跑题了,这样的代码都会。我想问的是:
    1.要封装MDI子窗体,跟SDI不是一回事,有区别的。2.一定要传递adoconnection 对象给DLL,一个程序只共用一个ADOconnection,exe程序决定连接那个数据库,然后调用DLL时把它的ADOconnection传给DLL,使dll连接的是同一个数据库。我试了一些写法总是报内存错误,所以请教高手给个例子看看
      

  3.   

    PlugIn = function(const app: TApplication; const adocnn: TADOConnection): Integer; stdcall;var
      hInst: THandle;
      plug: PlugIn;
    begin
      hInst := LoadLibrary('test.dll');
      if hInst=0 then exit;
      plug := GetProcAddress(hInst,'PlugInTest');
      plug(Application,nil);
    end;
    //////////////////////////////////////////////////
    library test;uses
      SysUtils,
      Classes,
      ADODB,
      Forms,
      Windows,
      Messages,
      child in 'child.pas' {FmChild};var
      DllApp: TApplication;{$R *.res}procedure MyDLLProc(Reason: Integer);  
    begin
      //DLL is unloading. Restore the Application pointer.
      if Reason=DLL_PROCESS_DETACH then
      begin
        if Assigned(DllApp) then Application := DllApp;
        FreeLibrary(Application.Handle);
      end;
    end;procedure PlugInTest(const app: TApplication; const adocnn: TADOConnection); stdcall;
    begin
      Application := app;
      if FmChild=nil then
      begin
        FmChild := TFmChild.Create(app);
      end;
      FmChild.Show;
    end;exports
      PlugInTest;begin
      DllApp := Application;
      DllProc:= @MyDLLProc;
    end.
    procedure TFmChild.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      FmChild := nil;
      Action := caFree;
    end;