Module States of a Regular DLL Dynamically Linked to MFC
The new home for Visual Studio documentation is Visual Studio 2017 Documentation on docs.microsoft.com.
The latest version of this topic can be found at Module States of a Regular DLL Dynamically Linked to MFC.
The ability to dynamically link a regular DLL to the MFC DLL allows some configurations that are very complicated. For example, a regular DLL and the executable that uses it can both dynamically link to the MFC DLL and to any extension DLLs.
This configuration poses a problem with regard to the MFC global data, such as the pointer to the current
CWinApp object and handle maps.
Before MFC version 4.0, this global data resided in the MFC DLL itself and was shared by all the modules in the process. Because each process using a Win32 DLL gets its own copy of the DLL's data, this scheme provided an easy way to track per-process data. Also, because the AFXDLL model presumed that there would be only one
CWinApp object and only one set of handle maps in the process, these items could be tracked in the MFC DLL itself.
But with the ability to dynamically link a regular DLL to the MFC DLL, it is now possible to have two or more
CWinApp objects in a process — and also two or more sets of handle maps. How does MFC keep track of which ones it should be using?
The solution is to give each module (application or regular DLL) its own copy of this global state information. Thus, a call to AfxGetApp in the regular DLL returns a pointer to the
CWinApp object in the DLL, not the one in the executable. This per-module copy of the MFC global data is known as a module state and is described in MFC Tech Note 58.
The MFC common window procedure automatically switches to the correct module state, so you do not need to worry about it in any message handlers implemented in your regular DLL. But when your executable calls into the regular DLL, you do need to explicitly set the current module state to the one for the DLL. To do this, use the AFX_MANAGE_STATE macro in every function exported from the DLL. This is done by adding the following line of code to the beginning of functions exported from the DLL: