有3个工程,MainExe.exe, FirstDll.dll, SecondDll.dllFirstDll.dll中有:
frmFirstForm: TfrmFirstForm (此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleSecondDll.dll中有:
frmSecondForm: TfrmSecondForm(此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleMainExe.exe中有:
MainForm: TMainForm
DataModule: TDataModule
------------------------------------
注意,以上3个工程中的DataModule文件其实是一个文件,只是在3个工程中都加入了其中.
MainForm导入一下函数
procedure ShowFirstForm; stdcall; external 'FirstDll.dll';
procedure CreateFirstDataModule; stdcall; external 'FirstDll.dll';
procedure ShowSecondForm; stdcall; external 'SecondDll.dll';
procedure CreateSecondDataModule; stdcall; external 'SecondDll.dll';启动MainExe程序,点Button1按钮,
procedure TMainForm.Button1Click(Sender: TObject);
begin
CreateFirstDataModule; //我想把此行语句删除,直接访问MainExe中的DataModule
ShowFirstForm;
end;procedure TMainForm.Button2Click(Sender: TObject);
begin
CreateSecondDataModule; //我想把此行语句删除,直接访问MainExe中的DataModule
ShowSecondForm;
end;如果是这样写,程序没有问题,frmFirstForm和frmSecondForm都可以正常Show出,
而且其中的DbGrid也可以显示后台数据.可是现在的问题是: DataModule在FirstDll和SecondDll中都创建了一次,2个Dll
中分别建立了相同的Connection, 我想把CreateDataModule的动作放到MainExe中,
也就是说我想在主线程中创建一个Connection, 然后不管加入多少个Dll,都可以
使用这个Dll, 请问应该怎么做????
我试了只在MainExe中创建DataModule, 点Button1的时候抱Missing Connection or ConnectionString, Dll访问不到MainExe的DataModule!
frmFirstForm: TfrmFirstForm (此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleSecondDll.dll中有:
frmSecondForm: TfrmSecondForm(此窗体中放ADOQuery, DataSource, DBGrid连DataModule中的Connection显示一个表的数据)
DataModule: TDataModuleMainExe.exe中有:
MainForm: TMainForm
DataModule: TDataModule
------------------------------------
注意,以上3个工程中的DataModule文件其实是一个文件,只是在3个工程中都加入了其中.
MainForm导入一下函数
procedure ShowFirstForm; stdcall; external 'FirstDll.dll';
procedure CreateFirstDataModule; stdcall; external 'FirstDll.dll';
procedure ShowSecondForm; stdcall; external 'SecondDll.dll';
procedure CreateSecondDataModule; stdcall; external 'SecondDll.dll';启动MainExe程序,点Button1按钮,
procedure TMainForm.Button1Click(Sender: TObject);
begin
CreateFirstDataModule; //我想把此行语句删除,直接访问MainExe中的DataModule
ShowFirstForm;
end;procedure TMainForm.Button2Click(Sender: TObject);
begin
CreateSecondDataModule; //我想把此行语句删除,直接访问MainExe中的DataModule
ShowSecondForm;
end;如果是这样写,程序没有问题,frmFirstForm和frmSecondForm都可以正常Show出,
而且其中的DbGrid也可以显示后台数据.可是现在的问题是: DataModule在FirstDll和SecondDll中都创建了一次,2个Dll
中分别建立了相同的Connection, 我想把CreateDataModule的动作放到MainExe中,
也就是说我想在主线程中创建一个Connection, 然后不管加入多少个Dll,都可以
使用这个Dll, 请问应该怎么做????
我试了只在MainExe中创建DataModule, 点Button1的时候抱Missing Connection or ConnectionString, Dll访问不到MainExe的DataModule!
begin
Form1:=TForm1.Create(nil);
Form1.ADOQuery1.Connection:=ado;
Form1.ADOQuery1.SQL.Text:='select top 1 * from salesman';
Form1.ADOQuery1.Open;
Form1.Show;
end;{$R *.res}
exports
ShowFirstForm;
..............SecondDll.dll中也类似定义处理。MainExe.exe中:procedure ShowFirstForm(ado:TAdoConnection); stdcall; external 'project1.dll';............
DataModule上放自己的ADOConnection1 ShowFirstForm(DataModule.ADOConnection1);
ShowSecondForm(DataModule.ADOConnection1);
里面有很多自定义的对象,包括DataSet等。不过这个变量要定义在EXE中,
把这个变量传入DLl就可以了。
我的exe+dll就是用这种变量代替DM的。
//------------------------------------------------------------------------------
//定义主模块传递子模块系统参数结构
//------------------------------------------------------------------------------
PSysParamRec = ^TSysParamRec;
TSysParamRec = record
EmpId: Integer; //职员ID
EmpCode: string; //职员编号
EmpName: string; //职员姓名
EmpPwd: string; //员工密码
UserId: Integer; //用户ID
UserCode: string; //用户编号
UserName: string; //用户姓名
UserPwd: string; //用户密码
DptId: Integer; //所属部门ID
DptCode: string; //所属部门编号
DptName: string; //所属部门名称
StockId: Integer; //所属仓库ID
StockCode: string; //所属仓库编号
StockName: string; //所属仓库名称
ModId: Integer; //模块ID
ModCode: string; //模块编号
ModName: string; //模块名称
MainTitle: string; //窗体的标题
MainApp: TApplication; //窗体的"TApplication"对象
Conn: TADOConnection; //数据库连接组件
SysSet: TSysSetRec; //系统参数设置
InfoDbs: TInfoDbRec; //基础资料数据集
end;
象2樓做法:通過傳遞指針,然后指定connection。這應該會造成地址訪問非法,因為會去訪問其中的數據成員(我沒有特地進行測試)。雖然地址是傳進了dll,但dll并無權限訪問exe內的對象數據。1、可采用1樓的做法,將dm等共用模塊放到bpl,bpl可達到“無縫鏈接”的效果;
2、可以創建需要的connection,與原先做法相比,不需引用dm。但此做法將問題復雜化,還不如引用dm。
if Connection <> Value then
begin
{ At design time we require the dataset to be closed }
if (csDesigning in ComponentState) then CheckInactive;
{ Set a flag that we can no longer requery if active }
FConnectionChanged := Active;
{ Allow nil assignment while open for disconnected recordsets }
if Active and (Value = nil) then
RecordSet.Set_ActiveConnection(nil);
if Assigned(Connection) then Connection.UnregisterClient(Self);
if Assigned(Command) then Command.Connection := Value;
if Assigned(Value) then
begin
Value.RegisterClient(Self);
if Active and Assigned(Value.ConnectionObject) then
RecordSet.Set_ActiveConnection(Value.ConnectionObject);
end;
if not (csLoading in ComponentState) then
DataEvent(dePropertyChange, 0);
end;
注意這段
Value.RegisterClient(Self);//虛方法,可通過
if Active and Assigned(Value.ConnectionObject) then//active為false,應該馬上退出,不繼續執行
RecordSet.Set_ActiveConnection(Value.ConnectionObject);
照如上分析,應正常運行。關鍵是active為false,否則訪問value.connecobject,就會出錯。