为啥 CString::LoadString 在我的应用程序的主模块(.exe)中有效,但在我的 extensionDLL 中无效?

Posted

技术标签:

【中文标题】为啥 CString::LoadString 在我的应用程序的主模块(.exe)中有效,但在我的 extensionDLL 中无效?【英文标题】:Why is it CString::LoadString works in the main module(.exe) of my app but will not work in my extensionDLL?为什么 CString::LoadString 在我的应用程序的主模块(.exe)中有效,但在我的 extensionDLL 中无效? 【发布时间】:2014-10-05 12:44:05 【问题描述】:

我有这个 MFC 应用程序,它使用 CString::LoadString 函数从字符串资源加载字符串。每个应用程序对话框的类及其相关资源都包含在 MFC 扩展 DLL 中。

CString::LoadString 从主模块(.exe) 资源的字符串资源中加载字符串成功,但从DLL 资源的字符串资源中加载字符串失败。

在每种情况下,我通过调用从 CWinApp 对象获取加载字符串的实例句柄: CWinApp *WinApp = AfxGetApp(), 当然,实例的句柄是 WinApp->m_hInstance,我在调用 CString::LoadString 函数时将其用作第一个参数。

可能是什么原因以及解决方法。

【问题讨论】:

MFC LoadString in dll fails 的可能重复项 ***.com/questions/9062034/… 【参考方案1】:

您是否通过 EXE 的 HINSTANCE 从扩展库加载字符串?听起来很像。

使用 MFC,如果您有扩展库并确保您的字符串标识符是唯一的,您只需要调用 CString::LoadString(UINT nID) 版本。因为扩展库创建进入全局链表的 CDynLinkLibrary 结构,所以 LoadString(UINT) 函数将搜索所有 MFC 库,直到找到包含该字符串的 HINSTANCE,然后从那里加载。如果您坚持使用带 HINSTANCE 参数的 LoadString() 函数,请务必在要从 DLL 加载字符串或对话框时使用扩展 DLL 的 HINSTANCE,而不是 EXE 的扩展。

对于小型项目,例如少于十几个 DLL,您可能设法只对所有内容使用唯一 ID。当您进入像 100 多个 DLL 之类的大型项目时,您必须使用其他技术,例如在您的 DLL 中调用 AfxSetResourceHandle() 的特殊命名函数,或者知道始终使用 DLL 的 HINSTANCE。那是另一个话题。

【讨论】:

【参考方案2】:

为了补充 Joe Willcoxson 的回答,请务必检查您使用的每个 MFC 扩展 DLL 是否需要特殊的初始化代码,类似于下面的示例:

#include "stdafx.h"
#include <afxdllx.h>

static AFX_EXTENSION_MODULE MyExtDLL =  NULL, NULL ;

extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

    if (dwReason == DLL_PROCESS_ATTACH)
    
        TRACE0("MyExt.DLL Initializing!\n");

        // Extension DLL one-time initialization
        if (!AfxInitExtensionModule(MyExtDLL, hInstance))
            return 0;
        new CDynLinkLibrary(MyExtDLL);
    
    else if (dwReason == DLL_PROCESS_DETACH)
    
        TRACE0("MyExt.DLL Terminating!\n");
        // Terminate the library before destructors are called
        AfxTermExtensionModule(MyExtDLL);
    
    return 1;   // ok

此代码只负责创建 CDynLinkLibrary,这是在 MFC 模块之间共享资源的关键。

如果所有这些都设置正确 - 并且没有 ID 冲突 - 那么它只是一个调用的数学:

CString str;
str.LoadString(IDS_MY_STRING_ID);

代码中的任何位置,无论字符串实际存在于何处。

可以在link 中找到有关资源 ID 和编号的良好起点。

【讨论】:

以上是关于为啥 CString::LoadString 在我的应用程序的主模块(.exe)中有效,但在我的 extensionDLL 中无效?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在我的 UIPanGestureRecognizer 上调用 UILongPressGestureRecognizer 方法?

为啥在我第一次单击按钮时在我的 RecyclerView 中调用绑定?

为啥 xlsxwriter 在我的单元格开头写 '

为啥在我的 java 代码中没有调用通知

为啥相同的代码在我的 BackGroundWorker 线程中比在我的 GUI 线程中慢得多?

为啥 Symfony 2 在我的环境中响应非常缓慢?