动态调用DLL的问题(200分)

  • 主题发起人 主题发起人 一飞冲天
  • 开始时间 开始时间

一飞冲天

Unregistered / Unconfirmed
GUEST, unregistred user!
procedure Tmain.getdll;
type
Tintfunc=function (AHandle: THandle;
ACaption: String;strUserId:string;
strMenuId:string): Longint;StdCall;
var
LibHandle,Ahandle:Thandle;
filepathchar:PChar;
showcalendar:Tshowcalendar;
Tp:Tfarproc;
Tf:tintfunc;
res:longint;
begin
// filepathchar:=pchar(FilePath);
LibHandle:=0;
LibHandle:=LoadLibrary('MS0102.DLL');
if LibHandle>0 then
try
Tp:=GetProcAddress(LibHandle,pchar('ShowDllFrm'));
if tp<>nil then
begin
Tf:=Tintfunc(tp);

res:=tf(Application.Handle,'ss','sss','fdfd');
application.Handle:=main.Handle;
end
else
ShowMessage('ShowDllFrm函数没有找到');
finally
FreeLibrary(LibHandle);
main.Show;
end
else
ShowMessage('dll没有找到');
end;
上面的代码是没问题的,但调用后出现问题!无法结束调用dll程序的线程!下面是我的dll代码
uses
SysUtils,
Classes,
ComObj,ActiveX,
DataModule in 'DataModule.pas' {DmFrm: TDataModule},
DLLFrm in 'DLLFrm.pas' {DLLForm},
PubUtils in 'PubUtils.pas';
{$R *.res}
exports
ShowDllFrm;
这也没什么问题哦呵呵,打开dll中的模块窗口的代码如下
implementation
Uses Datamodule,PubUtils, DBTables;
{$R *.DFM}
//参数:Ahandle:Thandle 传入调用本窗体的程序句柄;
//Acaption:string 传入本窗体的窗体标题,本例中没有使用
//以下的boolean变量可以根据自己的需要而增减,传入按钮控制
//
//返回值:Longint;
//
//==============================================================================
function ShowDllFrm(AHandle: THandle;
ACaption: String;strUserId:string;
strMenuId:string): Longint;
var
DLLForm: TDllForm;
//引用本窗体
begin
// Copy application handle to DLL's TApplication object
Application.Handle := AHandle;
//保存用户和菜单信息
sUserId:=strUserId;
sMenuId:=strMenuId;
InitEnv;
DLLForm := TDLLForm.Create(Application);
Result := Longint(DLLForm);
//以上的几句几乎不需改动
// DLLForm.Caption := ACaption;
DLLForm.ShowModal;
//显示该窗体
end;
调用没问题,但调用了后(执行了FreeLibrary)后,连main窗口(调用dll的窗口)也关闭了。但进程列表中还有该程序没有终止。如果加上application.destroy的话还是一样。请大虾指教
 
还是尽可能不用String类型的变量。
 
把 sharemem 单元放在两个dpr的uses语句第一位就可以了。
因为你使用了string类型的变量进行传递
 
尽量不要传递string类型的变量,将它转化成pchar
 
全部换成了pchar,问题仍然没有解决
 
其实我这是用dll封装了窗体,我看了以前的帖子然后把getdll过程中的
res:=tf(Application.Handle,'ss','sss','fdfd');改成了
res:=tf(Handle,'ss','sss','fdfd');别人的问题是解决了,但我却变成了程序无法响应
调用的窗口关闭了,主窗口就死在那里了,晕(2个窗口都是normal类型)
 
把 sharemem 单元放在两个dpr的uses语句第一位
然后找到一个叫什么的.bpl到程序当前目录下
 
主要还是程序handle没处理好,应该与String参数无关。试一下作以下修改:
procedure Tmain.getdll;
type
Tintfunc=function (AHandle: THandle;
ACaption: String;strUserId:string;
strMenuId:string): Longint;StdCall;
var
LibHandle,Ahandle:Thandle;
filepathchar:PChar;
showcalendar:Tshowcalendar;
Tp:Tfarproc;
Tf:tintfunc;
res:longint;
begin
// filepathchar:=pchar(FilePath);
LibHandle:=0;
LibHandle:=LoadLibrary('MS0102.DLL');
if LibHandle>0 then
try
Tp:=GetProcAddress(LibHandle,pchar('ShowDllFrm'));
if tp<>nil then
begin
Tf:=Tintfunc(tp);

