LoadString的如何确定load哪个语言的资源?

winger_w 2008-05-04 03:51:54
比如:有一个字符串ID:IDS_STRING,我的rc中对应两个字符串,一个是简体中文的"字符串",另一个是英文的“String”,
那么LoadString如何判断它load哪一个字符串?

以前我认为是根据调用线程的locale来确定的,后来发现了问题。

设置“区域和语言选项”中的“区域选项”为“英文(美国)”,
然后调用SetThreadLocale设置区域语言为英文。

此时调用LoadString(IDS_STRING),得到的结果却是简体中文的“字符串”!!~~~

不知道LoadString函数到底是依据什么来确定它Load一种语言的资源,请大侠赐教!!!!!谢谢!!!
...全文
3139 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhaojianzhong001 2012-02-09
  • 打赏
  • 举报
回复
借宝地再请教一下。
软件使用的客户使用的是阿拉伯文系统,
我现在的开发环境是中文系统,
VS2005应该如何设置,才能保证DDV校验的信息不会出现乱码?
diyixiyou2009 2011-11-29
  • 打赏
  • 举报
回复
看看emule plus V1.2e源代码,里面有任意切换不同语言的代码,其中string ID是相同的,


CString __stdcall GetResString(UINT dwStringID, WORD uLanguageID)
{
#ifndef NEW_SOCKETS_ENGINE
HINSTANCE hMod = ::GetModuleHandle(NULL);
CString strResString;

if (!strResString.LoadString(hMod, dwStringID, uLanguageID))
strResString.LoadString(hMod, dwStringID, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
return strResString;
#else
return _T("");
#endif //NEW_SOCKETS_ENGINE
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GetResString() loads default language resource string into already existing string.
__declspec(noinline) void __stdcall GetResString(CString *pstrOutput, UINT dwStringID)
{
#ifndef NEW_SOCKETS_ENGINE
HINSTANCE hMod = ::GetModuleHandle(NULL);

if (!pstrOutput->LoadString(hMod, dwStringID, g_App.m_pPrefs->GetLanguageID()))
pstrOutput->LoadString(hMod, dwStringID, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT));
#endif //NEW_SOCKETS_ENGINE
}
winger_w 2008-06-10
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 sugarshop 的回复:]
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了
[/Quote]
很明确的一点,你还没有搞清楚我问的是什么
吉哥 2008-05-19
  • 打赏
  • 举报
回复
可是我也遇到类似的问题啊。SetThreadLocale(GetUserDefaultLCID())为什么无效啊!如果单纯用SetThreadLocale(非当前区域设置)就可以。
GX198302 2008-05-10
  • 打赏
  • 举报
回复
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了
winger_w 2008-05-06
  • 打赏
  • 举报
回复
谢谢了,这么多贴还是没有明确的答案

看来想让FindResource完全按照我的意愿来Find一种语言资源是不太可能了
iyranly 2008-05-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 winger_w 的帖子:]
比如:有一个字符串ID:IDS_STRING,我的rc中对应两个字符串,一个是简体中文的"字符串",另一个是英文的“String”,
那么LoadString如何判断它load哪一个字符串?

以前我认为是根据调用线程的locale来确定的,后来发现了问题。

设置“区域和语言选项”中的“区域选项”为“英文(美国)”,
然后调用SetThreadLocale设置区域语言为英文。

此时调用LoadString(IDS_STRING),得到的结果却是简体中文的“字符串”…
[/Quote]

为什么不分别用两个ID来标识它"字符串"和"String"?
iyranly 2008-05-05
  • 打赏
  • 举报
回复
BOOL LoadString(
UINT nID );
只是将StringTable中ID为nID的字符串Load到你指定的CString变量中,如:

#define IDS_FILENOTFOUND 1
CString s;
if (! s.LoadString( IDS_FILENOTFOUND ))
{
AfxMessageBox("Error Loading String: IDS_FILENOTFOUND");
...
}


而你想要用户设置的是其它语言,LoadString也相应Load为该语言,需要重新定义StringTable,然后再根据用户选择的语言来进行switch或if判断,该LoadString哪一个字符串。如:

CString str;
switch(m_nLanID) //判断语言
{
case 0:str.LoadString( IDS_LAN_CHINESE );
break;
case 1:str.LoadString( IDS_LAN_ENGLISH );
break;
....
}
dbger 2008-05-05
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 winger_w 的回复:]
感谢dbger
不过这些我都看到过了

我是想了解LoadString通过什么判断其加载一种语言资源,而大都的回帖都是在告诉我如何多语言。。。。

我知道一些多语言方案,我现在只是想了解LoadString的判断过程,毕竟这样实现的多语言是最简单易行的。
[/Quote]

我反汇编了下Kernel32.dll里面的LoadString,XP系统下的LoadString内部调用了FindResourceEx。
MSDN里面说了SetTreadLocale会影响LoadString和FindResource,而不会影响FindResourceEx。
这也就是你在XP调用SetThreadLocale后出现的问题。

还是用其他方法吧。
winger_w 2008-05-05
  • 打赏
  • 举报
回复
感谢dbger
不过这些我都看到过了

我是想了解LoadString通过什么判断其加载一种语言资源,而大都的回帖都是在告诉我如何多语言。。。。

