VC6 用资源DLL实现多语言界面

llhohai 2014-02-24 09:55:44
开发环境 : VC6 MFC

按照网上的方法,将程序的资源从 A.EXE 程序中分离出来,并制作成资源 DLL 文件
并通过
         AfxEnableControlContainer();

if (m_bChinese)
{
m_hLangDLL=::LoadLibrary("chinese.dll");
}
else
{
m_hLangDLL=::LoadLibrary("english.dll");
}

AfxSetResourceHandle(m_hLangDLL);


这样的方法进行资源切换,可以实现。但是也存在了一个问题,就是 A.EXE 还调用了另外一个动态库B.DLL,且这个动态库中包含了一些资源文件。现在的问题就是 B.DLL 中的资源无法被调用了,请大家帮忙想想有没有解决的方法.
...全文
182 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
worldy 2014-02-25
  • 打赏
  • 举报
回复
引用 2 楼 llhohai 的回复:
[quote=引用 1 楼 xuddk727 的回复:] 同样在那个dll中也要AfxSetResourceHandle的
我在B.DLL中同样也将资源分离出来了,现在是在 A.EXE 中加载的只是 A.EXE 的资源,无法加载到B.DLL 中的资源。[/quote] 谁的资源归谁管 A加载B,B加载C
yangxuefeng09 2014-02-25
  • 打赏
  • 举报
回复
llhohai 2014-02-25
  • 打赏
  • 举报
回复
typedef LANGID (WINAPI *FP_SetThreadUILanguage)(LANGID LangId); LANGID SetThreadUILanguage(LANGID lcid) { HMODULE hKernel32 = GetModuleHandle(_T("Kernel32.dll")); FARPROC pFn = GetProcAddress(hKernel32, "SetThreadUILanguage"); FP_SetThreadUILanguage pSetThreadUILanguage = (FP_SetThreadUILanguage)pFn; if (pSetThreadUILanguage) { return pSetThreadUILanguage(lcid); } return 0; } 在网上找的方法,自己实现SetThreadUILanguage方法,经测试VC6+WIN7可用,多谢大家了。
llhohai 2014-02-25
  • 打赏
  • 举报
回复
引用 10 楼 Saimen 的回复:
// LCID lcEN = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); // LCID lcZH = MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT); // XP // SetThreadLocale(lcEN); // SetThreadLocale(lcZH); // WIN7 LANGID langEN = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); SetThreadUILanguage (langEN); 用多个DLL的方法,觉得不如这个方法 都在APP中
我按照你说的方法试验了一下,VC6的开发环境,在XP底下是可以实现的,但是在WIN7下面提示没有这个方法,有没有什么替代方法啊。
llhohai 2014-02-24
  • 打赏
  • 举报
回复
引用 1 楼 xuddk727 的回复:
同样在那个dll中也要AfxSetResourceHandle的
我在B.DLL中同样也将资源分离出来了,现在是在 A.EXE 中加载的只是 A.EXE 的资源,无法加载到B.DLL 中的资源。
许文君 2014-02-24
  • 打赏
  • 举报
回复
同样在那个dll中也要AfxSetResourceHandle的
HuWenjin 2014-02-24
  • 打赏
  • 举报
回复
// LCID lcEN = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); // LCID lcZH = MAKELCID(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED), SORT_DEFAULT); // XP // SetThreadLocale(lcEN); // SetThreadLocale(lcZH); // WIN7 LANGID langEN = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US); SetThreadUILanguage (langEN); 用多个DLL的方法,觉得不如这个方法 都在APP中
孤客天涯 2014-02-24
  • 打赏
  • 举报
