血本急求:将对话框放入 DLL 文件当中,在主程序中作为子窗口非模态显示,做完操作后,释放该 DLL 的方法
是这样的:小弟正在尝试MFC基于对话框的程序,将界面与逻辑分离的方法。也就是说,对于一个软件,将不同的功能模块,单独做成DLL,作为组件来加载,并且是动态使用这个DLL,...
是这样的:
小弟正在尝试 MFC 基于对话框的程序,将界面与逻辑分离的方法。
也就是说,对于一个软件,将不同的功能模块,单独做成 DLL,作为组件来加载,并且是动态使用这个 DLL,可随时加载、释放。
已经成功将两个对话框分别放入各自的DLL文件中,并且在主程序中作为子窗口非模态显示,能通过两个按钮,进行两个子对话框的切换
但是,当调用一个DLL ,显示其对话框以后,尝试释放另一个对话框所在的DLL,失败了。
一、下面是我的两个DLL:
1、在“DlgDllTest1.dll”中的实现函数中,导出函数:
extern "C" __declspec(dllexport) void ShowDlg()
{
// 获得父窗指针
HWND hWnd = ::FindWindow(NULL,_T("Main_Dlg"));
CWnd* cWnd = CWnd::FromHandle(hWnd);
// 如果没有子窗 testDlg1 的句柄,则创建,并显示
if( !theApp.testDlg1.m_hWnd )
theApp.testDlg1.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
::SetWindowText(theApp.testDlg1.m_hWnd,_T("TestDlg1"));
theApp.testDlg1.ShowWindow(SW_SHOW);
}
2、在“DlgDllTest2.dll”中的实现函数中,导出函数:
extern "C" __declspec(dllexport) void ShowDlg()
{
// 获得父窗指针
HWND hWnd = ::FindWindow(NULL,_T("Main_Dlg"));
CWnd* cWnd = CWnd::FromHandle(hWnd);
// 如果没有子窗 testDlg2 的句柄,则创建,并显示
if( !theApp.testDlg2.m_hWnd )
theApp.testDlg2.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
::SetWindowText(theApp.testDlg2.m_hWnd,_T("TestDlg2"));
theApp.testDlg2.ShowWindow(SW_SHOW);
}
二、下面是我在主程序(即父窗程序)中,根据按钮的ID号,集中处理了按钮的单击事件:
void CWADlgTestDlg::OnBtnClicked(UINT nBtnID)
{
// 先释放 DLL 模块句柄,
// hIns 是 CWADlgTestDlg 类的成员:public: HINSTANCE hIns;
// 并且在初始化函数OnInitDialog()中默认加载子窗口 testDlg1 所在的DLL:
// hIns = LoadLibrary(_T("DlgDllTest1.dll"));
// 各位请看,就是在下面这个地方,释放不成功,第一次点击按钮是成功的,
// 第二次就出异常了,意思就是,再次释放不成功
//if( hIns )
//FreeLibrary(hIns);
// 不管有没有显示子窗,先全部关闭
HWND hWnd1 = ::FindWindowEx(this->m_hWnd,NULL,NULL,_T("TestDlg1"));
HWND hWnd2 = ::FindWindowEx(this->m_hWnd,NULL,NULL,_T("TestDlg2"));
if( hWnd1 )
::CloseWindow(hWnd1);
if( hWnd2 )
::CloseWindow(hWnd2);
// 根据按钮ID号决定是显示哪个子对话框
switch(nBtnID)
{
case IDC_BUTTON1://点击按钮1,显示子对话框1
hIns = LoadLibrary(_T(".\\WAResDlg.dll"));
break;
case IDC_BUTTON2://点击按钮2,显示子窗2
hIns = LoadLibrary(_T(".\\WAEditDlg.dll"));
break;
}
typedef void (*pShowDlg)();
pShowDlg ShowDlg = (pShowDlg)GetProcAddress(hIns, "ShowDlg");
ShowDlg();
}
那么,我要怎么样才能实现这样的效果:
无论关闭哪个子 对话框,都能释放该子对话框所在的 DLL ?
虽然,不加 FreeLibrary(hIns);这一句来释放任何 DLL ,是可以达到子对话框的切换,而且没有异常,但是我的目的就是,随时可以随心所欲的加载我想要的子对话框的 DLL,不然的话,何必将子对话框放入 DLL,直接在主程序中新建对话框类,还轻松得多。
敬请各位前辈、高手,帮帮小弟,如果解决,分不是问题!
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
非常感谢 四位前辈的指导,三楼“何处淬吴钩”这位前辈,您告诉我的方法,用WM_CLOSE关闭不掉窗口,我已经证明不是子窗口句柄错了,但就是关闭不掉,如果用::DestroyWindow();,发生了异常,不如如何调试,很是晕乎。
四楼“qiujiejia” 这位前辈,您的方法,虽然复杂了点,但是有例子程序。看得出来,这是您亲自写了个程序,帮我验证和测试,虽然我已经在其他地方找到解决的方法,并且方法极为简单,还解决了资源释放的问题。但是,您辛苦了,亲自写程序,谢谢!
这样吧,四楼前辈的知道级别没有三楼前辈的高,就将此分酬谢给四楼前辈用于升级吧,但为了公平起见,本来三楼前辈已经指出了我的程序的“要害”之处,也要感谢的,所以,我结贴的时候就不加分了。
再次感谢各位的指导! 展开
小弟正在尝试 MFC 基于对话框的程序,将界面与逻辑分离的方法。
也就是说,对于一个软件,将不同的功能模块,单独做成 DLL,作为组件来加载,并且是动态使用这个 DLL,可随时加载、释放。
已经成功将两个对话框分别放入各自的DLL文件中,并且在主程序中作为子窗口非模态显示,能通过两个按钮,进行两个子对话框的切换
但是,当调用一个DLL ,显示其对话框以后,尝试释放另一个对话框所在的DLL,失败了。
一、下面是我的两个DLL:
1、在“DlgDllTest1.dll”中的实现函数中,导出函数:
extern "C" __declspec(dllexport) void ShowDlg()
{
// 获得父窗指针
HWND hWnd = ::FindWindow(NULL,_T("Main_Dlg"));
CWnd* cWnd = CWnd::FromHandle(hWnd);
// 如果没有子窗 testDlg1 的句柄,则创建,并显示
if( !theApp.testDlg1.m_hWnd )
theApp.testDlg1.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
::SetWindowText(theApp.testDlg1.m_hWnd,_T("TestDlg1"));
theApp.testDlg1.ShowWindow(SW_SHOW);
}
2、在“DlgDllTest2.dll”中的实现函数中,导出函数:
extern "C" __declspec(dllexport) void ShowDlg()
{
// 获得父窗指针
HWND hWnd = ::FindWindow(NULL,_T("Main_Dlg"));
CWnd* cWnd = CWnd::FromHandle(hWnd);
// 如果没有子窗 testDlg2 的句柄,则创建,并显示
if( !theApp.testDlg2.m_hWnd )
theApp.testDlg2.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
::SetWindowText(theApp.testDlg2.m_hWnd,_T("TestDlg2"));
theApp.testDlg2.ShowWindow(SW_SHOW);
}
二、下面是我在主程序(即父窗程序)中,根据按钮的ID号,集中处理了按钮的单击事件:
void CWADlgTestDlg::OnBtnClicked(UINT nBtnID)
{
// 先释放 DLL 模块句柄,
// hIns 是 CWADlgTestDlg 类的成员:public: HINSTANCE hIns;
// 并且在初始化函数OnInitDialog()中默认加载子窗口 testDlg1 所在的DLL:
// hIns = LoadLibrary(_T("DlgDllTest1.dll"));
// 各位请看,就是在下面这个地方,释放不成功,第一次点击按钮是成功的,
// 第二次就出异常了,意思就是,再次释放不成功
//if( hIns )
//FreeLibrary(hIns);
// 不管有没有显示子窗,先全部关闭
HWND hWnd1 = ::FindWindowEx(this->m_hWnd,NULL,NULL,_T("TestDlg1"));
HWND hWnd2 = ::FindWindowEx(this->m_hWnd,NULL,NULL,_T("TestDlg2"));
if( hWnd1 )
::CloseWindow(hWnd1);
if( hWnd2 )
::CloseWindow(hWnd2);
// 根据按钮ID号决定是显示哪个子对话框
switch(nBtnID)
{
case IDC_BUTTON1://点击按钮1,显示子对话框1
hIns = LoadLibrary(_T(".\\WAResDlg.dll"));
break;
case IDC_BUTTON2://点击按钮2,显示子窗2
hIns = LoadLibrary(_T(".\\WAEditDlg.dll"));
break;
}
typedef void (*pShowDlg)();
pShowDlg ShowDlg = (pShowDlg)GetProcAddress(hIns, "ShowDlg");
ShowDlg();
}
那么,我要怎么样才能实现这样的效果:
无论关闭哪个子 对话框,都能释放该子对话框所在的 DLL ?
虽然,不加 FreeLibrary(hIns);这一句来释放任何 DLL ,是可以达到子对话框的切换,而且没有异常,但是我的目的就是,随时可以随心所欲的加载我想要的子对话框的 DLL,不然的话,何必将子对话框放入 DLL,直接在主程序中新建对话框类,还轻松得多。
敬请各位前辈、高手,帮帮小弟,如果解决,分不是问题!
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
非常感谢 四位前辈的指导,三楼“何处淬吴钩”这位前辈,您告诉我的方法,用WM_CLOSE关闭不掉窗口,我已经证明不是子窗口句柄错了,但就是关闭不掉,如果用::DestroyWindow();,发生了异常,不如如何调试,很是晕乎。
四楼“qiujiejia” 这位前辈,您的方法,虽然复杂了点,但是有例子程序。看得出来,这是您亲自写了个程序,帮我验证和测试,虽然我已经在其他地方找到解决的方法,并且方法极为简单,还解决了资源释放的问题。但是,您辛苦了,亲自写程序,谢谢!
这样吧,四楼前辈的知道级别没有三楼前辈的高,就将此分酬谢给四楼前辈用于升级吧,但为了公平起见,本来三楼前辈已经指出了我的程序的“要害”之处,也要感谢的,所以,我结贴的时候就不加分了。
再次感谢各位的指导! 展开
3个回答
展开全部
你的对话框程序应该这样做:
1.当对话框按关闭,“确定”,取消 时 要摧毁窗口。
void CMyDlg::OnClose()
{
DestroyWindow();
}
void CMyDlg::OnBnClickedOk()
{
OnOK();
DestroyWindow();
}
void CMyDlg::OnBnClickedCancel()
{
OnCancel();
DestroyWindow();
}
2.添加虚函数PostNcDestroy ,使窗口关闭时可以自动删除自己。
因为你前面用了theApp.testDlg2.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
用创建就必须有删除。
#define WM_USERDEFMSG WM_USER + 101 //自定义消息
void CMyDlg::PostNcDestroy()
{
//删除自己
delete this;
//向主窗口发送自定义消息,告知对话框已关闭,可以调用FreeLibrary
::PostMessage(::FindWindow(NULL,"Demo"),WM_USERDEFMSG,NULL,NULL);
CDialog::PostNcDestroy();
}
3.主窗口添加自定义消息。
捕获来自子对话框的消息,并调用FreeLibrary
//自定义消息
LRESULT CDemoDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
HMODULE hModule = GetModuleHandle(_T("mydll.dll"));
ASSERT(hModule);
if (hModule)
FreeLibrary(hModule);
return 0;
}
例子下载:
http://cid-3ba16e78a53d2d3d.office.live.com/self.aspx/VC/Free-Dll-Dlg.zip(请不要使用下载工具)
阿弥陀佛!愿顺利!
1.当对话框按关闭,“确定”,取消 时 要摧毁窗口。
void CMyDlg::OnClose()
{
DestroyWindow();
}
void CMyDlg::OnBnClickedOk()
{
OnOK();
DestroyWindow();
}
void CMyDlg::OnBnClickedCancel()
{
OnCancel();
DestroyWindow();
}
2.添加虚函数PostNcDestroy ,使窗口关闭时可以自动删除自己。
因为你前面用了theApp.testDlg2.Create(MAKEINTRESOURCE(IDD_DIALOG1),cWnd);
用创建就必须有删除。
#define WM_USERDEFMSG WM_USER + 101 //自定义消息
void CMyDlg::PostNcDestroy()
{
//删除自己
delete this;
//向主窗口发送自定义消息,告知对话框已关闭,可以调用FreeLibrary
::PostMessage(::FindWindow(NULL,"Demo"),WM_USERDEFMSG,NULL,NULL);
CDialog::PostNcDestroy();
}
3.主窗口添加自定义消息。
捕获来自子对话框的消息,并调用FreeLibrary
//自定义消息
LRESULT CDemoDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
HMODULE hModule = GetModuleHandle(_T("mydll.dll"));
ASSERT(hModule);
if (hModule)
FreeLibrary(hModule);
return 0;
}
例子下载:
http://cid-3ba16e78a53d2d3d.office.live.com/self.aspx/VC/Free-Dll-Dlg.zip(请不要使用下载工具)
阿弥陀佛!愿顺利!
展开全部
你closewindow用在这里有问题。可以换为destroywindow,不过最好是发送WM_CLOSE消息。
你加载dll并调用其中资源后,必须先释放掉你使用的资源,才能freelibray。
反应在你的这个程序里,你每个dll都创建了一个线程,所以你需要一个句柄来保存当前在dll中创建的窗口,先要关闭掉窗口(WM_CLOSE)才能freelibrary
你加载dll并调用其中资源后,必须先释放掉你使用的资源,才能freelibray。
反应在你的这个程序里,你每个dll都创建了一个线程,所以你需要一个句柄来保存当前在dll中创建的窗口,先要关闭掉窗口(WM_CLOSE)才能freelibrary
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询