我的MDI主程序中有一个ADOConnection1,传递给DLL中MDI子窗体的ADOQUERY,在DLL中MDI子窗体的show中有语句:showmessage(adoquery1.adoconnection1.string);但显示子窗体时候报错误!
错误为:adortl70.bpl的XX地址错误!请高手帮助解决!!我的窗体采用了带包运行!
如能解决另给200分!

解决方案 »

  1.   

    原程序如下:主程序
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB;type
      TCallModule =  procedure(SS:TADOConnection);stdcall;
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        ADOConnection1: TADOConnection;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      LibHandle: HModule;
      procedure LoadModule(AModuleName: PChar);
    implementation{$R *.dfm}procedure LoadModule(AModuleName: PChar);
    var
      CallModule: TCallModule;
      FPointer: TFarProc;
      s:string;
      m:pchar;
    begin
        LibHandle := LoadLibrary(AModuleName);
        FPointer := GetProcAddress(LibHandle,'CallModule');
        if FPointer<>nil then
        begin
          CallModule := FPointer;
          CallModule(fORM1.ADOConnection1);
        end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      LoadModule('C:\Documents and Settings\Administrator\桌面\mdi4\z\project1.dll');end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      showmessage(inttostr(form1.MDIChildCount));
    end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    var
        iCount: Integer;
    begin
        if MessageDLG('是否退出?',mtConfirmation,[mbYes,mbNO],0) = mrYes then
        begin
            for iCount := 0 to MDIChildCount - 1 do
            begin
              MDIChildren[iCount].Close;
              MDIChildren[iCount].Free;
            end;
            if not (LibHandle = 0) then
              FreeLibrary(LibHandle);
            CanClose := True;
        end else
            CanClose := False;end;end.
      

  2.   

    dll程序1:
    library Project1;{ 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,
      Unit1 in 'Unit1.pas' {Form2};{$R *.res}
    exports
      CallModule;begin
    end.
      

  3.   

    DLL中的MDI窗体
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB,Activex;type
      TForm2 = class(TForm)
        ADOQuery1: TADOQuery;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormDestroy(Sender: TObject);
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form2: TForm2;
      procedure CallModule(ss:TADOConnection);stdcall;
    implementation{$R *.dfm}procedure CallModule(SS:TADOConnection);
    begin
    //  Coinitialize(nil);
        if not Assigned(Form2) then
          Form2:=TForm2.Create(Application);
    //      Application.CreateForm(TForm2, Form2);
    //        Form2 := TForm2.Create(NIL);
        Form2.Show;
        Form2.ADOQuery1.Connection:=ss;end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    end;procedure TForm2.FormDestroy(Sender: TObject);
    begin
    Form2 := nil;
    end;procedure TForm2.FormShow(Sender: TObject);
    begin
      showmessage(form2.ADOQuery1.Connection.ConnectionString);
    end;end.
      

  4.   

    procedure CallModule(SS:TADOConnection);
    ...
        Form2.Show;procedure TForm2.FormShow(Sender: TObject);
    begin
      showmessage(form2.ADOQuery1.Connection.ConnectionString);
    end;    Form2.ADOQuery1.Connection:=ss;執行順序是不是這樣??
      

  5.   

    干吗要传递TADOConnection呢,传Connectionstring不就OK吗??? 只不过在Delphi中要将参数String转为pchar型
      

  6.   

    如果传递connectionstring那就表示每打开一个子窗体就要进行一次和数据库的连接,
    即影响用户数据库的连接用户数量,而且也比我现在的方法要慢的
      

  7.   

    mdi子窗体create的时候就show了,你的show没有用阿,而且ss给的晚了,试试
    --
    var  Ado:TAdoconnection;
    procedure CallModule(SS:TADOConnection);stdcall;
    begin
      //Coinitialize(nil);
        Ado:=ss;
        if not Assigned(Form2) then
          Form2:=TForm2.Create(application);
    end;
    procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    end;procedure TForm2.FormDestroy(Sender: TObject);
    begin
      Form2 := nil;
    end;procedure TForm2.FormShow(Sender: TObject);
    begin
       ADOQuery1.Connection:=Ado;
       showmessage(adoquery1.Connection.ConnectionString);
    end;end.
      

  8.   

    我试了一下
    或者把
       ADOQuery1.Connection:=Ado;
    放到create事件里面就没有问题,但放到create后面(如下)就出现你上面的错了
    --------------------------
    var  Ado:TAdoconnection;
    procedure CallModule(SS:TADOConnection);stdcall;
    begin
      //Coinitialize(nil);
        Ado:=ss;
        if not Assigned(Form2) then
          Form2:=TForm2.Create(application);
          Form2.ADOQuery1.Connection:=Ado;
    end;
    ----------------------------------------------------------
      

  9.   

    jinjazz(近身剪(N-P攻略))我按你的方法实验了,但还是不行啊!我有原程序,我发给你,你帮助我看看好吗?
      

  10.   

    而且你这种办法能保证你子窗体中的变量和主窗体中的adoconnection是同一个连接吗?
      

  11.   

    而且你这种办法能保证你子窗体中的变量和主窗体中的adoconnection是同一个连接吗?
      

  12.   

    yi~~,我在看看,昨天下班前试了一下,的确可以的阿,你发个demo到[email protected]我看一下
      

  13.   

    在你的主程序里加上use ShareMem单元试一下
      

  14.   

    楼主看看,我和你的有什么不一样的,是不是我理解错了:按你的顺序,除了unit的名字不一样,我加点注释
    --
    主程序:
    unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB;type
      TCallModule =  procedure(SS:TADOConnection);stdcall;
    type
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        ADOConnection1: TADOConnection;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      LibHandle: HModule;
      procedure LoadModule(AModuleName: PChar);
    implementation{$R *.dfm}procedure LoadModule(AModuleName: PChar);
    var
      CallModule: TCallModule;
      FPointer: TFarProc;
      s:string;
      m:pchar;
    begin
        LibHandle := LoadLibrary(AModuleName);
        FPointer := GetProcAddress(LibHandle,'CallModule');
        if FPointer<>nil then
        begin
          CallModule := FPointer;
          CallModule(fORM1.ADOConnection1);
        end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      LoadModule('project3.dll');     //路径我改了
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      showmessage(inttostr(form1.MDIChildCount));
    end;procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    var
        iCount: Integer;
    begin
        if MessageDLG('是否退出?',mtConfirmation,[mbYes,mbNO],0) = mrYes then
        begin
            for iCount := 0 to MDIChildCount - 1 do
            begin
              MDIChildren[iCount].Close;
              MDIChildren[iCount].Free;
            end;
            if not (LibHandle = 0) then
              FreeLibrary(LibHandle);
            CanClose := True;
        end else
            CanClose := False;end;end.
      

  15.   

    第二个文件,和你的一样
    library Project3;{ 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,
      Unit3 in 'Unit3.pas' {Form2};  //unit名字{$R *.res}
    exports
      CallModule;
    begin
    end.
      

  16.   

    第三个
    unit Unit3;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, ADODB,Activex;type
      TForm2 = class(TForm)
        ADOQuery1: TADOQuery;
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormDestroy(Sender: TObject);
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form2: TForm2;
      procedure CallModule(ss:TADOConnection);stdcall;
    implementation{$R *.dfm}
    var AdoConn:TAdoConnection;                 //加了单元变量
    procedure CallModule(SS:TADOConnection);
    begin
     AdoConn:=SS;                              //付给变量
        if not Assigned(Form2) then
          Form2:=TForm2.Create(Application);   //create
    end;procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
    Action := caFree;
    end;procedure TForm2.FormDestroy(Sender: TObject);
    begin
    Form2 := nil;
    end;procedure TForm2.FormShow(Sender: TObject);
    begin
      ADOQuery1.Connection:=AdoConn;         //这里给指针
      showmessage(ADOQuery1.Connection.ConnectionString);     //可以
     // showmessage(Form2.ADOQuery1.Connection.ConnectionString); 这句不行
     // showmessage(self.ADOQuery1.Connection.ConnectionString);  这句可以 why??
    end;end.
      

  17.   

    我实验了你的写法是可以的!
    但能否保证MDI子窗体和主窗体采用的是一个连接呢??
      

  18.   

    不知道对不对,我照你的代码编译了一下,在DLL中MDI子窗体的show中定义一个string类型变量,在showmessage之前先把adoquery1.adoconnection1.string赋值给它,然后showmessage这个变量就不会出错。
      

  19.   

    我用string实验过,没有问题,关键问题是我怎么能让MDI子窗体和MDI主窗体采用的是同一个连接!!!!
    怎么能让MDI子窗体和MDI主窗体采用的是同一个连接!!!!
    怎么能让MDI子窗体和MDI主窗体采用的是同一个连接!!!!
      

  20.   

    可以的,用MSSQLServer2000测试,建立用户jin,查询分析器用sa登录,关闭其他所有没必要的连接
    -------------use master
    goselect count(*) 当前连接到SQLSERVER的用户数 from dbo.sysprocesses where status <>'background'  
    exec sp_who2
    -------------------------
    运行结果为4,两个系统一个LOG WRITER ,一个CHECKPOINT SLEEP.两个用户的就是上面的两个过程-------------------------
    运行上面的程序,结果为5,登录名为jin,说明只有一个连接------------------------
    建立一个新工程,不断往里面加adoconnection,设置同上connection设为true,运行上面脚本,发现每加一个,结果都加一,登录名都为jin
      

  21.   

    其实,只是个指针的指向问题,并没有副本的connection建立,你可以把
    var AdoConn:TAdoConnection;              
    换成
    var AdoConn:Pointer;             一样运行正常的
      

  22.   

    var AdoConn:Pointer;  
    这样的话就和你主程序的FPointer意思不就一样了
      

  23.   

    借高手宝地一用!!!高手看过来
    http://community.csdn.net/Expert/topic/3520/3520213.xml?temp=.9209406
    在delphi里面怎么回报这样的错?? SQLText := ' select * from DyeProcessList a,DyeVat b where a.VatNo=b.VatNo  
                 order by case left(VatNO,2) when 'JB' then 1 else 0 end,standard descc '
    [Error] DyeDayPrn.pas(73): Missing operator or semicolon
    [Error] DyeDayPrn.pas(73): Statement expected, but expression of type 'String' found
    [Fatal Error] Salary.dpr(214): Could not compile used unit 'Report\DyeDayPrn.pas'
      

  24.   

    但想问,为什么直接付就不行呢??
    就算我定义一个变量adoquery,然后在付值也不行!??/??
    什么原因造成的呢?
      

  25.   

    〉〉就算我定义一个变量adoquery,然后在付值也不行!??/??可以阿
    procedure CallModule(SS:TADOConnection);
    begin
     Adoquery2:=Tadoquery.Create(nil);
    // AdoConn:=SS;
     AdoQuery2.Connection:=SS;                              //付给变量
        if not Assigned(Form2) then
          Form2:=TForm2.Create(Application);   //create
    end;
      

  26.   

    在DLL中需要用主窗体的Application对象代替DLL中的Application才行,因此主窗体调用DLL的子窗体时需要传入主窗体的Application对象