This article was previously published under Q150121
The wrong resource is loaded when CBitmap::LoadBitmap, CMenu::LoadMenu,CString::LoadString or any other MFC resource-loading function is called inan MFC extension DLL (AFXDLL). In some cases, a resource in the applicationis loaded instead of the appropriate resource in the extension DLL.
When a resource in the application or another extension DLL gets loadedinstead of a resource in the current extension DLL, the cause is usuallyimproper resource management. An MFC application and all of its extensionDLLs are one global chain of resources. If there are multiple resourceswith the same ID value in any of the modules in the chain, MFC uses thefirst resource it finds with the desired ID value. The first resource isoften found in the application, which is searched before any of theextension DLLs.
Change the ID values of any resources that conflict so they are unique inboth the application and any extension DLL that the application uses. Thesevalues are stored in the Resource.h file for each project and can bemodified in the Resource Editor or AppStudio with the Resource Symbolscommand.
To ensure that modules do not use conflicting symbol values, reservedifferent ranges of ID values for each module in the 1 through 0x6FFFFrange. Set the _APS_NEXT_RESOURCE_VALUE definition in the Resource.h filefor each module to the low end of that module's range before creating anyresources. The Resource Editor uses this symbol to determine the ID valueof the next resource created.
This technique is documented in MFC Technical Note 35 and in the DLLHUSKsample included with Visual C++.
This behavior is by design.
In .exe or .dll files that link to MFC dynamically, MFC resource-loadingfunctions call AfxFindResourceHandle() to obtain the handle of themodule where a resource is located. AfxFindResourceHandle() searches forresources by type and symbol value in:
The module returned by AfxGetResourceHandle(). This is usually the application.
The extension DLLs through the chain of CDynLinkLibrary objects.
Any language-specific resource DLLs.
Any attached MFC system DLLs (MFCxx.dll, for example).
NOTE: Some 16-bit MFC resource loading functions do not callAfxFindResourceHandle(), but instead use the value returned fromAfxCurrentResourceHandle().
Each extension DLL creates, initializes, and then passes a CDynLinkLibraryobject to AfxInitExtensionModule() that places the DLL in the resourcechain. AfxTermExtensionModule() removes the DLL from the chain when the DLLis detached from the application.
A benefit of this design is that MFC automatically locates a resource foran application or extension DLL, even if that resource is located in adistant extension DLL or the application itself. All resources in theprocess are chained, so ID values are passed between DLLs and theapplication and the proper resources are loaded. A disadvantage is thatthere are no duplicate ID values between any of the extension DLLs or theapplication that uses them.
To set the default location where AfxFindResourceHandle() first checks fora resource, use AfxSetResourceHandle(). Because AfxFindResourceHandle()first checks the handle set by AfxSetResourceHandle(), it can be used tocircumvent the chain and load a resource from one particular DLL orapplication. The resource handle is restored to its original valueimmediately after loading the resources. The current default resourcehandle is found with AfxGetResourceHandle().
The DLLHUSK sample included with Visual C++ also illustrates thistechnique. In Testdll2.cpp, CListOutputFrame::Create() sets the resourcehandle to the module handle stored in the AFX_EXTENSION_MODULE structureextension DLL. This structure is initialized with the module handle when itis passed to the CDynLinkLibrary constructor in InitTestDLL2().
For more information on:
Extension DLLs, see the MFC Technical Note 33 and the DLLHUSK sample.
Resource management in projects, see Technical Note 35.