res:=tf(Application.Handle,'ss','sss','fdfd');
[red] //application.Handle:=main.Handle;[/red]
end
else
ShowMessage('ShowDllFrm函数没有找到');
finally
FreeLibrary(LibHandle);
main.Show;
end
else
ShowMessage('dll没有找到');
end;

uses
SysUtils,
Classes,
ComObj,ActiveX,
DataModule in 'DataModule.pas' {DmFrm: TDataModule},
DLLFrm in 'DLLFrm.pas' {DLLForm},
PubUtils in 'PubUtils.pas';
[red]var
DllApp: TApplication;[/red]
{$R *.res}
exports
ShowDllFrm;
implementation
Uses Datamodule,PubUtils, DBTables;
{$R *.DFM}
[red]procedure MyDLLProc(Reason: Integer);
begin
if Reason = DLL_PROCESS_DETACH then
//退出时
begin
if Assigned(DllApp) then
Application := DllApp;
end;
end;
[/red]
//参数:Ahandle:Thandle 传入调用本窗体的程序句柄;
//Acaption:string 传入本窗体的窗体标题,本例中没有使用
//以下的boolean变量可以根据自己的需要而增减,传入按钮控制
//
//返回值:Longint;
//
//==============================================================================
function ShowDllFrm(AHandle: THandle;
ACaption: String;strUserId:string;
strMenuId:string): Longint;
[red]//var
//DLLForm: TDllForm;
//这里已在Uses中包含了DllForm,不必另外定义[/red]
begin
// Copy application handle to DLL's TApplication object
[red] if not Assigned(DllApp) then
begin
DllApp := Application;
Application.handle := AHandle;
end;
[/red]
//保存用户和菜单信息
sUserId:=strUserId;
sMenuId:=strMenuId;
InitEnv;
[red] try
if not Assigned(FrmMain1258) then
DLLForm := TDLLForm.Create(Application);
DLLForm .ShowModal;
except
DLLForm .Free();
end;
[/red]
Result := Longint(DLLForm);

end;

[red]begin
DLLProc := @MyDLLProc;
end;
[/red]
//最后注意在Dll窗体关闭时释放在DLL中分配的内存
 
