DLL中的MDI窗口问题.(首次拜访大富翁,请多指教)(100分)

  • 主题发起人 主题发起人 rss
  • 开始时间 开始时间
那就继续吧:
将Delphi函数:
function ShowForm(mainForm:TForm):integer;stdcall
var
Form1: TForm1;
ptr:PLongInt;
begin
ptr:=@(Application.MainForm);
ptr^:=LongInt(mainForm);
Form1:=TForm1.Create(mainForm);
Form1.Show;
result:=1;
end;
转为 CBuilder
int ShowForm(TForm *mainForm)
{
TFrom **m1
//因MainForm 为指向指针的指针
m1=&(Application->MainForm)
*m1=mainForm;
TForm *Form1=new TForm(mainForm);
Form1->Show();
return 1
}
编译无问题,运行显示子窗口后就出错.
本人对C++的指针很糊涂,请高手指点改怎样转换Delphi函数.

 
OK,问题发现了。
还是LoadLibrary的问题,
>> aa=DLL1()

>> FreeLibrary(lib1);

调用完该函数就FreeLibrary是不行的,这正是强行修改
MainForm的副作用的体现,因为DLL中Application的MainForm
已经指向了当前的MDI主窗口,如果每次调用都FreeLibrary,
必然将当前的MDI主窗口一起Free掉了。

因此我对调用流程作了修改:

var
Moudle: THandle;
DLLCreateChild :procedure(MyForm:TForm) stdcall;
...

procedure TMainForm.FormCreate(Sender: TObject);
begin
Moudle := Loadlibrary('testdll.dll');
if Moudle <= 32 then Application.Terminate;
DLLCreateChild := GetProcAddress(Moudle,'DLLCreateChild');
end;

procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
DLLCreateChild(MainForm);
end;

procedure TMainForm.FormClose(Sender: TObject
var Action: TCloseAction);
begin
Freelibrary(Moudle);
end;

这样就没问题了。
 
改画个圆满的句号了,综合两位高手的回答正是问题的标准答案:
<<sam~s Teach Yourself Borland C++ Builder 3 in 21 days>>
希望公司翻译出版的<<Borland C++ Builder 3自学培训教程>>有此问题
的标准答案(节选):
DLL中的MDI子窗体是个特例.假设有个C++ Builder应用程序,主窗体是MDI窗体,
如果使用DLL中的子窗体,则VCL会仍出异常.
要显示MDI子窗体, VCL检查Application对象的MainForm属性是否有效.如果Main
Form属性无效,则VCL扔出异常.DLL中也包含Application对象.由于DLL没有MainForm所以失败.
为解决这个问题,将DLL的Application对象赋予调用应用程序的Application.
但在DLL删除之前,还要恢复原Application.
第一步在DLL顶部放上
TApplication *DLLapp=0;
二,

void ShowMDIChildForm(TApplication *mainApp)
{
if(!DLLapp){
DLLapp=Application;
Application=mainApp;
}
TChildForm *child=new TChildForm(Application->MainForm);
Child->Show();
}
三,在DLL删除之前恢复Application.
在OnCloseQuery事件中执行下面函数
void ResetDLLApplication()
{
if(DLLapp)
Application=DLLapp;
}
OK,我的CBuilder程序本无问题,正如dwWang所说,调用了Freelibrary();
而我的Delphi动态调用是忘了写Freelibrary,却正常.
当然此法只适于Borland产品,若让非Borland产品调用则
TMyForm *Form=new TMyForm(NULL);
探讨出真知,把应用放于DLL有很多好处,但肯定还有其他问题,
以后再研究.














 
后退
顶部