如何调用动态库中的MDI子窗体(FormStyle=fsMdiChild)? 急......(50分)

  • 主题发起人 主题发起人 VeryCoolBoy
  • 开始时间 开始时间
V

VeryCoolBoy

Unregistered / Unconfirmed
GUEST, unregistred user!
DLL中包含一窗体变量Form1:TForm,<br><br>并有如下一个函数:<br><br>function ShowDllForm(AHandle:THandle;ACaption:String):Longint;stdcall;<br>begin<br>&nbsp; Application.Handle:=AHandle;<br>&nbsp; if not Assigned(Form1) then<br>&nbsp; &nbsp; Form1:=TForm1.Create(Application);<br>&nbsp; Result:=Longint(Form1);<br>&nbsp; Form1.Caption := ACaption;<br>&nbsp; Form1.Show;<br>end;<br><br>如果 TForm1 的FormStyle=fsNormal 则系统能正常运行,而为fcMdiChild就出错,请问如何解决。<br><br>我这可是我一个项目的节骨眼儿啊,十万火急,忘大家可怜可怜我啊,知道就马上告诉我吧
 
我很着急啊,为什么如此冷清?
 
不要来了就走,给点提示好不好,我很急呀!
 
光传递 Application 的 Handle 是不够的,需要传递整个 Application 对象。这样:<br><br>Library ShowFrmdll;<br>uses<br>&nbsp; ...<br>&nbsp; Unit1 in 'Unit1.pas' {Form1};<br><br>var<br>&nbsp; DLLApp: TApplication;<br><br>function ShowDllForm(App:TApplication; ACaption:String):Longint;stdcall;<br>begin<br>&nbsp; <br>&nbsp; Application := App;<br><br>&nbsp; if not Assigned(Form1) then<br>&nbsp; &nbsp; Form1:=TForm1.Create(Application);<br>&nbsp; Result:=Longint(Form1);<br>&nbsp; Form1.Caption := ACaption;<br>&nbsp; Form1.Show;<br>end;<br><br>procedure DLLUnloadProc(Reason : Integer);<br>begin<br>&nbsp; if Reason = DLL_PROCESS_DETACH then Application := DLLApp;//恢复<br>end;<br><br>exports<br>&nbsp; ShowDllForm;<br><br>begin<br>&nbsp; DLLApp := Application; //保存 DLL 中初始的 Application 对象<br>&nbsp; DLLProc := @DLLUnloadProc; &nbsp; &nbsp; //保证 DLL 卸载时恢复原来的 Application<br>end.<br><br>要注意的是,创建的窗体被释放后再卸载 DLL。
 
唉,用PAckage不更好吗
 
谢谢bbkxjy,另外想请教djdsz,请问您所说的PAckage是指什么,能否详细说明?
 
就是将窗体放在包中,然后动态加载包
 
bbkxjy,照您的方法已将问题解决,但是目前尚存在一些小毛病:<br>一、MDI子窗体最大化后不能在菜单中显示还原、最小化和关闭按钮。<br>二、ActionList中定义的功能键完全不响应程序。<br>请问是否可以改善?
 
to VeryCoolBoy:<br>&nbsp; 没有啊,当 MainMenu 和 ActionList 都在 MDI 主窗口中时,我试了没问题啊?
 
to bbkxjy:<br>&nbsp; 我指的是MDI子窗口上的ActionList无响应,麻烦你再试一下
 
VeryCoolBoy:<br>&nbsp; 我试过了,确实有问题。跟踪了很久,问题关系到 TApplication.IsKeyMsg 函数中调用的<br>FindControl 函数的实现。由于主 exe 和加载的 dll 的 HInstance 值的不同,对于主 exe<br>中创建的 WinControl 窗口, FindControl 可以返回正确的值,而对于 dll 中创建的则总<br>返回 0。一个解决方法是这样的,把 Controls.pas 中 IniControls 过程中的这句话:<br>ControlAtom := GlobalAddAtom(StrFmt(AtomText, 'ControlOfs%.8X%.8X', <br>&nbsp; [HInstance, GetCurrentThreadID]);<br>改成 :<br>ControlAtom := GlobalAddAtom(StrFmt(AtomText, 'ControlOfs%.8X%.8X', <br>&nbsp; [GetCurrentProcessID, GetCurrentThreadID]);<br>另外,如果能在 DllProc 中将 Dll 的 HInstance 设成与主 exe 的 HInstance 一致也行,<br>但还未想到如何将这个值传递给 Dll。<br>
 
接受答案了.
 
后退
顶部