DLLHUSK: Dynamically Links the MFC Library

Click to open or copy the DLLHUSK project files.

DLLHUSK dynamically links the Microsoft Foundation Class Library (MFC) to applications and custom dynamic-link libraries (DLLs) sharing the same class library code, thus reducing the total memory required by running multiple applications.

Dynamically linking to the class library also offers other possible application architectures in which part of the application is implemented in a custom DLL, and both the application and the custom DLL share the MFC DLL (Mfcxx.dll). A custom DLL that shares framework functionality with an application is called an "MFC extension DLL." 

DLLHUSK demonstrates MFC extension DLLs with class exports. C++ classes in the DLLs (Testdll1.dll and Testdll2.dll) are exported using the AFX_EXT_CLASS macro. The first MFC Extension DLL (TESTDLL1) is one in which all C++ class interfaces of the custom DLL are accessed only by the framework, not directly by the application. The custom DLL exports only extern "C" functions to the application. The custom DLL does not need to export the functions of classes derived from framework classes. All calls from the framework to derived classes in the custom DLL are resolved via the C++ virtual function mechanism.

The second MFC Extension DLL (TESTDLL2) is one in which some C++ class interfaces of the custom DLL are exported to and accessed directly by the application.

Testdll1.dll

Testdll1.dll provides the implementation for DLLHUSK's document and view classes for both document types — the TEXT document type and the HELLO document type. The Dllhusk.exe implements the MDI frame window class, and the framework implements the MDI child window class (CMDIChildWnd). Two document template objects establish the associations among CTextDoc, CMDIChildWnd, and CEditView and among CDummyDoc, CMDIChildWnd, and CHelloView. DLLHUSK therefore illustrates that the framework can coordinate the relationships among framework-defined objects, even though the classes for those objects are implemented in the application, the custom (MFC extension) DLL, and the framework's Mfc42.dll.

TESTDLL1 actually calls the application object's AddDocTemplate member function twice to register the two document template objects. It does so in the implementation of TESTDLL1's InitTestDLL1 function, which is the only function that TESTDLL1 exports. This function is declared with extern "C" so that the DLLHUSK application can call it as a stand-alone C function.

The Testdll1.h header file (added as a #include by Dllhusk.cpp) includes not only the declaration of InitTestDLL1, but also the declarations of TESTDLL1's classes. Dllhusk.cpp refers directly to only the InitTestDLL1 function. Indirectly, however, DLLHUSK uses the document and view classes implemented in Testdll1.dll.

Testdll2.dll

Testdll2.dll provides the implementation for DLLHUSK's CListOutputFrame class. When the user chooses a diagnostic command by using the right-mouse-click pop-up menu, the application creates a CListOutputFrame object and then sends diagnostic messages to the List Output window by calling CListOutputFrame::AddString.

All the public member functions of CListOutputFrame are exported in the Testdll2.def file. The exports include not only AddString but also the public CListOutputFrame constructor and destructor.

It is more difficult to implement an MFC extension DLL that exports class member functions than one that exports only C functions. This is true particularly because you must manually add the C++ name-decorated function exports to the DLL's .def file. A technique for doing so is explained in Technical Note 33.

DLLHUSK also illustrates:

The DLLHUSK makefile builds both the Dllhusk.exe application and the two DLLs (TESTDLL1.DLL and TESTDLL2.DLL) to which the application is dynamically linked. DLLHUSK requires MFCxx.DLL or MFCxxD.DLL at run time. These DLLs are installed by default in your Microsoft Windows system directory.

This sample demonstrates the following keywords:

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::Enable3dControls; 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