DLLHUSK 示例:动态链接 MFC 库

更新:2007 年 11 月

DLLHUSK 示例将 MFC 库动态链接到共享相同类库代码的应用程序和自定义动态链接库 (DLL),从而减少运行多个应用程序所需的总内存。

动态链接到 MFC 还提供了其他可能的应用程序结构,使应用程序的一部分在自定义 DLL 中实现,并且应用程序和自定义 DLL 共享 MFC DLL (Mfcxx.dll)。与应用程序共享框架功能的自定义 DLL 称为 MFC 扩展 DLL。

安全说明:

提供该示例代码是为了阐释一个概念,并不代表着最安全的编码实践,因此不应在应用程序或网站中使用该示例代码。对于超出本示例代码的预期用途以外的使用所造成的偶然或继发性损失,Microsoft 不承担任何责任。

获取示例和安装示例的说明:

  • 在 Visual Studio 的“帮助”菜单上,单击“示例”。

    有关更多信息,请参见定位示例文件

  • 示例的最新版本和完整列表可以从 Visual Studio 2008 Samples page(Visual Studio 2008 示例页面)联机获取。

  • 还可以在计算机的硬盘上查找示例。默认情况下,示例和自述文件将复制到 \Program Files\Visual Studio 9.0\Samples\ 下的文件夹中。对于 Visual Studio 速成版,所有示例都位于联机位置。

生成并运行示例

生成并运行 DLLHUSK 示例

  1. 打开解决方案 dllhusk.sln。

  2. 在“生成”菜单中单击“生成”。

  3. 在“调试”菜单中,单击“开始执行(不调试)”。

DLLHUSK 解决方案同时生成 Dllhusk.exe 应用程序以及该应用程序动态链接到的两个 DLL(TESTDLL1.DLL 和 TESTDLL2.DLL)。DLLHUSK 在运行时需要 MFCxx.DLL 或 MFCxxD.DLL。这些 DLL 在默认情况下安装在 Windows 系统目录中。

DLLHUSK MFC 扩展 DLL

DLLHUSK 说明了带有类导出的 MFC 扩展 DLL。DLL(Testdll1.dll 和 Testdll2.dll)中的 C++ 类通过 AFX_EXT_CLASS 宏导出。在第一个 MFC 扩展 DLL (TESTDLL1) 中,自定义 DLL 的所有 C++ 类接口仅由框架访问,而不是直接由应用程序访问。自定义 DLL 只向应用程序导出 extern“C”函数。自定义 DLL 不需要导出从框架类派生的类的函数。自定义 DLL 中从框架到派生类的所有调用都通过 C++ 虚拟函数机制来解析。

在第二个 MFC 扩展 DLL (TESTDLL2) 中,自定义 DLL 的某些 C++ 类接口被导出到应用程序并直接由应用程序访问。

Testdll1.dll

Testdll1.dll 为两种文档类型(TEXT 文档类型和 HELLO 文档类型)提供 DLLHUSK 的文档和视图类的实现。Dllhusk.exe 实现 MDI 框架窗口类,而框架实现多文档界面 (MDI) 子窗口类 (CMDIChildWnd)。两个文档模板对象在 CTextDoc、CMDIChildWndCEditView 之间和 CDummyDoc、CMDIChildWnd 与 CHelloView 之间建立关联。DLLHUSK 因此阐释了框架可以协调框架定义的对象之间的关系,即使这些对象的类是在应用程序、自定义(MFC 扩展)DLL 和框架的 Mfcxx.dll 中实现的。

TESTDLL1 实际上调用两次应用程序对象的 AddDocTemplate 成员函数来注册两个文档模板对象。这是在 TESTDLL1 的 InitTestDLL1 函数的实现中完成的,该函数是 TESTDLL1 导出的唯一函数。InitTestDLL1 函数由 extern“C”声明,以便 DLLHUSK 应用程序可以将其作为独立的 C 函数来调用。

Testdll1.h 头文件(由 Dllhusk.cpp 作为 #include 添加)不仅包含 InitTestDLL1 的声明,还包含 TESTDLL1 的类声明。Dllhusk.cpp 仅直接引用 InitTestDLL1 函数。但 DLLHUSK 间接地使用在 Testdll1.dll 中实现的文档和视图类。

Testdll2.dll

Testdll2.dll 提供 DLLHUSK 的 CListOutputFrame 类的实现。当用户通过使用快捷菜单选择诊断命令时,应用程序创建 CListOutputFrame 对象,然后通过调用 CListOutputFrame::AddString 将诊断消息发送到“列表输出”窗口。

CListOutputFrame 的所有公共成员函数都在 Testdll2.def 文件中导出。该导出不仅包括 AddString,还包括公共 CListOutputFrame 构造函数和析构函数。

实现导出类成员函数的 MFC 扩展 DLL 比实现只导出 C 函数的 MFC 扩展 DLL 困难。之所以会这样,主要是因为必须手动将 C++ 名称修饰函数导出添加到 DLL 的 .def 文件。技术说明 33 说明了具体的做法。

其他 DLLHUSK 功能

DLLHUSK 还阐释:

  • 将单个应用程序的资源拆分为多个 .rc 文件,这些文件可以在 Visual C++ 资源编辑器中进行编辑。

  • 使用两个全局诊断函数 AfxDoForAllClassesAfxDoForAllObjects

  • 枚举 CDynLinkLibrary 对象。

关键字

此示例说明以下关键字:

AfxDoForAllClasses;AfxDoForAllObjects;AfxGetApp;AfxGetResourceHandle;AfxMessageBox;AfxSetResourceHandle;AfxThrowMemoryException;CCmdUI::SetCheck;CColorDialog::DoModal;CColorDialog::GetColor;CDC::DrawText;CDC::SetBkColor;CDC::SetTextColor;CDialogBar::Create;CDocTemplate::GetDocString;CEditView::SerializeRaw;CFrameWnd::LoadFrame;CListBox::AddString;CListBox::Create;CListBox::GetCount;CListBox::GetText;CListBox::GetTextLen;CListBox::ResetContent;CListBox::SetCurSel;CMDIChildWnd::Create;CMenu::GetSubMenu;CMenu::LoadMenu;CMenu::TrackPopupMenu;CObject::AssertValid;CObject::Dump;CObject::Serialize;CStatusBar::Create;CStatusBar::SetIndicators;CToolBar::Create;CToolBar::LoadBitmap;CToolBar::SetButtons;CView::OnDraw;CWinApp::AddDocTemplate;CWinApp::InitInstance;CWinApp::LoadStdProfileSettings;CWinApp::OnFileNew;CWinApp::OpenDocumentFile;CWnd::GetClientRect;CWnd::GetCurrentMessage;CWnd::GetFont;CWnd::Invalidate;CWnd::OnCreate;CWnd::OnNcRButtonDown;CWnd::OpenClipboard;CWnd::SetFont;CWnd::ShowWindow;CWnd::UpdateWindow;CloseClipboard;EmptyClipboard;GetModuleFileName;GetSysColor;GlobalAlloc;GlobalLock;LOWORD;RGB;SetClipboardData;lstrlen;wsprintf

说明:

某些示例(如此示例)尚未经过修改以反映 Visual C++ 向导、库和编译器中所做的更改,但仍演示了如何完成所需的任务。

请参见

其他资源

MFC 示例