如何用Dll导出MFC的对话框类及其相应的资源以供其他程序使用?高分求救

guigui98 2005-07-23 03:15:06
我用MFC做了一个对话框类,其中包含其他的类对象和相关的事件与消息响应,现在要将该对话框类做成dll供其他的程序使用,请问我该怎么做?谢谢
...全文
307 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
guigui98 2005-07-23
  • 打赏
  • 举报
回复
其实我已经按照第三种方法做的,不同的是,我自己重载了一个对话框类的重载函数,dll编译没问题,但在客户程序调用上述dll输出的类时,一执行我重载的CMyDialog函数就报错。 同时,假如我输出的是一个showdialog()函数而不是一个类的话,该函数负责dlg.domodal的话,则程序能正常进行。
AntonlioX 2005-07-23
  • 打赏
  • 举报
回复
http://www.vckbase.com/document/viewdoc/?id=543
里面有源代码
AntonlioX 2005-07-23
  • 打赏
  • 举报
回复
==========1=======
从MFC扩展动态链接库中输出对话框似乎是很容易的.你仅需要将相应类用AFX_EXT_CLASS输出即可。如果你用一个应用程序和一个动态链接库建立或许会成功。但是如果你在应用程序和DLL中都插入更多的资源,你将会得到严重错误。
原因如下:

表示一个指定资源的正常途径是用它的ID。ID是一个用资源编辑器定义的整型常量。现在,假定你已有一个资源(是字符串)命名为ID_MY_TEXT.

CString strText;
strText.LoadString( ID_MY_TEXT );
afxDump << strText;

上述代码将字符串输出到调试窗口。有时你可能得到一个错误,而且它只发生在如果文本在一个MFC的扩展动态链接库里。错误的原因在于应用程序获取一个资源的途径。因为应用程序和动态链接库都有一个资源文件。不同的资源ID有可能一样(以为VC资源编辑器为每个模块确定ID的起始编号方式)。

你可能认为在你的应用程序里搜索一个资源的顺序是首先为应用程序,而后为你的DLL。我们需要改变搜索资源的顺序。

在本站有其他文章详细讲述了从DLL中输出对话框。但是它只能工作在正规的MFC动态链接库中。

我写了一个类(在DLL的MAIN和对话框中有一些改变),允许你在任何你喜欢的地方调用你的对话框,就象:

CMyApp::OnDLLDialog()
{
CDLLDialog dlg;
dlg.DoModal();
}
我写了一个简单的类,在类的构造函数中设置动态链接库的资源句柄,在析构函数中设置先前的句柄。

/////////////////////////////////////////////////////////////////////////////////////////////
// File ExtDllState.h
////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __EXTDLLSTATE_H__
#define __EXTDLLSTATE_H__

class CEXTDLLState
{
public:
CEXTDLLState();
~CEXTDLLState();
protected:
HINSTANCE m_hInstOld;
};

#endif
////////////////////////////////////////////////////////////////////////////////////////////
File ExtDllState.cpp
////////////////////////////////////////////////////////////////////////////////////////////
CEXTDLLState::CEXTDLLState()
{
m_hInstOld = AfxGetResourceHandle();
AfxSetResourceHandle(extensionDLL.hModule);
}

CEXTDLLState::~CEXTDLLState()
{
AfxSetResourceHandle(m_hInstOld);
}
//////////////////////////////////////////////////////////////////////////////////////

你可能看它很短小,但是却能做很多工作:复制上面的类代码到ExDllState.h和ExtDllState.cpp中,将两个文件放入公有的Include目录下,使得每个项目找到它。在你的DLL中,找到main源文件,你会看到类似下面的一些代码:

static AFX_EXTENSION_MODULE MY_DLL_NAMEDLL = { NULL, NULL };
用 "extensionDLL"替换该变量。放入下面的代码:

#include "EXTDLLState.h"
#include "ExtDllState.cpp"

在文件的其他地方寻找MY_DLL_NAMEDLL的事件,用extensionDLL替换它。事件只能在这个文件里发生,以为该变量是静态的。

现在,如果你想输出一个对话框,请进入COrresponding类的源文件里并包含EXTDLLState.h,重载函数DoModal()(最好使用ClassWizard),你将看到类似下面的代码:

