主程序(是MDI主窗体):
...var
   function Load_FeeItemInfo(App: TApplication ):TForm; stdcall; external 'FeeMana.dll';
...procedure TfmMain.N8Click(Sender: TObject);
var
   fmbs_FeeItemInfo:TForm;
begin
    // if (not Assigned(fmbs_FeeItemInfo)) or (fmbs_FeeItemInfo = Nil) then
      begin
          fmbs_FeeItemInfo:= Load_FeeItemInfo( Application);
       end;
    //  fmbs_FeeItemInfo.Show;  
end;
--------------------------------
Dll窗体(要作成MDI子窗体)
library FeeMana;{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }uses
  SysUtils,
  Classes,
  Forms,
  Windows,
  Messages,
  Dialogs,
  ActiveX,
  DB,
  ADODB,
 
  FeeItemInfo in 'FeeItemInfo.pas' {fmbs_FeeItemInfo};var
  DLLApp: TApplication;
  DLLScr: TScreen;  pubAdoConn:TAdoConnection;
{$R *.res}
procedure ExitDLL(Reason: Integer); register;
begin
  showmessage('Dll退出!');
  if(Reason = DLL_PROCESS_ATTACH) then
  begin
    CoInitialize(nil) ;
  end ;  if Reason = DLL_PROCESS_DETACH then
  begin
    Screen:= DLLScr;
    Application := DLLApp;
 
  end;
end;
 
function Load_FeeItemInfo(App: TApplication ):TForm; stdcall;
var
   i:integer;
begin
  Application := App;  //******请注意此行!!!!
   //    CoInitialize(nil) ;   showmessage('staart1');
   if (not Assigned(fmbs_FeeItemInfo)) or  (fmbs_FeeItemInfo = Nil) then
   begin
 
        fmbs_FeeItemInfo:=Tfmbs_FeeItemInfo.Create(app );
        fmbs_FeeItemInfo.FormStyle:=fsMDIChild;
        fmbs_FeeItemInfo.Visible :=True;
 
 
   end;
   Result:=fmbs_FeeItemInfo;
end;
 
exports
  Load_FeeItemInfo;
begin
    DLLApp := Application;
  DLLScr := Screen;
  DLLProc := @ExitDLL; 
end.-----------
Dll子窗体的 OnClose中写有:
procedure Tfmbs_FeeItemInfo.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  action:=cafree;
  fmbs_FeeItemInfo:=Nil;
end;************************************
错误:
1.如果去掉以下这行, 没有显示MDI子窗体,而是出错(退出主程序不会报内存出错):
  
  出错信息: Exception EInvalidOperation in module FeeMana.dll at 000549DF. Application := App;  //******请注意此行!!!!2.如果加上Application := App;这一行, 能显示子窗体,但退出主程序后报内容出错:
   Runtime error 216 at 004C36E6.    3.  ExitDLL 这个函数我发现系统在退出时好像没有执行。

解决方案 »

  1.   

    偶的代码:
    var
      DllApp: TApplication;
      DllScr: TScreen;{$R *.res}procedure MyDllHandle(iReason: Integer);
    begin
      if iReason = 0 then
      begin
        Application := DllApp;
        Screen := DllScr;
      end;
      if iReason = 1 then
      begin
        DllApp := Application;
        DllScr := Screen;
      end;
    end;exports RelationPlanInfShow,UserRelayShow,ClientSrvInfShow,
            ClientDisCloseShow,WorkPlanQueryShow;begin
      DllProc := @MyDllHandle;
    end.
      

  2.   

    1 在dll的全局变量处定义 SaveExit: Pointer;
    2 在dll的全局begin end中的最后
    begin
     ....
      SaveExit := @ExitProc;
      ExitProc := @ExitDLL;
    end.没发现问题
      

  3.   

    建议直接传入Application.Handle即可,Dll窗体退出时应该不会产生问题。最好的办法就是在Dll窗体中不要直接退出,而是输出Dll窗体退出函数供主窗体调用。
      

  4.   

    出错的源码下载地址:http://www.cngrandpower.com/tanyong/jozosoft/down/help.rar