用dll封装mdi子窗体,子窗体里做数据库操作。所需要的adoconnection 从主窗体获取,主窗体调用dll以参数或者以adoconnection 指针方式传过去。子窗可以正常取得adoconnection 连接,并做相关数据库操作,但在关闭子窗体后再关主窗体(先关那个不重要,在打开子窗体的时候直接关主窗体也是一样)就会报错,Runtime error 216 at 0029336
找不到原因。分不多,全给了,下面跟出代码 ,各位帮我看看。是不是那里重复释放了资源。先来DLL的。
library Project2;{ 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,
  ADODB,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};
type
  adoPI = ^TADOConnection;{$R *.res}
var DLLApp: TApplication;
    //adopi1 : adoPI;
function ShowForm(var App: TApplication;ParentForm: TForm): Boolean;export; stdcall;
begin
  try
   {获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作}
    Application:= App;//将DLL的Application转为App
    Form1:= TForm1.Create(ParentForm);//创建子窗体,子窗体随着ParentForm存在、释放。
    Form1.FormStyle:= fsMDIChild;//设置窗体模式
    Form1.Show;
    Result:=True;
  finally
    //FreeMem(nil);//有问题
  end;
end;function ShowForm_2(var App: TApplication; ParentForm: TForm; adopi1: adoPI): Boolean;export; stdcall;
begin
   {获取调用窗体的Application,显而易见的功能是 能使你的窗体融合到调用程序中。通过它还能进行很多操作}
    Application:= App;//将DLL的Application转为App
    Form2:= TForm2.Create(ParentForm);//创建子窗体,子窗体随着ParentForm存在、释放。
    Form2.FormStyle:= fsMDIChild;//设置窗体模式
    Form2.Show;
    form2.ADOTable1.Connection:=adopi1^;
end;
{重写Dll入口函数,否则程序会出错}
procedure DLLUnloadProc(Reason: Integer); register;
begin
{DLL取消调用时,发送DLL_PROCESS_DETACH消息,此时将DLL的Application返回为本身}
  if Reason = DLL_PROCESS_DETACH then Application:=DLLApp;
end;exports
ShowForm,
ShowForm_2;begin
{在DLL入口预先储存DLL的Application}
  DLLApp:=Application;
{DllProc:DLL入口函数指针。Delphi定义为 DllProc: TDLLProc;}
{在此指向我们自己定义的函数}
  DLLProc := @DLLUnloadProc;end.下面是DLL里的封装的一个窗体,其中一个unit Unit2;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, DBGrids, DB, ADODB;type
  TForm2 = class(TForm)
    ADOTable1: TADOTable;
    DataSource1: TDataSource;
    DBGrid1: TDBGrid;
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  Form2: TForm2;
  procedure SynAPP(App:THandle);stdcall;
  procedure ShowForm;stdcall;
implementation{$R *.dfm}
procedure SynAPP(App:THandle );stdcall;
begin
  Application.Handle := App;
end;procedure ShowForm;stdcall;
begin
  try
    Form2 := TForm2.Create (Application);
    try
      if Form2.ShowModal = idOk then
      begin
        try
          Form2 := TForm2.Create(Application);
          Form2.ShowModal;
        finally
          FreeAndnil(Form2);
        end;
      end;
    finally
      FreeAndNil(Form2);
    end;
  except
    on E: Exception do
      MessageDlg ('Error in DLLForm: ' +
        E.Message, mtError, [mbOK], 0);
  end;
end;procedure TForm2.Button1Click(Sender: TObject);
begin
  ADOTable1.Open;
  Label1.Caption:=ADOTable1.ConnectionString;
  ShowMessage(ADOTable1.ConnectionString);
end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //ADOTable1.Free;
  Action:=caFree;
