library Project1;
uses
  SysUtils,
  windows,
  messages,
  controls,
  forms,
  dialogs,
  graphics,
  Classes,
  Unit1 in 'Unit1.pas' {Form1};{$R *.RES}
   var dllapplication :tapplication;
     dllproc:pointer; procedure provachild(parentapplication:tapplication;parentform:tform);export;stdcall;
 var form1:tform1;  begin
  application:=parentapplication;
  form1:=tform1.Create(parentform);
  form1.myparentapplication:=parentapplication;
  form1.myparentform:=parentform;
  windows.SetParent(form1.handle,parentform.handle);
  form1.FormStyle:=fsmdichild;
  form1.Show;  end;
 procedure dllunloadproc(reason:integer);register;
 begin
 if reason=DLL_PROCESS_DETACH then
 application:=dllapplication;
 end; exports
 provachild;
  begin
 // dllapplication:=application;
 // dllproc:=@dllunloadproc;
end.
mdi 子窗体
 
unit1;
public
   myparentapplication:tapplication;
   myparentform:tform;
    { Public declarations }
  end;
var
  Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
application.Handle:=0;
action:=caFree ;end;
 调用代码 
procedure TForm1.Button1Click(Sender: TObject);
 var
proaddr:farproc;
provachild:T_provachlid;begin
 
 dllhandle:=loadlibrary('Project1.dll');
 @provachild:=getprocaddress(dllhandle,'provachild');
 if @provachild<>nil then
 provachild(application,self); end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin    while dllhandle<>0 do
    FreeLibrary(dllhandle);
    close;
     end;procedure TForm1.FormCreate(Sender: TObject);
begin
  dllhandle:=0;
end;
1: 程关闭时,按 ctrl+alt+delete 看,程序还存在啊,
2:mdi的application 关闭时,是否释放,怎样释放