int CMyDLLDlg::DoModal()
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::DoModal();
}

用"CEXTDLLState State;"替换TODO行,就象下面:

int CDLLDlgDlg::DoModal()
{
CEXTDLLState State;
return CDialog::DoModal();
}

你能在MFC扩展DLL中想存取资源的任何地方使用CEXTDLLState,而且总能得到正确的结果,我希望它能对你有所帮助。

==========2 =======
怎样从MFC扩展动态链结库(DLL)中显示一个对话框
程序员之家 作者:不详 日期:2002-8-16 21:52:00

--------------------------------------------------------------------------------

问:我在过去的几天中试着在DLL中定义的函数中显示一个对话框,可是已
经在DLL中定义好的对话框资源,在常规DLL调用时,我可以正常的显示出来,
为什么在扩展DLL中同样的资源我却不能显示.


答:当你在DLL中使用资源时,有些小细节需要注意,首先,在DLL运行时,
必须保存DLL的实例,可以通过AfxInitExtensionModule


static AFX_EXTENSION_MODULE extensionDLL;

extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(extensionDLL, hInstance))
return false;
}

return(true);
}

然后,每次使用DLL资源时,你必须改变资源的句柄,使其指向DLL,并保
存exe的资源,以便以后正确恢复


void get_DLL_resource(void)
{
/* this function changes the resource handle to that of the DLL */
//这个函数改变资源句柄使其指向DLL
if (resource_counter == 0)
{
save_hInstance = AfxGetResourceHandle();
AfxSetResourceHandle(extensionDLL.hModule);
}

resource_counter++;
}

接着你需要其它函数来恢复资源句柄


void reset_DLL_resource(void)
{
/* this function restores the resource handle set by
'get_DLL_resource()' */

if (resource_counter > 0)
resource_counter--;

if (resource_counter == 0)
AfxSetResourceHandle(save_hInstance);
}

接下来一点非常重要,只要有可能就必须恢复资源句柄,否则,你将会遇到许
多问题.原因是可执行文件必须重画工具条等等,比如说,如果用户移动DLL的
对话框,如果资源句柄仍然为DLL的资源,程序就崩溃了,我发现最好恢复句柄
的时机在对话框的OnInitDialog()中,这时对话框的模板等已经读出了.

=======3 ===========
在《MFC开发Windows 95/NT应用程序》中指出:  "一个扩展DLL只能与MFC采用动态联编方式链接并且只能被MFC应用程序使用。扩展DLLs能自由地将MFC派生类对象发到调用程序中,同时也能自由地从调用程序中接受MFC派生类对象。"  从字面上理解,应用程序要想使用在扩展DLL中的类,必须对扩展DLL进行动态联编。可是我采用静态联编,实现了该功能。具体步骤如正文所示。


   1.用AppWizard生成扩展DLLs:名为ExtDll. 2.选主菜单Insert/Resource/Dialog插入对话框:IDD_DIALOG1. 3.相应地用ClassWizard生成对话框类CDllDialog. 4.修改CDllDialog类声明: 从class CDllDialog : public CDialog 改为 class AFX_EXT_CLASS CDllDialog : public CDialog 5.将resource.h改名为Dllres.h 6.在DllDialog.h中加入: #include Dllres.h 7.编译生成ExtDll.dll和ExtDll.lib 8.用AppWizard生成应用程序RunExtDll,将ExtDll.dll、ExtDll.lib DllDialog.h拷入应用程序工作目录,在主菜单Project/Settings/Link 的Object/library modules中加入extdll.lib。 9.在MainFrm.cpp中加入#include "DllDialog.h"(如下顺序)#include "stdafx.h"#include "RunExtDll.h"#include "DllDialog.h"#include "MainFrm.h" 10.在CMainFrame的响应函数中加入:CDllDialog dlldlg;dlldlg.DoModal(); 至此,即可实现通过静态联编从扩展DLLS中输出Dialog类。[讨论] 1.与从新定位资源不同,此方法可以将不同的资源/类装入不同的DLL中。 2.注意到两者资源定义可能重复:比如: #define IDD_DIALOG1 129 请修改Dllres.h的相应定义。(本例不需要)

AntonlioX 2005-07-23
  • 打赏
  • 举报
回复
使用 extend MFC dll建立一个dll工程

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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