DLLHUSK Sample: Dynamically Links the MFC Library
The DLLHUSK sample dynamically links the MFC library to applications and custom dynamic-link libraries (DLL) sharing the same class library code, thus reducing the total memory required by running multiple applications.
Dynamically linking to MFC 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.
Building and Running the Sample
To build and run the DLLHUSK sample
- Open the solution dllhusk.sln.
- On the Build menu, click Build.
- On the Debug menu, click Start Without Debugging.
The DLLHUSK solution 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 the Windows system directory.
DLLHUSK MFC Extension DLLs
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 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 multiple document interface (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 Mfcxx.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 provides the implementation for DLLHUSK's CListOutputFrame class. When the user chooses a diagnostic command by using the shortcut menu, the application creates a CListOutputFrame object and then sends diagnostic messages to the List Output window by calling CListOutputFrame::AddString.
All 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.
Additional DLLHUSK Features
DLLHUSK also illustrates:
- Splitting resources for a single application into multiple .rc files, which can be edited in the Visual C++ resource editor.
- Using two global diagnostic functions, AfxDoForAllClasses and AfxDoForAllObjects.
- Enumerating CDynLinkLibrary objects.
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::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
Note Some samples, such as this one, have not been modified to reflect the changes in the Visual C++ wizards, libraries, and compiler, but still demonstrate how to complete your desired task.