在主程序里为何取不到DLL中已打开的子窗体的数目?
 self.MDIChildcount 好象只能取主工程内的子窗体数,而取不到调用DLL中子窗体数。

解决方案 »

  1.   

    用findwindow();为何查找不到DLL的窗体呢?
      

  2.   

    帮你up我也正在做,遇到相同的问题,finewindow()找不到窗体,计数也为0
      

  3.   

    当然找不到DLL中打开的窗体的数目,根本就不在一个进程空间啊
    你从DLL中得到后再传回主窗体不行吗?
      

  4.   

    在调用DLL时将主程序的application,screen一起传进去替换DLL中的application,screen在DLL释放时再回复DLl的application,screen就可以了
    {DLL中的部分}
    var
      Dllapp:Tapplication;
      Dllscr:Tscreen;
    function createdllform(app:Tapplication;scr:Tscreen;mainhandle:Thandle;sadoconn:Tadoconnection;mNO:pchar;
      scds:Tclientdataset):Tform;
    begin
      OleInitialize(Nil);
      application:=app;
      screen:=scr;
      mainTH:=mainhandle;
      Application.CreateForm(Tform2, form2);
      Gadoconn:=sadoconn;
      ICDS:=scds;
      form2.ClientDataSet2.Data:=ICDS.Data;
      form2.button1.caption:=string(mNO);
      IniDBgrid(form2.dbgrideh1,form2.clientdataset2,'bill_stock_main');
      result:=form2;
      OleUnInitialize;
    end;procedure exitdll(reason:integer);
    begin
      if reason=DLL_PROCESS_DETACH then
      begin
        application:=Dllapp;
        screen:=Dllscr;
      end;
    end;exports
      createdllform;begin
      Dllapp:=application;
      Dllscr:=screen;
      Dllproc:=@exitdll;
    end.
      

  5.   

    能不能讲具体点?主窗体中怎么样调用DLL?
      

  6.   

    哦……我做到了。
    DLL文件:
    library DLL;uses
      SysUtils,windows,Classes,Controls,Forms,
      DLLForm in 'DLLForm.pas' {FrmDLLChild};{$R *.res}var
    DllApp:TApplication;
    DllScr:TScreen;procedure InitDLL(App:TApplication);stdcall;
    begin
    DLLApp:=Application;
    DllScr:=Screen;
    Application:=App;
    end;procedure FreeDLL;stdcall;
    begin
    Application:=DllApp;
    Screen:=DllScr;
    end;function GetDllChildForm(Parent:TComponent;scr:TScreen):TFrmDLLChild;stdcall;
    begin
    Screen:=scr;
    Application.CreateForm(TfrmDLLChild,frmDLLChild);
    Result := FrmDLLChild;
    end;exportsInitDLL,FreeDLL,GetDllChildForm;begin
    end.
    ******************************************************
    主窗口文件:unit Main;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Menus, DLLForm;//注意这里引用了MDI子窗体的单元type
      TForm1 = class(TForm)
        MainMenu1: TMainMenu;
        N1: TMenuItem;
        Count1: TMenuItem;
        procedure FormDestroy(Sender: TObject);
        procedure N1Click(Sender: TObject);
        procedure Count1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;  function GetDllChildForm(Parent:TComponent;scr:TScreen):TFrmDllChild;stdcall;external 'dll.dll';
      procedure InitDLL(App:TApplication);stdcall;external'dll.dll';
      procedure FreeDLL;stdcall;external 'dll.dll';implementation{$R *.dfm}procedure TForm1.FormDestroy(Sender: TObject);
    begin
      FreeDLL;
    end;procedure TForm1.N1Click(Sender: TObject);
    var
      DForm:TFrmDllChild;
    begin
      DForm := GetDllChildForm(Form1,Screen);
      DForm.Show;
    end;procedure TForm1.Count1Click(Sender: TObject);
    begin
    showmessage(inttostr(Form1.MDIChildCount));
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
    InitDLL(Application);
    end;end.
      

  7.   

    to  Jack_Ye(小杰) :
    能问一下,为什么要引用DLLForm单元呢?我做的是大型系统,把DLL中的子窗体放到主程序里编译,跟单工程文件一样,.EXE太大了。
      

  8.   

    sorry,我也是按别人的文章搞的,我能做的就是把原文帖出来,抱歉……***************************************************************
    DLL中导出窗体指南    
        
    作为一个经常被提起的问题,很多人不知道怎么来从DLL中导出窗体,特别是MDI的子窗体,因此Kingron愿意在这里把一些经验写出来给大家分享,让大家在碰到类似的问题的时候,少走些弯路。
    大家知道,DLL有两种加载方式,至于动态的,和静态的,稍微有点儿区别。动态的加载,大家可以参考Torry's Delphi Page上面的例子,其中有一个MDI的例子,非常简单的,很好用。我的例子以静态加载为主。
    据目前来看,我们要在DLL中导出这个Form的话,必须通过DLL导出函数来做到,但是我们知道DLL工程的Application和Host程序的Application是有区别的,对于一般的应用程序来说,Application是VCL固定的,一般不会修改Application对象指针,但是在DLL中,我们需要使用窗体等,或者使用Application对象的时候,使DLL的Application和Host程序一样,这样才不至于混淆。以下面的例子为例,如果不修改Application对象,那么Host程序退出的时候,可能出现AV错误!例如:在Host中Export一个函数:function DllFunction(App:TApplication;PForm:TForm):TForm2;stdcall;
    begin
    Result :=TForm2.Create(PForm);
    end;那么主程序推出的时候,很可能发生AV错误。
    下面一步一步来做:
    首先,我们需要一个DLL工程,在IDE中New一个DLL,然后New一个Form,Save All File,工程名为DLL.DPR,Form的Unit文件为DLLForm.pas,窗体类名为FrmDLLChild。然后随便设计这个DLLChild Form即可。然后,在DLL.DPR中修改代码,添加:library Dll;
    uses
    SysUtils,windows,
    Classes,Controls,Forms,
    DllForm in 'DllForm.pas' ;
    {$R *.res}var
    DllApp:TApplication;{ 用于初始化:保存DLL本身的Application,然后设置DLL的Application指向Host的Application }procedure InitDLL(App:TApplication);stdcall;
    begin
    DllApp:=Application;
    Application:=App;
    end;{ 善后工作:恢复DLL原来的Application }
    procedure FreeDLL;stdcall;
    begin
    Application:=DllApp;
    end;{ 返回一个窗体对象,这是DLL的主要功能 }function GetDllChildForm(Parent:TComponent):TFrmDLLChild;stdcall;
    begin
    Result := TFrmDLLChild.Create(Parent);
    end;exports
    InitDLL,FreeDLL,GetDllChildForm;begin
    end.至此DLL已经完成了,在使用DLL的时候,需要注意:首先必须调用InitDLL,并且传递主程序的Application作为参数,否则主程序退出的时候,会报AV错误。主程序调用如下:
    ^^^^^^^^^^^********^^^^^^^^^^^^^^^^^^
    为了简单方便地使用,可以把DLL中包含窗体的那个单元Use进来,如果不喜欢,用类型强制也可。^^^^^^^^^^^********^^^^^^^^^^^^^^^^^^
    //注意这里!!我也不喜欢用use的,搞到文件很大,
    //但什么叫用类型强制?我不明白,所以就用use了。
    //如果你搞定了记得告诉我哦!!
    function GetDllChildForm(Parent:TComponent):TFrmDllChild;stdcall;external 'dll.dll';
    procedure InitDLL(App:TApplication);stdcall;external 'dll.dll';
    procedure FreeDLL;stdcall;external 'dll.dll';procedure TForm1.FormCreate(Sender: TObject);
    begin
    InitDLL(Application);
    end;procedure TForm1.FormDestroy(Sender: TObject);
    begin
    FreeDLL;
    end;
    调用窗体代码:var
    DForm:TFrmDllChild;
    begin
    DForm := GetDllChildForm(yourcomponent);
    //yourcomponent是主窗体上的某个TComponent类型的组件,或者就干脆是主窗体Form。
    DForm.Show;
    end;