不行[:(]你估计是按你系统改的,但你系统上一些东西的重要声明我不知道,按你的我这边搞不定,比如MyDLLProc,DllApp ……
 
MyDllProc、DllApp的定义我上面都给出了啊,没有另外的东西了(我这里是Delphi5.0)
 
在dll中的模式窗体不需要传入handle
可这样改dll
function ShowDllFrm(ACaption: String;strUserId:string;
strMenuId:string): Longint;
var
DLLForm: TDllForm;
//引用本窗体
begin
// Copy application handle to DLL's TApplication object
//保存用户和菜单信息
sUserId:=strUserId;
sMenuId:=strMenuId;
InitEnv;
DLLForm := TDLLForm.Create(Application);
Result := Longint(DLLForm);
//以上的几句几乎不需改动
// DLLForm.Caption := ACaption;
DLLForm.ShowModal;
//显示该窗体
dllform.free;
end;

如果是非模态窗体的话
可以需传入handle
可这样用
function ShowDllFrm(AHandle: THandle;
ACaption: String;strUserId:string;
strMenuId:string): Longint;
var
DLLForm: TDllForm;
//引用本窗体
begin
// Copy application handle to DLL's TApplication object
//保存用户和菜单信息
sUserId:=strUserId;
sMenuId:=strMenuId;
InitEnv;
DLLForm := TDLLForm.Create(Application);
dllform.formhandle:=ahandle;
Result := Longint(DLLForm);
//以上的几句几乎不需改动
// DLLForm.Caption := ACaption;
DLLForm.Show;
//显示该窗体
end;
传进来的handle只需用全局变量handle即可
 
现在我删去了数据连接,就是一个单窗口问题依旧,请各位检查
//调用dll的函数,在某按钮click事件里引用
procedure Tmain.getdll;
type
Tintfunc=function (AHandle: THandle): Longint;StdCall;
var
LibHandle,Ahandle:Thandle;
filepathchar:PChar;
Tf:tintfunc;
Tp:Tfarproc;
res:longint;
begin
// filepathchar:=pchar(FilePath);
LibHandle:=0;
LibHandle:=LoadLibrary('DllPrj.dll');
if LibHandle>0 then
try
Tp:=GetProcAddress(LibHandle,pchar('ShowDllFrm'));
if tp<>nil then
begin
Tf:=Tintfunc(tp);
res:=tf(application.Handle);
end
else
ShowMessage('ShowDllFrm函数没有找到');
finally
FreeLibrary(LibHandle);
end
else
ShowMessage('dll没有找到');
end;
//dll文件主单元
library DllPrj;
uses
ShareMem,
SysUtils,
Classes,
DLLFrm in 'DLLFrm.pas' {DLLFrm};
exports
ShowDllFrm;

begin
end.
//dll中引用的创建窗口单元
unit DLLFrm;
//==============================================================================
//本程序由杨明学参照《高级编程》书写;
//
//程序封装一个模式窗体于DLL中,并结合我们的权限要求对按钮进行控制;此只是一个
//范例程序,在具体的过程中可以进行修改,如可以增加和删除按钮的个数,在增加和减少
//按钮的个数的同时应修改ShowDllFrm的参数的个数。
//
//版本:1.0 。
//
//完成时间:2003年6月5日
//==============================================================================
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, Grids, Calendar,Buttons, StdCtrls, ComCtrls, DBGrids,
TFlatButtonUnit, TFlatSpeedButtonUnit, ExtCtrls, TFlatPanelUnit;
type
TDLLForm = class(TForm)
FlatPanel1: TFlatPanel;
btn_Add: TFlatSpeedButton;
btn_save: TFlatSpeedButton;
btn_query: TFlatSpeedButton;
btn_print: TFlatSpeedButton;
btn_exit: TFlatSpeedButton;
FlatPanel2: TFlatPanel;
FlatPanel3: TFlatPanel;
FlatPanel4: TFlatPanel;
Label11: TLabel;
Label10: TLabel;
Label9: TLabel;
Label8: TLabel;
btn_delete: TFlatSpeedButton;
btn_cancel: TFlatSpeedButton;
btn_Modify: TFlatSpeedButton;
Memo1: TMemo;
Edit7: TEdit;
Label5: TLabel;
Label3: TLabel;
Label1: TLabel;
Label2: TLabel;
Edit6: TEdit;
Edit5: TEdit;
Label4: TLabel;
Edit1: TEdit;
Edit2: TEdit;
Label7: TLabel;
TreeView1: TTreeView;
procedure btn_exitClick(Sender: TObject);
end;

{ Declare the export function }
function ShowDllFrm(AHandle: THandle): Longint;
stdCall;
var
sUserId,sMenuId:string;
implementation
Uses Datamodule,PubUtils, DB, DBTables;
{$R *.DFM}

//==============================================================================
//
//本文件的主函数,用于显示非模式窗体,同时传入按钮控制变量。
//
//函数名: ShowDllFrm
//
//参数:Ahandle:Thandle 传入调用本窗体的程序句柄;
//Acaption:string 传入本窗体的窗体标题,本例中没有使用
//以下的boolean变量可以根据自己的需要而增减,传入按钮控制
//
//返回值:Longint;
//
//==============================================================================
function ShowDllFrm(AHandle: THandle): Longint;
var
DLLForm: TDllForm;
//引用本窗体
begin

DLLForm := TDLLForm.Create(Application);
Result := Longint(DLLForm);
//以上的几句几乎不需改动
// DLLForm.Caption := ACaption;
DLLForm.ShowModal;
//显示该窗体
dllform.free;
//显示该窗体
end;


procedure TDLLForm.btn_exitClick(Sender: TObject);
begin
close;
end;

end.
//用静态调用没问题,但动态调就总说什么内存啊,什么没响应啊什么什么的
我delphi6pack2,和升级没关系:)
to:52free 不知道formhandle是什么,是不是要另外use下什么单元?请大家帮我看看
代码很简单了,就在这里,我不认为有什么错误,但……就一个寡窗体什么都没有也是这样我太伤心了…………《在线等待!!!!!!!!!!!!!!!!!》
 
现在是说调用没问题,但到了FreeLibrary(LibHandle);的时候出现cpu调试窗口,有的时候不出则程序没法响应
 
多人接受答案了。
 
后退
顶部