那么LoadString如何判断它load哪一个字符串?
以前我认为是根据调用线程的locale来确定的,后来发现了问题。
设置“区域和语言选项”中的“区域选项”为“英文(美国)”,
然后调用SetThreadLocale设置区域语言为英文。
此时调用LoadString(IDS_STRING),得到的结果却是简体中文的“字符串”!!~~~
不知道LoadString函数到底是依据什么来确定它Load一种语言的资源,请大侠赐教!!!!!谢谢!!!
33 个解决方案
#1
设置“区域和语言选项”中的“高级”为“英文(美国)”。
#2
个人觉得可能是系统先调用GetACP()函数取得系统语言,如果资源里没有这种语言则加载英文资源
#3
你凭什么去修改用户的设置呢?你也不能要求修改设置,你应该读取当前的LOCAL信息,
然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。
根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);
然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。
根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);
#4
回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。
回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。
不知我说的是否明白?。。。。
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。
回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。
不知我说的是否明白?。。。。
#5
回3楼:
你没看明白我问的问题
不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串
你没看明白我问的问题
不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串
#6
你确认你设置的代码页与你的资源里字符串资源的代码页一致嘛
#7
我没有设置代码页,我设置的是区域选项!
如果我设置区域选项为“英文(美国)”,我在程序中用SetThreadLocale设置为“英文(美国)”
那么LoadString就不会load出英文(美国)这个code page的字符串,而是简体中文的字符串。(我的系统是简体中文的windows XP)
如果我设置区域选项为“英文(美国)”,我在程序中用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是没问题的,兄台有兴趣的话可以试一下~~
我资源里设置的code page肯定是对的。
如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试一下~~
#10
看看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;
}
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显示的是中文。
加上则显示为英文。
SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US));
CString strText;
strText.LoadString(IDS_TEST);
MessegeBox(strText);
我的语言资源里面有中文和英文两种字符串资源。
我的系统语言是中文XP。
如果没有调用SetThreadLocal显示的是中文。
加上则显示为英文。
#13
我的是VS2003
#14
设置“控制面板”——“区域和语言选项”中的“区域选项”为“英文(美国)”
不知这一步你做了没有
可以把2003里的CString::LoadString的代码贴下吗?我这里没有,作了参考
不知这一步你做了没有
可以把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 );
}
__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.动态加载资源库
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.
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的判断过程,毕竟这样实现的多语言是最简单易行的。
不过这些我都看到过了
我是想了解LoadString通过什么判断其加载一种语言资源,而大都的回帖都是在告诉我如何多语言。。。。
我知道一些多语言方案,我现在只是想了解LoadString的判断过程,毕竟这样实现的多语言是最简单易行的。
#19
#20
我反汇编了下Kernel32.dll里面的LoadString,XP系统下的LoadString内部调用了FindResourceEx。
MSDN里面说了SetTreadLocale会影响LoadString和FindResource,而不会影响FindResourceEx。
这也就是你在XP调用SetThreadLocale后出现的问题。
还是用其他方法吧。
#21
BOOL LoadString(
UINT nID );
只是将StringTable中ID为nID的字符串Load到你指定的CString变量中,如:
而你想要用户设置的是其它语言,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;
....
}
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
为什么不分别用两个ID来标识它"字符串"和"String"?
#23
我是想了解LoadString通过什么判断其加载一种语言资源
Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
#24
要支持多语言,最好采用字典的方式,很方便
#25
为没language立一个resource了,每一个resouce设置为各国的语言就可以了,呵呵!
#26
等待正解出现
#27
老弟,何必这么较真呢。
下面链接里有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一种语言资源是不太可能了
看来想让FindResource完全按照我的意愿来Find一种语言资源是不太可能了
#29
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了
#30
可是我也遇到类似的问题啊。SetThreadLocale(GetUserDefaultLCID())为什么无效啊!如果单纯用SetThreadLocale(非当前区域设置)就可以。
#31
很明确的一点,你还没有搞清楚我问的是什么
#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
}
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校验的信息不会出现乱码?
软件使用的客户使用的是阿拉伯文系统,
我现在的开发环境是中文系统,
VS2005应该如何设置,才能保证DDV校验的信息不会出现乱码?
#1
设置“区域和语言选项”中的“高级”为“英文(美国)”。
#2
个人觉得可能是系统先调用GetACP()函数取得系统语言,如果资源里没有这种语言则加载英文资源
#3
你凭什么去修改用户的设置呢?你也不能要求修改设置,你应该读取当前的LOCAL信息,
然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。
根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);
然后把中文和英文的字符串放在不同的DLL,你在RC中修改字符串资源的语言属性几乎没有意义。
根据读到的LOCAL信息加载不同语言的DLL,然后调用LoadString(hInstYourDll, ....);
#4
回1楼的
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。
回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。
不知我说的是否明白?。。。。
这个跟系统locale(代码页)没有关系,只要我设置了用户locale和我SetThreadLocale相同,无论我怎么设置代码页,都不能load我想要的字符串。
回2楼:
只要SetThreadLocale设置的locale和当前设置的用户locale(区域选项)不同,LoadString都会按照SetThreadLocale设置的locale来LoadString。。。。
不知我说的是否明白?。。。。
#5
回3楼:
你没看明白我问的问题
不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串
你没看明白我问的问题
不是我去修改那个设置,而是用户去修改了,我是尝试用SetThreadLocale让loadString,load我想要的字符串
#6
你确认你设置的代码页与你的资源里字符串资源的代码页一致嘛
#7
我没有设置代码页,我设置的是区域选项!
如果我设置区域选项为“英文(美国)”,我在程序中用SetThreadLocale设置为“英文(美国)”
那么LoadString就不会load出英文(美国)这个code page的字符串,而是简体中文的字符串。(我的系统是简体中文的windows XP)
如果我设置区域选项为“英文(美国)”,我在程序中用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是没问题的,兄台有兴趣的话可以试一下~~
我资源里设置的code page肯定是对的。
如果我在控制面板的区域选项里设置的用户locale,和SetThreadLocale里设置的locale不一样,这个LoadString函数会按照SetThreadLocale设置的locale来决定load的资源,他都能正确的load出我想要的字符串,所以我资源文件里设置的code page是没问题的,兄台有兴趣的话可以试一下~~
#10
看看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;
}
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显示的是中文。
加上则显示为英文。
SetThreadLocal(MAKELANGID(LANG_ENGLISH,SUBLANGE_ENGLISH_US));
CString strText;
strText.LoadString(IDS_TEST);
MessegeBox(strText);
我的语言资源里面有中文和英文两种字符串资源。
我的系统语言是中文XP。
如果没有调用SetThreadLocal显示的是中文。
加上则显示为英文。
#13
我的是VS2003
#14
设置“控制面板”——“区域和语言选项”中的“区域选项”为“英文(美国)”
不知这一步你做了没有
可以把2003里的CString::LoadString的代码贴下吗?我这里没有,作了参考
不知这一步你做了没有
可以把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 );
}
__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.动态加载资源库
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.
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的判断过程,毕竟这样实现的多语言是最简单易行的。
不过这些我都看到过了
我是想了解LoadString通过什么判断其加载一种语言资源,而大都的回帖都是在告诉我如何多语言。。。。
我知道一些多语言方案,我现在只是想了解LoadString的判断过程,毕竟这样实现的多语言是最简单易行的。
#19
#20
我反汇编了下Kernel32.dll里面的LoadString,XP系统下的LoadString内部调用了FindResourceEx。
MSDN里面说了SetTreadLocale会影响LoadString和FindResource,而不会影响FindResourceEx。
这也就是你在XP调用SetThreadLocale后出现的问题。
还是用其他方法吧。
#21
BOOL LoadString(
UINT nID );
只是将StringTable中ID为nID的字符串Load到你指定的CString变量中,如:
而你想要用户设置的是其它语言,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;
....
}
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
为什么不分别用两个ID来标识它"字符串"和"String"?
#23
我是想了解LoadString通过什么判断其加载一种语言资源
Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
Kernel32.dll内部调了FindResourceEx,那么传递给FindResourceEx的wLanguageID是怎么得来的呢?
#24
要支持多语言,最好采用字典的方式,很方便
#25
为没language立一个resource了,每一个resouce设置为各国的语言就可以了,呵呵!
#26
等待正解出现
#27
老弟,何必这么较真呢。
下面链接里有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一种语言资源是不太可能了
看来想让FindResource完全按照我的意愿来Find一种语言资源是不太可能了
#29
很明确的一点: 自己根本不想搞清楚 我觉得dbger说的很清楚了
#30
可是我也遇到类似的问题啊。SetThreadLocale(GetUserDefaultLCID())为什么无效啊!如果单纯用SetThreadLocale(非当前区域设置)就可以。
#31
很明确的一点,你还没有搞清楚我问的是什么
#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
}
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校验的信息不会出现乱码?
软件使用的客户使用的是阿拉伯文系统,
我现在的开发环境是中文系统,
VS2005应该如何设置,才能保证DDV校验的信息不会出现乱码?