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

时间:2021-08-25 15:53:16
比如:有一个字符串ID:IDS_STRING,我的rc中对应两个字符串,一个是简体中文的"字符串",另一个是英文的“String”,
那么LoadString如何判断它load哪一个字符串? 

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

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

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

不知道LoadString函数到底是依据什么来确定它Load一种语言的资源,请大侠赐教!!!!!谢谢!!!

33 个解决方案

#1


设置“区域和语言选项”中的“高级”为“英文(美国)”。

#2


个人觉得可能是系统先调用GetACP()函数取得系统语言,如果资源里没有这种语言则加载英文资源

#3


你凭什么去修改用户的设置呢?你也不能要求修改设置,你应该读取当前的LOCAL信息,

然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。

根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);

#4


回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。

回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。

不知我说的是否明白?。。。。

#5


回3楼:
你没看明白我问的问题

不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串

#6


引用 4 楼 winger_w 的回复:
回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。

回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。

不知我说的是否明白?。。。。


你确认你设置的代码页与你的资源里字符串资源的代码页一致嘛

#7


我没有设置代码页,我设置的是区域选项!

如果我设置区域选项为“英文(美国)”,我在程序中用SetThreadLocale设置为“英文(美国)”
那么LoadString就不会load出英文(美国)这个code page的字符串,而是简体中文的字符串。(我的系统是简体中文的windows XP)

#8


看了看CString里面的源码,应该设置了LanguageID就可以啦,反汇编看了看Kernel32.dll的LoadStringA跟CString里面的实现是一样的。可能还是你的Code page没设置对。

#9


我知道是一样的,都是最终调用API,我不知道这个API内部是什么过程,所以想问问他怎么决定load一种语言的资源。

我资源里设置的code page肯定是对的。

如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试一下~~

#10


引用 9 楼 winger_w 的回复:
我知道是一样的,都是最终调用API,我不知道这个API内部是什么过程,所以想问问他怎么决定load一种语言的资源。

我资源里设置的code page肯定是对的。

如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试…


看看CString的LoadStirng就知道啦,它里面没有直接调用LoadString的API,是调用的FindResourceEx

#11


不知你是什么版本的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 containing the string is not present
if (::FindResource(AfxGetResourceHandle(),
   MAKEINTRESOURCE((nID>>4)+1), RT_STRING) == NULL)
{
lpszBuf[0] = '\0';
return 0; // not found
}
#endif //_DEBUG
int nLen = ::LoadString(AfxGetResourceHandle(), nID, lpszBuf, nMaxBuf);
if (nLen == 0)
lpszBuf[0] = '\0';
return nLen;
}

#12


我测试了下,没问题的。

SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US));
CString strText;
strText.LoadString(IDS_TEST);
MessegeBox(strText);


我的语言资源里面有中文和英文两种字符串资源。
我的系统语言是中文XP。
如果没有调用SetThreadLocal显示的是中文。
加上则显示为英文。

#13


引用 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…


我的是VS2003

#14


设置“控制面板”——“区域和语言选项”中的“区域选项”为“英文(美国)”

不知这一步你做了没有


可以把2003里的CString::LoadString的代码贴下吗?我这里没有,作了参考

#15


家里装的是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 );
}

#16


1.设置里面设语言资源
2.动态加载资源库

#17


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.

#18


感谢dbger 
不过这些我都看到过了

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

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

#19


该回复于2008-05-05 10:24:50被版主删除

#20


引用 18 楼 winger_w 的回复:
感谢dbger
不过这些我都看到过了

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

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


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

还是用其他方法吧。

#21


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;
    ....
}

#22


引用楼主 winger_w 的帖子:
比如:有一个字符串ID:IDS_STRING,我的rc中对应两个字符串,一个是简体中文的"字符串",另一个是英文的“String”, 
那么LoadString如何判断它load哪一个字符串?  

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

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

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


为什么不分别用两个ID来标识它"字符串"和"String"?

#23


我是想了解LoadString通过什么判断其加载一种语言资源

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

#24


要支持多语言,最好采用字典的方式,很方便

#25


为没language立一个resource了,每一个resouce设置为各国的语言就可以了,呵呵!

#26


等待正解出现

#27


引用 23 楼 winger_w 的回复:
我是想了解LoadString通过什么判断其加载一种语言资源

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


老弟,何必这么较真呢。

下面链接里有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))后可以加载英文(英国)的语言资源。

#28


谢谢了,这么多贴还是没有明确的答案

看来想让FindResource完全按照我的意愿来Find一种语言资源是不太可能了

#29


很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了

#30


可是我也遇到类似的问题啊。SetThreadLocale(GetUserDefaultLCID())为什么无效啊!如果单纯用SetThreadLocale(非当前区域设置)就可以。

#31


引用 29 楼 sugarshop 的回复:
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了

很明确的一点,你还没有搞清楚我问的是什么

#32


看看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
}