我知道一些多语言方案,我现在只是想了解LoadString的判断过程,毕竟这样实现的多语言是最简单易行的。
dbger 2008-05-05
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 winger_w 的回复:]
我是想了解LoadString通过什么判断其加载一种语言资源

Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
[/Quote]

老弟,何必这么较真呢。

下面链接里有FindResourceEx的实现代码:
http://www.codase.com/search/display?file=L2dlbnRvbzIvdmFyL3RtcC9yZXBvcy9jb2Rhc2UuYy93aW5lLTIwMDUwMTExLXIxL3dvcmsvd2luZS0yMDA1MDExMS9kbGxzL250ZGxsL3Jlc291cmNlLmM=&lang=c

我测试了下原因可能是这样的:

代码运行原理:
1)SetThreadLocale函数内部会判断设置的语言是否与当前语言(就是你在区域设置里面设置的语言)一致。
2)如果一致,则不做具体操作,否则修改LocaleInfo信息,并记录语言做了修改操作。
3)FindResoucesEx在实现上首先判断LocaleInfo是否修改过,如果修改过则取修改设置的语言字符串;如果没有修改则直接取系统默认语言(是操作系统自身的语言,不是区域设置里面设置的语言)。

由于你在区域里设置了设置了语言为英文(美国),当你的程序SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US))后,系统认为你设置的语言与当前语言一致,没有置修改标志。而当你LoadString时则直接取系统语言中文来加载字符串啦。

我测试了,如果在资源里添加“英文(英国)”语言资源,此时在系统区域里设置为“英文(美国)”,SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_UK))后可以加载英文(英国)的语言资源。
con_con 2008-05-05
  • 打赏
  • 举报
回复
等待正解出现
na_he 2008-05-05
  • 打赏
  • 举报
回复
为没language立一个resource了,每一个resouce设置为各国的语言就可以了,呵呵!
yajyjy 2008-05-05
  • 打赏
  • 举报
回复
要支持多语言,最好采用字典的方式,很方便
winger_w 2008-05-05
  • 打赏
  • 举报
回复
我是想了解LoadString通过什么判断其加载一种语言资源

Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
dbger 2008-05-04
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/en-us/library/ms776285(VS.85).aspx

Windows 2000/XP: Do not use SetThreadLocale to select a user interface language. To select the resource that is defined in the .rc file with a LANGUAGE statement, the application must use the Win32 FindResourceEx function.
Walker-cheng 2008-05-04
  • 打赏
  • 举报
回复
1.设置里面设语言资源
2.动态加载资源库
dbger 2008-05-04
  • 打赏
  • 举报
回复
家里装的是VS2005,代码如下:

__checkReturn BOOL LoadString( __in HINSTANCE hInstance, __in UINT nID, __in WORD wLanguageID )
{
const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage( hInstance, nID, wLanguageID );
if( pImage == NULL )
{
return( FALSE );
}

int nLength = StringTraits::GetBaseTypeLength( pImage->achString, pImage->nLength );
PXSTR pszBuffer = GetBuffer( nLength );
StringTraits::ConvertToBaseType( pszBuffer, nLength, pImage->achString, pImage->nLength );
ReleaseBufferSetLength( nLength );

return( TRUE );
}

inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id, WORD wLanguage ) throw()
{
HRSRC hResource;

hResource = ::FindResourceEx( hInstance, RT_STRING, MAKEINTRESOURCE( ((id>>4)+1) ), wLanguage );
if( hResource == NULL )
{
return( NULL );
}

return _AtlGetStringResourceImage( hInstance, hResource, id );
}

inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage( HINSTANCE hInstance, HRSRC hResource, UINT id ) throw()
{
const ATLSTRINGRESOURCEIMAGE* pImage;
const ATLSTRINGRESOURCEIMAGE* pImageEnd;
ULONG nResourceSize;
HGLOBAL hGlobal;
UINT iIndex;

hGlobal = ::LoadResource( hInstance, hResource );
if( hGlobal == NULL )
{
return( NULL );
}

pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource( hGlobal );
if( pImage == NULL )
{
return( NULL );
}

nResourceSize = ::SizeofResource( hInstance, hResource );
pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+nResourceSize);
iIndex = id&0x000f;

while( (iIndex > 0) && (pImage < pImageEnd) )
{
pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+(sizeof( ATLSTRINGRESOURCEIMAGE )+(pImage->nLength*sizeof( WCHAR ))));
iIndex--;
}
if( pImage >= pImageEnd )
{
return( NULL );
}
if( pImage->nLength == 0 )
{
return( NULL );
}

return( pImage );
}
winger_w 2008-05-04
  • 打赏
  • 举报
回复
设置“控制面板”——“区域和语言选项”中的“区域选项”为“英文(美国)”

不知这一步你做了没有


可以把2003里的CString::LoadString的代码贴下吗?我这里没有,作了参考
dbger 2008-05-04
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 winger_w 的回复:]
不知你是什么版本的MFC,我用的vc6.0
CString的LoadString最终调用的AfxLoadString
而AfxLoadString先用FindResource判断字符串表是否存在,如果存在就直接调用::LoadString了

int AFXAPI AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
{
ASSERT(AfxIsValidAddress(lpszBuf, nMaxBuf*sizeof(TCHAR)));
#ifdef _DEBUG
// LoadString without annoying warning from the Debug kernel if the
// segment cont…
[/Quote]

我的是VS2003
加载更多回复(12)

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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