MDI调用了一个DLL,该DLL有一个FORM,并且窗体里定义了ADOConntion对象。
当MDI试图Call这个DLL显示窗体时就立即报错:
>>>>
Project MDI.exe raised exception class EOleSysError with message '标记没有引用存储'.Process stopped.Use Step or Run to continue.
>>>>
如果在SDI中一点问题都没有,或者换成BDE而不是ADO也是一点问题都没有。dll文件:library mdidll;uses
  Windows,
  Messages,
  SysUtils,
  Classes,
  Graphics,
  Controls,
  Forms,
  Dialogs,
  mdi_Unit in 'mdi_Unit.pas' {Form2};var
Form2: TForm2;
procedure LoadChild(ParentApplication: TApplication; ParentForm: TForm); export; stdcall;
var DllProc: Pointer;begin
Application:=ParentApplication;
Form2:=TForm2.Create(ParentForm);
Form2.MyParentForm:=ParentForm;
Form2.MyParentApplication:=ParentApplication;
Form2.Show;
end;procedure CloseChild(); export; stdcall;
begin
  Form2.Free;
end;
procedure DLLUnloadProc(Reason: Integer); register;
begin
if Reason = DLL_PROCESS_DETACH then Application:=DllApplication;
end;{$R *.res}
exports
LoadChild,CloseChild;
begin
DllApplication:=Application;
DLLProc := @DLLUnloadProc;
end.
dll中的窗体unit:unit mdi_Unit;
interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, ADODB, Grids, DBGrids, Mask, DBCtrls, ExtCtrls,
  DBTables,ActiveX;type
TForm2 = class(TForm)
    Label1: TLabel;
    DataSource1: TDataSource;
    DBNavigator1: TDBNavigator;
    DBGrid1: TDBGrid;
    ADOConnection1: TADOConnection;
    ADOQuery1: TADOQuery;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
MyParentForm: TForm;
MyParentApplication: TApplication;
end;var
DllApplication: TApplication;
implementation{$R *.dfm}procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:=caFree;
end;end.在MDI主窗口调用方法(动态调用):
T_ProvaChild = procedure (ParentApplication: TApplication; ParentForm: TForm); stdcall;procedure TForm1.N1Click(Sender: TObject);
var
DllHandle: THandle;
ProcAddr: FarProc;
ProvaChild: T_ProvaChild;
begin 
DllHandle := LoadLibrary('mdidll');
ProcAddr := GetProcAddress(DllHandle, 'LoadChild');
if ProcAddr <> nil then
begin
ProvaChild := ProcAddr;
ProvaChild(Application,Self);
end
else
  showMessage('ProcAddr is Nil');
end;

解决方案 »

  1.   

    DLL本身有一個的Application,它不與MDI的相同,所以要傳一個Application到DLL中
      

  2.   

    看下面是源码对你应有帮助:    Project1.DPR {主叫程序}
        Unit1.PAS {主叫程序单元}
        Project2.DPR {DLL}
        Unit2.PAS {DLL单元}
    {---------- DLL 主程序 Project2.DPR ----------}library Project2;uses
      SysUtils,
      Classes,
      Unit2 in 'Unit2.pas' {Form1};{$R *.RES}{ 下面的语句用于向调用该 DLL的程序提供调用接口 }
    exports
      DoTest;       { 过程来自单元Unit2 }begin
    end.
    {---------- DLL中的单元 Unit2.PAS ----------}unit Unit2;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Db, ADODB, StdCtrls, Menus;type
      TForm1 = class(TForm)
        ADOConnection1: TADOConnection;{ 本地数据库连接 }
        Memo1: TMemo;                  { 用于显示信息   }
      private
      public
      end;{ 该过程向外提供 }
    procedure DoTest(H: THandle;           { 获得调用者的句柄       }
                     AConn: TADOConnection;{ 获得调用者的数据库连接 }
                     S: string;            { 获得一些文本信息       }
                     N: Integer);          { 获得一些数值信息       }
                     cdecl;                { 指定调用协议           } implementation{$R *.DFM}procedure DoTest(H: THandle; AConn: TADOConnection; S: string; N: Integer);
    begin
      Application.Handle := H;              { 将过程的句柄赋值为调用者的句柄 }
      { 上面语句的作用在于, DLL的句柄和调用者的句柄相同,在任务栏中就不会   }
      { 各自出现一个任务标题了。                                             }
      with TForm1.Create(Application) do try{ 创建窗体                       }
        Memo1.Lines.Append('成功调用');     { 显示一行信息                   }
        ADOConnection1 := AConn;            { 获得数据库连接的实例           }
        Memo1.Lines.Append(
          ADOConnection1.ConnectionString +
          ' - ' + S + ' - ' + IntToStr(N)); { 根据得到的参数显示另一行信息   }
        ShowModal;                          { 模式化显示窗体                 }
      finally
        Free;                               { 调用结束时销毁窗口             }
      end;
    end;end.
    {---------- 调用者 Project1.DPR,很普通的工程文件 ----------}program Project1;uses
      Forms,
      Unit1 in 'Unit1.pas' {Form1};{$R *.RES}begin
      Application.Initialize;
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.
    {---------- 调用者单元Unit1.PAS ----------}unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls, Db, ADODB;type
      TForm1 = class(TForm)
        Button1: TButton;   { 按此按钮进行调用 }
        ADOConnection1: TADOConnection;         { 本地数据库连接,将传递给 DLL }
        procedure Button1Click(Sender: TObject);{ 调用 DLL}
      private
      public
      end;var
      Form1: TForm1;implementation{$R *.DFM}{ 外部声明必须和 DLL中的参数列表一致,否则会运行时错误    }
    procedure DoTest(H: THandle;             { 传递句柄       }
                     AConn: TADOConnection;  { 传递数据库连接 }
                     S: string;              { 传递文本信息   }
                     N: Integer);            { 传递数值信息   }
                     cdecl;                  { 指定调用协议   }
                     external 'Project2.dll';{ 指定过程来源   }{ 调用过程 }
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      DoTest(Application.Handle,
             ADOConnection1,
             'Call OK',
             256);
    end;end.
      

  3.   

    不知道有没有哪位老兄,试过在DLL的MDICHILDFROM中添加主菜单,然后进行菜单融合。并能成功执行菜单命令的。如果有这样的例子,不知可否发一个给我:
       [email protected]
    MSN : [email protected]
      

  4.   

    楼主是不是要在DLL的主单元中进行一个coInitialize
      

  5.   

    to : jxc163
    如何加?我也认为是初始化问题,但不知道如何初始化。
      

  6.   

    我做的数据库的项目基本上都是这种形式的,每个菜单项都用一个DLL去实现。但没用出现你所说的问题。
      

  7.   

    这个问题倒没有遇到过,不过如果将DLL里的窗体显示在调用FORM上的PANEL上时,这个FORM消息响应会有问题,始终没找到答案。
      

  8.   

    你在主调程序USES中加上ADODB,
    然后在调用DLL加如下代码:
    1.OnClose:
      action:=caFree;
    2.OnDestroy:
      form1 := nil;
      
    即可解决你的问题!
      

  9.   

    Application有个特殊的Form,
    Application.MainForm.如果是Mdi程序调用时应该传送这个参数。
      

  10.   

    不知道你的调用方法单元是否有了DB, ADODB两个引用单元
    ========================================
    以前遇到一种情况,在dll中使用了db\adodb,在调用的单元也必需要有db\adodb
    不然会报错!
      

  11.   

    问题已解决
    XXSingle(三笑留情〓★▲◆)   和   nxfbccu()  说的是对的
    感谢所有的参于者
    给分了!