主程序分别调用stock.dll、sell.dll,非模式状态显式,指定了他们的父窗体Parent为主程序中的一个Panel,(在模式状态下显式不能指定dll的父窗体,不知道什么原因...)现在有几个问题请教各位:
1、点击菜单调用了stock.dll,不进行任何操作,直接关闭主程序,主程序窗体是不见了,但实际上程序没有关闭,在进程中仍可以看到!必须按Ctrl+F2强行退出调试状态才结束!
但是点击stock.dll窗体里面的close按钮后,dll关闭了,主程序也正常关闭了.现在的问题也就是直接关闭主程序,已调用的dll没有自动释放?2、看到资料是说一般显式调用dll的非模式窗体必须有配套的两个过程或函数,一个调用、显示窗体,另外一个用于释放窗体,对于释放窗体的这个过程或者函数不晓得在主程序中应该怎么调用?在什么时候调用呢?下面是部分代码:
stock.dll内容:
function ShowDllForm(AHandle: THandle):Boolean;
var DllForm:Tcggl_main_f;
begin
   Result := True;
    try
      CoInitialize(nil);
      if cggl_main_f=nil then
      begin
        DllForm := Tcggl_main_f.Create(Application);
        try
            DllForm.ParentWindow:=AHandle;
            dm:=Tdm.Create(Application);//创建dm
            DllForm.Show;
        except
            on e:exception do
            begin
                cggl_main_f.Free;
                dm.Free;
            end;
        end;
      end;
    except
      Result:=False;
    end;
end;function FreeDLLForm(AHandle:THandle):Boolean;//【这段释放的不知道该怎么写,请教各位帮忙写下 ^_^ 】
begin
  Application.Handle:=AHandle;
 //dm中用到SocketConnection的要先于dll主窗体之前关闭~~
  if dm.SocketConnection1.Connected then dm.SocketConnection1.Connected:=False;
  if cggl_main_f.Showing then cggl_main_f.Close;  
  if not cggl_main_f.Showing then
  begin
    cggl_main_f.Free;
    Result:=True;
  end else Result:=False;end;主程序中:
Type
  TShowDllForm = Function(AHandle:THandle):boolean;stdcall;
  TFreedllForm = Function(AHandle:THandle):boolean;stdcall;var
  main_f: Tmain_f;
  HandleCall:THandle;//stock.dll窗口句柄procedure Tmain_f.MyEXImage9Click(Sender: TObject);
var
 ShowDllForm: TShowDllForm;
begin
  try
    if HandleCall=0 then
    begin
      HandleCall:=LoadLibrary('stock.dll');
      if HandleCall=0 then
      begin
         Messagebox(Handle,'没有找到附带DLL文件,请确认程序是否完整!','加载DLL失败',MB_OK+MB_ICONEXCLAMATION);
         Exit;
      end ;
      @ShowDllForm:=GetProcAddress(HandleCall,'ShowDllForm') ;
      if @ShowDllForm<>nil then
      try
        ShowDllForm(RzPanel10.Handle);
      except
         raise Exception.Create('加载DLL失败');
      end;
    end;
 finally
   FreeLibrary(RzPanel10.Handle);
 end;
end;procedure Tmain_f.FormDestroy(Sender: TObject);
begin
  if HandleCall<>0 then
  begin
    FreeLibrary(HandleCall);
    HandleCall:=0;
  end;
end;不知道FreeDllForm在主程序中何时调用?该怎么样调用?以上描述的如不清楚随时跟贴说明~~~~麻烦大家了!~

解决方案 »

  1.   

    在Dll中,把DllForm作为全局的变量
    var 
      DllForm:Tcggl_main_f = nil;function FreeDLLForm:Boolean
    begin
      if Assigned(DllForm) then
      begin
        DllForm.Free;
        DllForm := nil;
      end;
    end;exe中退出时调用FreeDllForm但是这里需要注意一个问题,就是多次调用ShowDllForm的问题
    如果你允许多次调用,那么你就应该维护一个DllForm:Tcggl_main_f的数组
    每次创建新的Form时,把Form记录到数组里面如果只有一个这种窗口出现,那么你的ShowDllForm应该如下:function ShowDllForm(AHandle: THandle):Boolean;
    begin
      ....
      if not Assigned(DllForm) then
        DllForm :=  Tcggl_main_f.Create(Application);
      DllForm.Show;
      ...
    end;
    //再次提醒下,DllForm是全局的
      

  2.   

    感谢楼上回答,对于回答的内容因为个人水平限制有些模糊,正在揣摩中 ^_^FreeDllForm在主程序退出中:
    procedure Tmain_f.FormClose(Sender: TObject; var Action: TCloseAction);
    var FreeCgForm:TFreeCgForm;
    begin
      if HandleCall<>0 then  FreeCgForm(HandleCall);
    end;这样写仍是错误的?原意是不想让客户多次ShowDllForm的,但因为要让Dll在指定的Parent上显示只能采取非模式显示Show,如果用ShowModal则DLL窗体不能在Parent中....请问有没有什么好的方法控制如果DLL已经Show了不能再次加载ShowDllForm呢?通过什么来检测?当客户重复点击如何让已经存在的DllForm显示在最上层呢?
      

  3.   

    在delphi中,我从为用dll,只用bpl,所有怪现象都会消失