DragonNest/Third/XTToolkitPro/Samples/ToolkitPro/MultiLanguage/LangManager.cpp

385 lines
10 KiB
C++
Raw Normal View History

2024-12-19 09:48:26 +08:00
// LangManager.cpp: implementation of the CLanguageManger class.
//
// This file is a part of the XTREME TOOLKIT PRO MFC class library.
// (c)1998-2008 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "LangManager.h"
#pragma comment(lib, "version.lib")
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CLanguageManger::CLanguageManger()
: m_wLangID(0)
, m_hModule(0)
{
m_wLangID = (WORD)AfxGetApp()->GetProfileInt(_T("Settings"),
_T("Current Language"), MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
InitLanguageDlls();
}
CLanguageManger::~CLanguageManger()
{
if (m_hModule)
::FreeLibrary(m_hModule);
AfxGetApp()->WriteProfileInt(_T("Settings"),
_T("Current Language"), m_wLangID);
}
struct LANGDEF
{
UINT nID;
WORD wLangID;
};
const LANGDEF languages[] =
{
{ XTP_IDC_LANG_ARABIC, MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA) },
{ XTP_IDC_LANG_BULGARIAN, MAKELANGID(LANG_BULGARIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_CHINESE_PRC, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED) },
{ XTP_IDC_LANG_CHINESE_TAIWAN, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL) },
{ XTP_IDC_LANG_CROATIAN, MAKELANGID(LANG_CROATIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_CZECH, MAKELANGID(LANG_CZECH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_DANISH, MAKELANGID(LANG_DANISH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_DUTCH, MAKELANGID(LANG_DUTCH, SUBLANG_DUTCH) },
{ XTP_IDC_LANG_ENGLISH, MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US) },
{ XTP_IDC_LANG_ESTONIAN, MAKELANGID(LANG_ESTONIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_FINNISH, MAKELANGID(LANG_FINNISH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_FRENCH, MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH) },
{ XTP_IDC_LANG_GERMAN, MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN) },
{ XTP_IDC_LANG_GREEK, MAKELANGID(LANG_GREEK, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_HEBREW, MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_HUNGARIAN, MAKELANGID(LANG_HUNGARIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_ITALIAN, MAKELANGID(LANG_ITALIAN, SUBLANG_ITALIAN) },
{ XTP_IDC_LANG_JAPANESE, MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_KOREAN, MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_LATVIAN, MAKELANGID(LANG_LATVIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_LITHUANIAN, MAKELANGID(LANG_LITHUANIAN, SUBLANG_LITHUANIAN) },
{ XTP_IDC_LANG_NORWEGIAN, MAKELANGID(LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL) },
{ XTP_IDC_LANG_POLISH, MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_PORTUGUESE_BR, MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN) },
{ XTP_IDC_LANG_PORTUGUESE, MAKELANGID(LANG_PORTUGUESE, SUBLANG_PORTUGUESE) },
{ XTP_IDC_LANG_ROMANIAN, MAKELANGID(LANG_ROMANIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_RUSSIAN, MAKELANGID(LANG_RUSSIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_SLOVAK, MAKELANGID(LANG_SLOVAK, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_SLOVENIAN, MAKELANGID(LANG_SLOVENIAN, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_SPANISH, MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN) },
{ XTP_IDC_LANG_SWEDISH, MAKELANGID(LANG_SWEDISH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_THAI, MAKELANGID(LANG_THAI, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_TURKISH, MAKELANGID(LANG_TURKISH, SUBLANG_DEFAULT) },
{ XTP_IDC_LANG_UKRAINIAN, MAKELANGID(LANG_UKRAINIAN, SUBLANG_DEFAULT) },
};
BOOL CLanguageManger::GetDllInfo(const WORD& wLangId, LANGUAGE_DLL& langDll)
{
return m_mapLangDll.Lookup(wLangId, langDll);
}
BOOL CLanguageManger::EnumResTypeProc(HMODULE hModule, LPTSTR lpszType, LONG_PTR lParam)
{
WORD* pwLangID = (WORD*)lParam;
ASSERT(pwLangID);
if (!pwLangID)
return FALSE;
::EnumResourceNames(hModule, lpszType, &CLanguageManger::EnumResNameProc, lParam);
if(*pwLangID == LANG_NEUTRAL)
return TRUE; // continue if neutral
return FALSE; // continue if default
}
BOOL CLanguageManger::EnumResNameProc(HMODULE hModule, LPCTSTR lpszType, LPTSTR lpszName,
LONG_PTR lParam)
{
WORD* pwLangID = (WORD*)lParam;
ASSERT(pwLangID);
if (!pwLangID)
return FALSE;
::EnumResourceLanguages(hModule, lpszType, lpszName,
&CLanguageManger::EnumResLangProc, lParam);
if(*pwLangID == LANG_NEUTRAL)
return TRUE; // continue if neutral
return FALSE;
}
BOOL CLanguageManger::EnumResLangProc(HMODULE hModule, LPCTSTR lpszType,
LPCTSTR lpszName, WORD wIDLanguage, LONG_PTR lParam)
{
UNREFERENCED_PARAMETER(hModule); UNREFERENCED_PARAMETER(lpszType); UNREFERENCED_PARAMETER(lpszName);
WORD* pwLangID = (WORD*)lParam;
ASSERT(pwLangID);
if (!pwLangID)
return FALSE; // stop emuneration
if(wIDLanguage == LANG_NEUTRAL)
return TRUE; // continue if neutral
*pwLangID = wIDLanguage;
return FALSE;
}
WORD CLanguageManger::GetLangID(HMODULE hResDll) const
{
typedef WORD (CALLBACK* PGETLANGID)();
if (hResDll != NULL)
{
PGETLANGID pfnGetLangID = (PGETLANGID)::GetProcAddress(
hResDll, "GetLangID");
if (pfnGetLangID)
return (*pfnGetLangID)();
WORD wLanguage = 0;
DWORD Zero;
UINT cbTranslate;
TCHAR pszPath[MAX_PATH];
struct LANGANDCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
GetModuleFileName(hResDll, pszPath, MAX_PATH);
DWORD dwDataLen = ::GetFileVersionInfoSize(pszPath, &Zero);
if (dwDataLen == 0)
{
EnumResourceTypes(hResDll, &CLanguageManger::EnumResTypeProc, (LONG_PTR)&wLanguage);
return wLanguage;
}
LPVOID pData = new BYTE[dwDataLen];
if (::GetFileVersionInfo((TCHAR*)pszPath, NULL, dwDataLen, pData))
{
::VerQueryValue(pData, _T("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate);
if (cbTranslate >= 4)
{
wLanguage = lpTranslate->wLanguage;
}
}
delete [] pData;
return wLanguage;
}
return 0;
}
WORD CLanguageManger::GetLangID(UINT uCmdID) const
{
for (int i = 0; i < _countof(languages); ++i)
{
if (uCmdID == languages[i].nID)
{
return languages[i].wLangID;
}
}
return 0;
}
UINT CLanguageManger::GetCmdID(const WORD& wLangId) const
{
for (int i = 0; i < _countof(languages); ++i)
{
if (wLangId == languages[i].wLangID)
{
return languages[i].nID;
}
}
return 0;
}
CString CLanguageManger::GetDescription(const WORD& wLangId) const
{
for (int i = 0; i < _countof(languages); ++i)
{
if (wLangId == languages[i].wLangID)
{
CString strBuffer;
XTPResourceManager()->LoadString(&strBuffer, languages[i].nID);
return strBuffer;
}
}
return _T("");
}
BOOL CLanguageManger::InitLanguageDlls()
{
TCHAR szBuff[_MAX_PATH];
::GetModuleFileName(NULL, szBuff, _countof(szBuff));
TCHAR *p = _tcsrchr(szBuff, _T('\\'));
if (p != NULL) {
*p = _T('\0');
}
CString strDllPath;
if (!DIRECTORYEXISTS_S(CString(szBuff) + _T("\\Translations")) &&
DIRECTORYEXISTS_S(CString(szBuff) + _T("\\..\\..\\Utils\\Translations")))
{
strDllPath.Format(_T("%s\\..\\..\\Utils\\Translations\\*.dll"), szBuff);
}
else
{
strDllPath.Format(_T("%s\\Translations\\*.dll"), szBuff);
}
return InitLanguageDlls(strDllPath);
}
BOOL CLanguageManger::InitLanguageDlls(CString strDllPath)
{
m_mapLangDll.RemoveAll();
CFileFind ff;
BOOL bContinue = ff.FindFile(strDllPath);
while (bContinue)
{
bContinue = ff.FindNextFile();
if (ff.IsDots())
continue;
if (ff.IsDirectory())
continue;
CString strDllPath(ff.GetFilePath());
HMODULE hModule = ::LoadLibrary(strDllPath);
if (hModule)
{
WORD wLangID = GetLangID(hModule);
if (wLangID != 0)
{
LANGUAGE_DLL langDll;
langDll.uCmdID = GetCmdID(wLangID);
langDll.strDllPath = strDllPath;
m_mapLangDll[wLangID] = langDll;
}
::FreeLibrary(hModule);
}
}
ff.Close();
return TRUE;
}
BOOL CLanguageManger::IsRTL() const
{
return (
(m_wLangID == MAKELANGID(LANG_ARABIC, SUBLANG_ARABIC_SAUDI_ARABIA)) ||
(m_wLangID == MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT)));
}
WORD CLanguageManger::GetLangID() const
{
return m_wLangID;
}
BOOL CLanguageManger::LoadLanguageDll(LPCTSTR lpszDllPath)
{
if (m_hModule)
{
::FreeLibrary(m_hModule);
m_hModule = 0;
}
m_hModule = ::LoadLibrary(lpszDllPath);
m_wLangID = GetLangID(m_hModule);
XTPResourceManager()->SetResourceHandle(m_hModule);
return (m_hModule != NULL);
}
BOOL CLanguageManger::LoadLanguageDll(const WORD& wLangId)
{
LANGUAGE_DLL langDll;
if (m_mapLangDll.Lookup(wLangId, langDll))
{
return LoadLanguageDll(langDll.strDllPath);
}
return FALSE;
}
CMapLangDll& CLanguageManger::GetLangMap()
{
return m_mapLangDll;
}
void CLanguageManger::LayoutWindow(CWnd* pWnd, BOOL bRTLLayout)
{
pWnd->ModifyStyleEx(bRTLLayout? 0: WS_EX_LAYOUTRTL, !bRTLLayout? 0: WS_EX_LAYOUTRTL);
// walk through HWNDs to avoid creating temporary CWnd objects
// unless we need to call this function recursively
for (CWnd* pChild = pWnd->GetWindow(GW_CHILD); pChild != NULL;
pChild = pChild->GetWindow(GW_HWNDNEXT))
{
// send to child windows after parent
LayoutWindow(pChild, bRTLLayout);
}
}
void CLanguageManger::SetRTLLayout(CWnd* pWnd, BOOL bRTLLayout)
{
if ((BYTE)::GetVersion() < 4)
return;
LayoutWindow(pWnd, bRTLLayout);
// then update the state of all floating windows owned by the parent
HWND hWnd = ::GetWindow(::GetDesktopWindow(), GW_CHILD);
while (hWnd != NULL)
{
if (pWnd->m_hWnd == ::GetParent(hWnd))
LayoutWindow(CWnd::FromHandle(hWnd), bRTLLayout);
hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
}
}