384 lines
10 KiB
C++
384 lines
10 KiB
C++
// 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);
|
|
}
|
|
}
|