调用DLL 中的MDI子窗体,提示"Cannot create form.No MDI forms are currently active"

mimong_lin 2008-06-13 10:34:07
如果,我的程序结构是这样的,一个存放MDI Child 子窗体的DLL(DLLMDIChildPro.dll),一个管理这些MDI Child子窗体DLL的管理DLL(DLLMDIChildManagePro.dll),MDI主程序(DLLMDIChildTestPro.exe).程序结构就要求这样子,不能改变的.显示MDI Child子窗体的过程是这样的,MDI主程序中的一个MDI Child子窗体(在主程序里带的,不是DLL生成)调用管理DLL中的接口来显示MDI Child.

DLLMDIChildPro.dll的导出函数

extern "C" __declspec(dllexport)
bool GetReportFileInfo(ReportInfo& rptInfo)
{
rptInfo.formClass = __classid(TFormFirstDLLMDIChild);
rptInfo.ppForm = (TForm **)&FormFirstDLLMDIChild;
//rptInfo.reportTitle = std::string("第一个DLL MDI子窗体");
//rptInfo.reportType = std::string("测试报表");

return true;
}


DLLMDIChildManagePro.dll的导出函数

extern "C" __declspec(dllexport)
void ShowFirstMDIChild(TApplication* pApp)
{
if(g_SavedApp == NULL)
{
g_SavedApp = Application;
Application = pApp;
}

if(g_firstDLLMDIChildIns == NULL)
{
g_firstDLLMDIChildIns = ::LoadLibrary("DLLMDIChildPro.dll");
if(g_firstDLLMDIChildIns == NULL)
{
return ;
}
}

struct ReportInfo rptInfo;
GETREPORTFILEINFOFUNC GetInfo
= (GETREPORTFILEINFOFUNC)::GetProcAddress(g_firstDLLMDIChildIns, "_GetReportFileInfo");
if(GetInfo == NULL)
{
return ;
}
GetInfo(rptInfo);

if(rptInfo.ppForm == NULL)
{
return ;
}
if((*rptInfo.ppForm) == NULL)
{
Application->CreateForm(rptInfo.formClass, rptInfo.ppForm);
}
(*rptInfo.ppForm)->Show();
}


DLLMDIChildTestPro.exe中的调用代码

void __fastcall TFormDLLMDIChildUsage::btn1Click(TObject *Sender)
{
typedef void (*SHOWFIRSTMDICHILDFUNC)(TApplication* pApp);
SHOWFIRSTMDICHILDFUNC ShowFunc
= (SHOWFIRSTMDICHILDFUNC)::GetProcAddress(m_dllMDIChildMIns, "_ShowFirstMDIChild");
if(ShowFunc == NULL)
{
throw(Exception(Format("函数取址失败:%u", ARRAYOFCONST(((int)::GetLastError())))));
}
ShowFunc(Application);
}


Application->CreateForm(rptInfo.formClass, rptInfo.ppForm);
这个是在网上找到的内容,说是在调用DLL中的MDI Child子窗体的时候,需要从外部传入Application,在调试的时候,我查看传进来的Application的MainForm的FFormStyle,是2(fsMDIForm),但是在这一步调用的时,问题提示"Cannot create form.No MDI forms are currently active".

这究竟是什么问题呢?要怎么解决?
...全文
1009 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
我来看看CB 2008-06-13
  • 打赏
  • 举报
回复
关注。。。。。。
mimong_lin 2008-06-13
  • 打赏
  • 举报
回复
问题解决,是认识上的错误.
虽然知道DLL中的Application和MDI主程序中的Application是不同样的,在ShowForm有替换DLL中的Application.以为用GetFormClass后是在MDI主程序中调用Application->CreateForm,应该不关DLL中的Application的事,没想到它还是会去判断DLL中的那个Application.所以,需要在GetFormClass的时候,也替换DLL中的Application,才能解决问题.新的函数接口如下:

void GetFormClass(TApplication* pApp, struct FormClass& f)
{
if(g_SavedApp == NULL)
{
g_SavedApp = Application;
Application = pApp;
}

f.ppForm = (TForm **)&FormDLL;
f.formClass = __classid(TFormDLL);
}


这样就OK了.
mimong_lin 2008-06-13
  • 打赏
  • 举报
回复
经过调试发现,对于fsMDIChild的窗体,调用Application->CreateForm的时候,似乎需要CreateForm这个操作和fsMDIChild窗体在同一个模块中(同一个DLL或者EXE文件中,也就是同一个项目中),是否是这样子的呢?

请向前辈们求证一下.
本课程主要是针对ILRuntime设计一个独立的脚本热更新框,框架的优势:1.将代码热更脱离Assetbundle资源热更,独立的部分更适用于各种不同的框架。2.加快项目的逻辑更新,bug修复.(后期修bug,多数情况下并不用动到资源,只需要更新脚本代码,无需重走资源打包发布流程,大大提升效率)3.提供热更模式和正常开发模式的快速切换接口,可以让队友像平常一样去开发.4.不依赖市面上的任何AB框架,完全兼容市面上各种不同的AB框架.5.重点:希望通过它,帮助你学习、了解ILRuntime真正在项目的应用.框架的将提供以下这些接口,这些接口将从0开始,在Unity里将C#脚本编译成dll,然后将dll放到服务器上,再将dll下载下来,进行加载,到最后从Unity主工程调用热更新的代码逻辑.1.Create hotfixdll接口将热更部分的代码 编译成dll生成dll版本配置(MD5)2.更新对比接口本地跟服务器的dll进行版本对比3.下载热更dll下载dll本身的文件下载版本记录文件4.加载热更dll加载dll实例化:AppDomain初始化:注册跨域继承适配器注册委托适配器LitJson重定向调用性能优化(CLR绑定功能)调用热更接口Hotfix.HotfixApplication.Main 进入热更逻辑5.ILMonoBehaviour用于监听组件的生命周期,实际是桥接(调用)热更的逻辑AwakeStartEnableUpdateLateUpdate.......6.添加其他常用的库DOTweenLitJsonSpineGoogle.ProtobufTextAnimation可以根据上面的方式,自行添加依赖的库... 

13,825

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