end;end.再下面是主窗体的,
interfaceuses Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
  StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
  ActnList, ToolWin, ImgList,XPMan,DataMod,ADODB;type
  TMainForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    FileNewItem: TMenuItem;
    FileOpenItem: TMenuItem;
    FileCloseItem: TMenuItem;
    Window1: TMenuItem;
    Help1: TMenuItem;
    N1: TMenuItem;
    FileExitItem: TMenuItem;
    WindowCascadeItem: TMenuItem;
    WindowTileItem: TMenuItem;
    WindowArrangeItem: TMenuItem;
    HelpAboutItem: TMenuItem;
    OpenDialog: TOpenDialog;
    FileSaveItem: TMenuItem;
    FileSaveAsItem: TMenuItem;
    Edit1: TMenuItem;
    CutItem: TMenuItem;
    CopyItem: TMenuItem;
    PasteItem: TMenuItem;
    WindowMinimizeItem: TMenuItem;
    StatusBar: TStatusBar;
    ActionList1: TActionList;
    EditCut1: TEditCut;
    EditCopy1: TEditCopy;
    EditPaste1: TEditPaste;
    FileNew1: TAction;
    FileSave1: TAction;
    FileExit1: TAction;
    FileOpen1: TAction;
    FileSaveAs1: TAction;
    WindowCascade1: TWindowCascade;
    WindowTileHorizontal1: TWindowTileHorizontal;
    WindowArrangeAll1: TWindowArrange;
    WindowMinimizeAll1: TWindowMinimizeAll;
    HelpAbout1: TAction;
    FileClose1: TWindowClose;
    WindowTileVertical1: TWindowTileVertical;
    WindowTileItem2: TMenuItem;
    ToolBar2: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ToolButton4: TToolButton;
    ToolButton5: TToolButton;
    ToolButton6: TToolButton;
    ToolButton9: TToolButton;
    ToolButton7: TToolButton;
    ToolButton8: TToolButton;
    ToolButton10: TToolButton;
    ToolButton11: TToolButton;
    ImageList1: TImageList;
    DLL1: TMenuItem;
    DLL2: TMenuItem;
    procedure FileNew1Execute(Sender: TObject);
    procedure FileOpen1Execute(Sender: TObject);
    procedure HelpAbout1Execute(Sender: TObject);
    procedure FileExit1Execute(Sender: TObject);
    procedure DLL1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure DLL2Click(Sender: TObject);  private
    { Private declarations }
    procedure CreateMDIChild(const Name: string);
  public
    { Public declarations }
  end;  adoPI = ^TADOConnection;var
  MainForm: TMainForm;
function ShowForm(var App: TApplication; ParentForm: TForm): Boolean;stdcall; external 'Project2.dll';
function ShowForm_2(var App: TApplication; ParentForm: TForm; adopi1: adoPI): Boolean; stdcall; external 'Project2.dll';implementation{$R *.dfm}uses CHILDWIN, about;procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  { create a new MDI child window }
  Child := TMDIChild.Create(Application);
  Child.Caption := Name;
  if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
  //ADOpI := @DataModule1.ADOConnection1
end;procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
  CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
  if OpenDialog.Execute then
    CreateMDIChild(OpenDialog.FileName);
end;procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
  AboutBox.ShowModal;
end;procedure TMainForm.FileExit1Execute(Sender: TObject);
begin
  Close;
end;procedure TMainForm.DLL1Click(Sender: TObject);
begin
    ShowForm(Application, Self);
end;procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin  //Close;
  //FreeAndNil(Self);
  Exit;
end;procedure TMainForm.DLL2Click(Sender: TObject);
begin  ShowForm_2(Application, Self, @DataModule1.ADOConnection1);
end;end.上面就是完整的代码。只要主窗体不调用DLL。关闭主窗体时就不会出错,只要一调DLL。就会出错,还有两个情况,一个是这个程序我拿在win2k AND  win7 关闭主窗体后就不会报错,只有在XP上会,还有一个情况是,只要我DLL里不装ADO控件,只是一个窗体上面放点基本控件,也就不会报错,网上找了些资料,说是可能有资源也经释放了,后面又释放,就会这样,不过我也找不到那里有问题,

解决方案 »

  1.   

    DLL 里不加ado控件 就不会报错呀,说明DLL 能释放的啊
      

  2.   

    在dll窗体中在end.前面加上initialization
      CoInitialize(nil);
    finalization
      CoUninitialize;试试!
      

  3.   


    对了,其中还必须uses ActiveX
      

  4.   

    dll中凡是存在ADO控件的窗体中,都必须:在dll窗体中在end.前面加上   //注意看是不是在这个地方加的initialization
    CoInitialize(nil);
    finalization
    CoUninitialize;
      

  5.   

    把这部份去掉看看。procedure SynAPP(App:THandle );stdcall;
    begin
      Application.Handle := App;
    end;procedure ShowForm;stdcall;
    begin
      try
        Form2 := TForm2.Create (Application);
        try
          if Form2.ShowModal = idOk then
          begin
            try
              Form2 := TForm2.Create(Application);
              Form2.ShowModal;
            finally
              FreeAndnil(Form2);
            end;
          end;
        finally
          FreeAndNil(Form2);
        end;
      except
        on E: Exception do
          MessageDlg ('Error in DLLForm: ' +
            E.Message, mtError, [mbOK], 0);
      end;
    end;
      

  6.   

    to senven7
    你是怎么解决的呀,不要上面的一部分是不要哪部分?