dll封装的无模式窗体调用问题,大家帮忙看看.(100分)

  • 主题发起人 主题发起人 yl0971
  • 开始时间 开始时间
Y

yl0971

Unregistered / Unconfirmed
GUEST, unregistred user!
library Project1;
uses
SysUtils,
Classes,
Unit1 in 'Unit1.pas' {FrmWTCD};

{$R *.res}
exports
ShowWTCD,
CloseWTCD;
begin
end.
//----------------------------------------------------------------
unit1
function ShowWTCD(AHandle: THandle; var PPanel: TPanel): LongInt;
var
FrmWTCD: TFrmWTCD;
begin
Application.Handle := AHandle;
FrmWTCD := TFrmWTCD.Create(Application); //这句动态调用出错
Result := LongInt(FrmWTCD);
Windows.SetParent(FrmWTCD.Handle, PPanel.Handle);
FrmWTCD.Show;
end;

procedure CloseWTCD(IFrm: LongInt);
begin
if IFrm > 0 then
TFrmWTCD(IFrm).Release;
end;
每次动态调用时创建窗体那一句提示"无效的句柄",但是静态调用没有问题,在网上查了资料,很多是模式窗体和子窗体的调用,无模式窗体调用给出的代码都是静态调用,实在找不到原因,大家帮忙给看看
调用代码如下:
procedure TForm1.Button1Click(Sender: TObject);
var
libhandle: THandle;
ShowWTCD: TShowWTCD;
begin
libHandle := Loadlibrary('Project1.dll');
@ShowWTCD := GetProcAddress(libHandle, 'ShowWTCD');
if @ShowWTCD <> nil then
tmpForm := TForm(ShowWTCD(Application.Handle, Panel1));//tmpForm是个临时窗体,每次都是这里出错,提示"无效的窗口句柄";
FreeLibrary(handle);
end;
 
问题产生的原因: 很有可能(不确定)是由于DLL和EXE各自拥有同一全局变量或者对象不同拷贝.
解决的办法(我的):使用包.
 
这里不能使用包,因为想要给程序留出对外的接口,使用户可以很容易的把自己需要的模块加进来,但同时不提供源码给用户.
 
最近也在讲究DLL,
FrmWTCD := TFrmWTCD.Create(Application); //这句动态调用出错
上句话应该不会有错,错的地方可能是FormCreate的过程吧?!
你仔细看看!!!
 
公司不能上外网很麻烦,所以只能晚上来,我个人感觉formcreate的问题不是太大,毕竟静态调用是正确的,我下午查了下,静态调用时,dll里的application.handle开始值为0,并且可以赋值,动态调用时application.handle的值为非0,同时application.handle := ahandle;这句的值没赋进去.
 
to 寻路:
包,我没用过,应该是bpl文件吧,能给我说下如果用包,该怎么调用嘛?同时dpk文件里的unit中和dll里的unit里有什么区别嘛?谢谢!
 
你上面是用到对象FORM调用了,删除就可以了。
技术交流QQ:136293586
 
使用包不过是一种思路.如果确定使用的话,你可以查查以前的帖子,有很多!我回答也不过是拷贝而已,呵呵!
 
动态调用时不要调用FreeLibrary,把libHandle 定义成全局变量,在DLL窗体释放时再FreeLibrary。
 
谢谢各位,现在不是释放的问题,而是调用时就出错.
 
无模式窗体不能立即释放
FreeLibrary(handle);//错误
静态调用是程序结束才释放所以不会报错,建议使用模式窗体,或者消息通知方式进行释放
 
谢谢各位不是freelibrary的问题,还没到那地方呢,问题解决了,顺便说下原因,代码如下:
function ShowWTCD(AHandle: THandle; var PPanel: TPanel): LongInt;stdcall;
//------------------------------------------------------------------------
function ShowWTCD(AHandle: THandle; var PPanel: TPanel): LongInt;//注意这里没有stdcall
var
FrmWTCD: TFrmWTCD;
begin
Application.Handle := AHandle;
FrmWTCD := TFrmWTCD.Create(Application); //这句动态调用出错
Result := LongInt(FrmWTCD);
Windows.SetParent(FrmWTCD.Handle, PPanel.Handle);
FrmWTCD.Show;
end;
//-------------------------------------------------------------------------
错误是由于只在声明里加了stdcall
而实现里没加stdcall,加了就好了,很奇怪,静态可以,动态这样就不能调用,另外告诉我错误的那个朋友同时还提到一个问题,当时没注意,就是dll里尽量不要把对象当做参数传递,如果要传递对象很麻烦,因为dll主要是基于结构化编程,对类等支持不是很好.
 
令注: 模式窗体和无模式窗体的区别在于,无模式窗体dll中除了引出创建函数外还应该有一个释放的函数,和freelibrary的关系不是很大,已经试验通过了,顺便谢谢大家.
 
前段时间解释有误,已改正!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
I
回复
0
查看
830
import
I
后退
顶部