MFC Loads Wrong Resource in Extension DLL

本文详细介绍了在使用MFC扩展DLL时遇到资源加载冲突的常见原因,并提供了通过更改资源ID值来解决该问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

This article was previously published under Q150121

Collapse imageSYMPTOMS

The wrong resource is loaded when CBitmap::LoadBitmap, CMenu::LoadMenu, CString::LoadString or any other MFC resource-loading function is called in an MFC extension DLL (AFXDLL). In some cases, a resource in the application is loaded instead of the appropriate resource in the extension DLL.

Collapse imageCAUSE

When a resource in the application or another extension DLL gets loaded instead of a resource in the current extension DLL, the cause is usually improper resource management. An MFC application and all of its extension DLLs are one global chain of resources. If there are multiple resources with the same ID value in any of the modules in the chain, MFC uses the first resource it finds with the desired ID value. The first resource is often found in the application, which is searched before any of the extension DLLs.

Collapse imageRESOLUTION

Change the ID values of any resources that conflict so they are unique in both the application and any extension DLL that the application uses. These values are stored in the Resource.h file for each project and can be modified in the Resource Editor or AppStudio with the Resource Symbols command. 

To ensure that modules do not use conflicting symbol values, reserve different ranges of ID values for each module in the 1 through 0x6FFFF range. Set the _APS_NEXT_RESOURCE_VALUE definition in the Resource.h file for each module to the low end of that module's range before creating any resources. The Resource Editor uses this symbol to determine the ID value of the next resource created. 

This technique is documented in MFC Technical Note 35 and in the DLLHUSK sample included with Visual C++.

Collapse imageSTATUS

This behavior is by design.

Collapse imageMORE INFORMATION

In .exe or .dll files that link to MFC dynamically, MFC resource-loading functions call AfxFindResourceHandle() to obtain the handle of the module where a resource is located. AfxFindResourceHandle() searches for resources 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 call AfxFindResourceHandle(), but instead use the value returned from AfxCurrentResourceHandle(). 

Each extension DLL creates, initializes, and then passes a CDynLinkLibrary object to AfxInitExtensionModule() that places the DLL in the resource chain. AfxTermExtensionModule() removes the DLL from the chain when the DLL is detached from the application. 

A benefit of this design is that MFC automatically locates a resource for an application or extension DLL, even if that resource is located in a distant extension DLL or the application itself. All resources in the process are chained, so ID values are passed between DLLs and the application and the proper resources are loaded. A disadvantage is that there are no duplicate ID values between any of the extension DLLs or the application that uses them. 

To set the default location where AfxFindResourceHandle() first checks for a resource, use AfxSetResourceHandle(). Because AfxFindResourceHandle() first checks the handle set by AfxSetResourceHandle(), it can be used to circumvent the chain and load a resource from one particular DLL or application. The resource handle is restored to its original value immediately after loading the resources. The current default resource handle is found with AfxGetResourceHandle(). 

The DLLHUSK sample included with Visual C++ also illustrates this technique. In Testdll2.cpp, CListOutputFrame::Create() sets the resource handle to the module handle stored in the AFX_EXTENSION_MODULE structure extension DLL. This structure is initialized with the module handle when it is passed to the CDynLinkLibrary constructor in InitTestDLL2().

Collapse imageREFERENCES

For more information on: 

  • Extension DLLs, see the MFC Technical Note 33 and the DLLHUSK sample.
  • Resource management in projects, see Technical Note 35.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值