为什么CString :: LoadString在我的应用程序的主模块(.exe)中工作,但在我的扩展DLL中不起作用?

时间:2014-10-05 12:44:05

标签: c++ mfc

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

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

对于小型项目,例如不到12个DLL,您可能只需使用唯一ID即可。当您进入像100+ DLL这样疯狂的大型项目时,您必须使用其他技术,例如DLL中调用AfxSetResourceHandle()的特殊命名函数,或者知道始终使用DLL的HINSTANCE。这是另一个话题。

答案 1 :(得分:0)

为了补充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模块之间共享资源的关键。

如果所有这些都设置正确 - 并且没有身份证冲突 - 那么它只是一个呼唤:

CString str;
str.LoadString(IDS_MY_STRING_ID);

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

有关资源ID和编号的良好起点,请参阅此link