解决方案 »

  1.   

    exports 
    provachild;
    begin
      dllapplication:=application;
      dllproc:=@dllunloadproc;
      //去掉这里的注释
    end.
      

  2.   

    我现在做的项目就采用楼主的模式,所有的功能都封装在一个个DLL中,同样也存在DLL库MDI子窗体释放的问题,这个问题从项目开始到现在快半年啦,眼看项目都要结束这个问题还没得到解决,真是寝食不安,CSDN经常有人说自己是高手,如果那写所谓的高手能给我解决这个难题,我一定开贴重酬!
      

  3.   

    zdy0155 () 程序写的什么呀!to Liusp:
    这种模式很常用的,但动态加载功能dll是不可取的,
    静态是很简单的。主程序有一个主窗口,各个功能用dll来实现,dll中可能会有子窗口
    我不知道你具体用的什么方式。我说一下我们以前一个程序的处理方式,1.
    dll中提供一个函数,用来创建子窗口,假设子窗口类名为TGIS02F01
    函数名为GIS02F01_Open;
    procedure GIS02F01_Open(var Form: TForm; Parameter: string);
    begin
      Form := TGIS02F01.Create(nil);
      Form.WindowState:= ...;
    end;子窗口关闭的时候用action:= caFree;2.
    在主窗口中点击相应的菜单时,调用GIS02F01_Open就行了;
    子窗口在关闭后是可以释放的
      

  4.   

    library dlldb;uses
      Windows,
      Forms in 'forms.pas',
      udll in 'udll.pas' {dll_Frm},
      umainformsVar in 'umainformsVar.pas';{}
    {Function: Load the child Form
     Returns : FormVariable
     Par0: Application var off ExeFile
     Par1: CallBack procedure pointer to inform exefile of unloaded (freed)
           Form
    }
    function ShowChild(App:TApplication;PFormFreeCallBack:Pointer):TForm;stdcall; export;
    begin
      Application:=App;
      Result:=TDll_Frm.Create(Application);
      @FormFreeCallBack:=PFormFreeCallBack;
    end;
    {Function: Set Dll-Application Var back to originall Value
    }
    procedure SetOldApplication;stdcall;export;
    begin
      Application:=OldApp;
    end;
    {$R *.RES}
      exports ShowChild,SetOldApplication;
    begin
      {Save original Applicatioin Variable}
      OldApp:=Application;
    end.unit udll;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      StdCtrls;type
      Tdll_Frm = class(TForm)
        Memo1: TMemo;
        procedure FormDestroy(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
    //    procedure CreateParams(var Params: TCreateParams);override;
      end;
      {ProtoType of Exe_CallBackFunction}
      tf_FormFreeCallBack=procedure ;stdcall;var
      dll_Frm: Tdll_Frm;
      FormFreeCallBack:Tf_FormFreeCallBack;
    implementationuses mdidll,umainformsVar;{$R *.DFM}procedure Tdll_Frm.FormDestroy(Sender: TObject);
    begin
      {notify exe-File that Form is onloaded}
      FormFreeCallBack;
    end;procedure Tdll_Frm.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      action:=caFree;
    end;end.
      

  5.   

    主程序:
    program maindb;uses
      Forms,
      uexe in 'uexe.pas' {Form1},
      Umain in 'Umain.pas' {main};{$R *.RES}begin
      Application.Initialize;
      Application.CreateForm(Tmain, main);
      Application.CreateForm(TForm1, Form1);
      Application.Run;
    end.mainform:
    unit Umain;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Menus;type
      Tmain = class(TForm)
        MainMenu1: TMainMenu;
        Datei1: TMenuItem;
        Neu1: TMenuItem;
        ffnen1: TMenuItem;
        Speichern1: TMenuItem;
        Speichernunter1: TMenuItem;
        N1: TMenuItem;
        Drucken1: TMenuItem;
        Druckereinrichtung1: TMenuItem;
        N2: TMenuItem;
        Beenden1: TMenuItem;
        Bearbeiten1: TMenuItem;
        Rckgngig1: TMenuItem;
        WiederholenBefehl1: TMenuItem;
        N3: TMenuItem;
        Ausschneiden1: TMenuItem;
        Kopieren1: TMenuItem;
        Einfgen1: TMenuItem;
        Inhalteeinfgen1: TMenuItem;
        N4: TMenuItem;
        Suchen1: TMenuItem;
        Ersetzen1: TMenuItem;
        Gehezu1: TMenuItem;
        N5: TMenuItem;
        Verknpfungen1: TMenuItem;
        Objekt1: TMenuItem;
        Fenster1: TMenuItem;
        NeuesFenster1: TMenuItem;
        Nebeneinander1: TMenuItem;
        berlappend1: TMenuItem;
        Alleanordnen1: TMenuItem;
        N6: TMenuItem;
        Verbergen1: TMenuItem;
        Zeigen1: TMenuItem;
        Hilfe1: TMenuItem;
        Inhalt1: TMenuItem;
        Index1: TMenuItem;
        Befehle1: TMenuItem;
        Verfahren1: TMenuItem;
        Tastatur1: TMenuItem;
        Suchen2: TMenuItem;
        Lernprogramm1: TMenuItem;
        Hilfebenutzen1: TMenuItem;
        Info1: TMenuItem;
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
      end;var
      main: Tmain;implementation{$R *.DFM}end.unit uexe;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ExtCtrls, StdCtrls;type
      TForm1 = class(TForm)
        Panel1: TPanel;
        Button1: TButton;
        Memo1: TMemo;
        procedure Button1Click(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
      private
        { Private-Deklarationen }
      public
        { Public-Deklarationen }
        procedure LoadDll;
      end;
      {types for dynamical load from dll}
      TF_ShowChild = function (App:TApplication;PFormFreeCallBack:Pointer):TForm;stdcall;
      {Set old Applicaton Var in Dll to protect for GPF}
      TF_SetOldApplication=procedure ;stdcall;
      EDLLLoadError = class(Exception);
      procedure FormFreeCallBack;stdcall;
    var
      Form1: TForm1;
      ChildForm:TForm;
      ShowChild :TF_ShowChild;
      SetOldApplication:TF_SetOldApplication;
      dlldbhWnd:hwnd=0;
    implementationuses Umain;{$R *.DFM}
    {must be called in dll to recognize if childform is onloaded}
    procedure FormFreeCallBack;
    begin
      ChildForm:=Nil;
    end;
    {dynamically load functions from dlldb.dll}
    procedure TForm1.LoadDll;
    var LastError:DWord;
    begin
      if dlldbhWnd= 0 then begin
        dlldbhWnd:=loadLibrary('DLLDB.DLL');
        if dlldbhWnd =0 then begin
          LastError := GetLastError;
          Raise EDLLLoadError.create(IntToStr(LastError) +
                                     ': Unable to load DLLDB.dll');
        end;
        ShowChild:=getProcAddress(dlldbhWnd,'ShowChild');
        if @showChild=Nil then begin
          Raise EDLLLoadError.create(IntToStr(LastError) +
                                     ': Unable to find function ShowChild');
        end;
        SetOldApplication:=getProcAddress(dlldbhWnd,'SetOldApplication');
        if @SetOldApplication=Nil then begin
          Raise EDLLLoadError.create(IntToStr(LastError) +
                                     ': Unable to find function SetOldApplication');
        end;
      end;
    end;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      loadDll;
      if not assigned(ChildForm) then begin
        ChildForm:=ShowChild(Application,@FormFreeCallBack);
      end;
      ChildForm.Show;
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
      if dlldbhWnd<>0 then begin
        SetOldApplication;
        FreeLibrary (dlldbhWnd);
      end;
    end;
    end.