
Sharing Resources and Classes
Exporting resources is done through a resource list. Each application contains a singly linked list of CDynLinkLibrary objects. When looking for a resource, most of the standard MFC implementations that load resources look first at the current resource module (AfxGetResourceHandle) and if the resource is not found walk the list of CDynLinkLibrary objects attempting to load the requested resource.
Walking the list has the disadvantages that it is slightly slower and requires managing resource ID ranges. It has the advantage that a client application that links to several extension DLLs can use any DLL-provided resource without having to specify the DLL instance handle. AfxFindResourceHandle is an API used for walking the resource list to look for a given match. It takes the name and type of a resource and returns the resource handle where it was first found (or NULL).
If you do not want to walk the list and only load resources from a specific place, use the functions AfxGetResourceHandle and AfxSetResourceHandle to save the old handle and set the new handle. Be sure to restore the old resource handle before you return to the client application. For an example of using this approach to explicitly load a menu, see Testdll2 .cpp in the MFC sample DLLHUSK.
Dynamic creation of MFC objects given an MFC name is similar. The MFC object deserialization mechanism needs to have all of the CRuntimeClass objects registered so that it can reconstruct by dynamically creating C++ objects of the required type based on what was stored earlier.
In the case of the MFC sample DLLHUSK, the list looks something like:
head -> DLLHUSK.EXE - or - DLLHUSK.EXE
| |
TESTDLL2.DLL TESTDLL2.DLL
| |
TESTDLL1.DLL TESTDLL1.DLL
| |
MFCOxxD.DLL |
| |
MFCDxxD.DLL |
| |
MFCxxD.DLL MFCxx.DLL
where xx is the version number; for example, 42 represents version 4.2.
The MFCxx.dll is usually last on the resource and class list. MFCxx.dll includes all of the standard MFC resources, including prompt strings for all of the standard command IDs. Placing it at the end of the list allows DLLs and the client application itself not to have their own copy of the standard MFC resources, but to rely on the shared resources in the MFCxx.dll instead.
Merging the resources and class names of all DLLs into the client application's name space has the disadvantage of requiring you to be careful with what IDs or names you pick.
The DLLHUSK sample manages the shared resource name space by using multiple header files.
If your MFC extension DLL needs to maintain extra data for each application, you can derive a new class from CDynLinkLibrary and create it in DllMain. When running, the DLL can check the current application's list of CDynLinkLibrary objects to find the one for that particular extension DLL.
What do you want to do?
What do you want to know more about?