#33


借宝地再请教一下。
软件使用的客户使用的是阿拉伯文系统,
我现在的开发环境是中文系统,
VS2005应该如何设置,才能保证DDV校验的信息不会出现乱码?

#1


设置“区域和语言选项”中的“高级”为“英文(美国)”。

#2


个人觉得可能是系统先调用GetACP()函数取得系统语言,如果资源里没有这种语言则加载英文资源

#3


你凭什么去修改用户的设置呢?你也不能要求修改设置,你应该读取当前的LOCAL信息,

然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。

根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);

#4


回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。

回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。

不知我说的是否明白?。。。。

#5


回3楼:
你没看明白我问的问题

不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串

#6


引用 4 楼 winger_w 的回复:
回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。

回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。

不知我说的是否明白?。。。。


你确认你设置的代码页与你的资源里字符串资源的代码页一致嘛

#7


我没有设置代码页,我设置的是区域选项!

如果我设置区域选项为“英文(美国)”,我在程序中用SetThreadLocale设置为“英文(美国)”
那么LoadString就不会load出英文(美国)这个code page的字符串,而是简体中文的字符串。(我的系统是简体中文的windows XP)

#8


看了看CString里面的源码,应该设置了LanguageID就可以啦,反汇编看了看Kernel32.dll的LoadStringA跟CString里面的实现是一样的。可能还是你的Code page没设置对。

#9


我知道是一样的,都是最终调用API,我不知道这个API内部是什么过程,所以想问问他怎么决定load一种语言的资源。

我资源里设置的code page肯定是对的。

如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试一下~~

#10


引用 9 楼 winger_w 的回复:
我知道是一样的,都是最终调用API,我不知道这个API内部是什么过程,所以想问问他怎么决定load一种语言的资源。

我资源里设置的code page肯定是对的。

如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试…


看看CString的LoadStirng就知道啦,它里面没有直接调用LoadString的API,是调用的FindResourceEx

#11


不知你是什么版本的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 containing the string is not present
if (::FindResource(AfxGetResourceHandle(),
   MAKEINTRESOURCE((nID>>4)+1), RT_STRING) == NULL)
{
lpszBuf[0] = '\0';
return 0; // not found
}
#endif //_DEBUG
int nLen = ::LoadString(AfxGetResourceHandle(), nID, lpszBuf, nMaxBuf);
if (nLen == 0)
lpszBuf[0] = '\0';
return nLen;
}

#12


我测试了下,没问题的。

SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US));
CString strText;
strText.LoadString(IDS_TEST);
MessegeBox(strText);


我的语言资源里面有中文和英文两种字符串资源。
我的系统语言是中文XP。
如果没有调用SetThreadLocal显示的是中文。
加上则显示为英文。

#13


引用 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…


我的是VS2003

#14


设置“控制面板”——“区域和语言选项”中的“区域选项”为“英文(美国)”

不知这一步你做了没有


可以把2003里的CString::LoadString的代码贴下吗?我这里没有,作了参考

#15


家里装的是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 );
}

#16


1.设置里面设语言资源
2.动态加载资源库

#17


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.

#18


感谢dbger 
不过这些我都看到过了

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

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

#19


该回复于2008-05-05 10:24:50被版主删除

#20


引用 18 楼 winger_w 的回复:
感谢dbger
不过这些我都看到过了

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

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


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

还是用其他方法吧。

#21


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;
    ....
}

#22


引用楼主 winger_w 的帖子:
比如:有一个字符串ID:IDS_STRING,我的rc中对应两个字符串,一个是简体中文的"字符串",另一个是英文的“String”, 
那么LoadString如何判断它load哪一个字符串?  

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

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

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


为什么不分别用两个ID来标识它"字符串"和"String"?

#23


我是想了解LoadString通过什么判断其加载一种语言资源

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

#24


要支持多语言,最好采用字典的方式,很方便

#25


为没language立一个resource了,每一个resouce设置为各国的语言就可以了,呵呵!

#26


等待正解出现

#27


引用 23 楼 winger_w 的回复:
我是想了解LoadString通过什么判断其加载一种语言资源

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


老弟,何必这么较真呢。

下面链接里有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))后可以加载英文(英国)的语言资源。

#28


谢谢了,这么多贴还是没有明确的答案

看来想让FindResource完全按照我的意愿来Find一种语言资源是不太可能了

#29


很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了

#30


可是我也遇到类似的问题啊。SetThreadLocale(GetUserDefaultLCID())为什么无效啊!如果单纯用SetThreadLocale(非当前区域设置)就可以。

#31


引用 29 楼 sugarshop 的回复:
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了

很明确的一点,你还没有搞清楚我问的是什么

#32


看看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
}

#33


借宝地再请教一下。
软件使用的客户使用的是阿拉伯文系统,
我现在的开发环境是中文系统,
VS2005应该如何设置,才能保证DDV校验的信息不会出现乱码?