回复
若要做多语言切换,记得你任何一个模块,写代码时都要注意,与资源相关的函数就尽量从自身资源中查找,而不要用系统默认的查找方式,举个简单的例子:
AfxLoadString函数,它的实现如下:
int AFXAPI AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
{
ASSERT(AfxIsValidAddress(lpszBuf, nMaxBuf*sizeof(TCHAR)));

LPCTSTR lpszName = MAKEINTRESOURCE((nID>>4)+1);
HINSTANCE hInst;
int nLen;

// first check the main module state
AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
if (!pModuleState->m_bSystem)
{
hInst = AfxGetResourceHandle();
if (::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
{
// found a non-zero string in app
return nLen;
}
}

// check non-system DLLs in proper order
AfxLockGlobals(CRIT_DYNLINKLIST);
for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
pDLL = pDLL->m_pNextDLL)
{
if (!pDLL->m_bSystem && (hInst = pDLL->m_hResource) != NULL &&
::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
{
AfxUnlockGlobals(CRIT_DYNLINKLIST);
return nLen;
}
}
AfxUnlockGlobals(CRIT_DYNLINKLIST);

// check language specific DLL next
hInst = pModuleState->m_appLangDLL;
if (hInst != NULL && ::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
{
// found a non-zero string in language DLL
return nLen;
}

// check the system module state
if (pModuleState->m_bSystem)
{
hInst = AfxGetResourceHandle();
if (::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
{
// found a non-zero string in app
return nLen;
}
}

// check system DLLs in proper order
AfxLockGlobals(CRIT_DYNLINKLIST);
for (pDLL = pModuleState->m_libraryList; pDLL != NULL; pDLL = pDLL->m_pNextDLL)
{
if (pDLL->m_bSystem && (hInst = pDLL->m_hResource) != NULL &&
::FindResource(hInst, lpszName, RT_STRING) != NULL &&
(nLen = ::LoadString(hInst, nID, lpszBuf, nMaxBuf)) != 0)
{
AfxUnlockGlobals(CRIT_DYNLINKLIST);
return nLen;
}
}
AfxUnlockGlobals(CRIT_DYNLINKLIST);

// did not find it
lpszBuf[0] = '\0';
return 0;
}

不难看出,它是通过AfxGetResourceHandle的方式获取当前的资源句柄,当你AfxSetResourceHandle(m_hLangDLL);的时候,那么当前资源指向了m_hLangDLL,那么系统就会从这里面去找,肯定找不到B动态库中的资源了。
那么解决是B.dll加载时先记录自身的 HINSTANCE hInst,然后直接用
::LoadString(
HINSTANCE hInstance,
UINT uID,
LPWSTR lpBuffer,
int nBufferMax)

把B.dll的HINSTANCE 传给LoadString就可以了
许文君 2014-02-24
  • 打赏
  • 举报
回复
那你通过dll导出个接口来供exe来调用资源
llhohai 2014-02-24
  • 打赏
  • 举报
回复
引用 6 楼 xuddk727 的回复:
[quote=引用 5 楼 llhohai 的回复:] [quote=引用 3 楼 xuddk727 的回复:] 你的m_hLangDLL是如何得来的
HINSTANCE m_hLangDLL = NULL;[/quote] 不对,你应该通过dllmain获得hinstance,若是mfc的dll,通过theApp.m_hInstance获得[/quote] 无论我怎么获得的,最终是我在切换语言的时候 用AfxSetResourceHandle("Chinese.dll") 设置成 其它的资源了,本身这样的方法我是已经实现,并且可以的。 存在的问题就是程序还想调用其它的 资源文件,譬如 X.DLL。
许文君 2014-02-24
  • 打赏
  • 举报
回复
引用 5 楼 llhohai 的回复:
[quote=引用 3 楼 xuddk727 的回复:] 你的m_hLangDLL是如何得来的
HINSTANCE m_hLangDLL = NULL;[/quote] 不对,你应该通过dllmain获得hinstance,若是mfc的dll,通过theApp.m_hInstance获得
llhohai 2014-02-24
  • 打赏
  • 举报
回复
引用 3 楼 xuddk727 的回复:
你的m_hLangDLL是如何得来的
HINSTANCE m_hLangDLL = NULL;
schlafenhamster 2014-02-24
  • 打赏
  • 举报
回复
B.dll 加一个 改资源的函数。 a.exe 改 资源时 加 b.dll也改资源
许文君 2014-02-24
  • 打赏
  • 举报
回复
你的m_hLangDLL是如何得来的

2,586

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 资源
社区管理员
  • 资源
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