c++builder6运行时错误:cannot create form no mdi form are currently active

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

【全新正版】C语言从入门到精通c语言程序设计c++电脑编程入门零基础自学轻松学计算机c语言入门软件程序员开发教程教材书籍
全新版【赠:电子书实战案例+VC6.0安装包】 | 月销量2075件
优惠价28.8元
原价¥98

淘口令:

¥zH2BX9DySiX¥
 

我的程序结构是这样的,一个存放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的导出函数

C/C++ code

?

1
2
3
4
5
6
7
8
9
10
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的导出函数

C/C++ code

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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中的调用代码

C/C++ code

?

1
2
3
4
5
6
7
8
9
10
11
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”.

这究竟是什么问题呢?要怎么解决?

问题解决,是认识上的错误.
虽然知道DLL中的Application和MDI主程序中的Application是不同样的,在ShowForm有替换DLL中的Application.以为用GetFormClass后是在MDI主程序中调用Application->CreateForm,应该不关DLL中的Application的事,没想到它还是会去判断DLL中的那个Application.所以,需要在GetFormClass的时候,也替换DLL中的Application,才能解决问题.新的函数接口如下:

C/C++ code

?

1
2
3
4
5
6
7
8
9
10
11
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了.


No MDI forms are currently active 的解决方法

描述一下运行环境,几个存放MDI Child 子窗体的DLL和一个管理这些子窗体MDI主程序.在主程序中动态调入DLL子窗体

首先,DLL中的Application和MDI主程序中的Application是不同样的。要将MDI主程序中的Application替换掉DLL中的Application

其次,在工程->属性->packages->Runtime packages->勾选Build with runtime packages,重新编译。这个也是最让人晕的


好像必须将主程序的Application.Handle传递到DLL中的Application.Handle,因为DLL中的Application.Handle=0,所以直接创建时会报没有MDI主窗口的错误。


一般的都是在DLL初始化的时候把EXE中的Application, Screen
两个对象替换DLL中的对应的对象, 在DLL释放的时候再还原.

© 版权声明
THE END
喜欢就支持一下吧,技术咨询可以联系QQ407933975
点赞0
分享
评论 抢沙发