📄 mui.cpp
字号:
// mui.cpp
#include <windows.h>
#include "msc.h"
#include "filename.h"
#include "mui.h"
#include "res.h"
static int IsHaveOwnResource ( int nLangId ) ;
static const void *nDefaultRsrcType ;
static int nDefaultRsrcId ;
static char *GetDllDirectoryA ( char *szBuffer ) ;
static wchar_t *GetDllDirectoryW ( wchar_t *szBuffer ) ;
static char *GetDllPrefixA ( char *szBuffer ) ;
static wchar_t *GetDllPrefixW ( wchar_t *szBuffer ) ;
//////////////////////////////
// 儘乕僪 //
//////////////////////////////
// 懡尵岅梡 DLL 傪儘乕僪偡傞
// 惉岟偟偨傜 0 傪曉偡
int LoadMuiLibrary ( int nLangId ) {
HINSTANCE hPrevInstance = SetSatelliteResourceInstance ( NULL ) ;
if ( hPrevInstance ) FreeLibrary ( hPrevInstance ) ;
SetResourceLanguage ( nLangId ) ;
if ( ! nLangId ) return 0 ;
if ( IsHaveOwnResource ( nLangId ) ) return 0 ;
HINSTANCE hNewInstance = NULL ;
if ( IsNT () ) {
wchar_t szFileName [ MAX_PATH * 2 ] ;
GetModuleFileNameW ( NULL, szFileName, MAX_PATH ) ;
ChangeFileNameW ( szFileName, NULL ) ;
GetDllDirectoryW ( wcsend ( szFileName ) ) ;
SetPathSeparatorW ( szFileName, 1 ) ;
GetDllPrefixW ( wcsend ( szFileName ) ) ;
if ( GetLocaleInfoW ( MAKELCID ( nLangId, SORT_DEFAULT ), LOCALE_SABBREVLANGNAME, wcsend ( szFileName ), MAX_PATH ) ) {
wcscat ( szFileName, L".dll" ) ;
hNewInstance = LoadLibraryExW ( szFileName, NULL, LOAD_LIBRARY_AS_DATAFILE ) ;
}
}
else {
char szFileName [ MAX_PATH * 2 ] ;
GetModuleFileNameA ( NULL, szFileName, MAX_PATH ) ;
ChangeFileNameA ( szFileName, NULL ) ;
GetDllDirectoryA ( strend ( szFileName ) ) ;
SetPathSeparatorA ( szFileName, 1 ) ;
GetDllPrefixA ( strend ( szFileName ) ) ;
if ( GetLocaleInfoA ( MAKELCID ( nLangId, SORT_DEFAULT ), LOCALE_SABBREVLANGNAME, strend ( szFileName ), MAX_PATH ) ) {
strcat ( szFileName, ".dll" ) ;
hNewInstance = LoadLibraryExA ( szFileName, NULL, LOAD_LIBRARY_AS_DATAFILE ) ;
}
}
if ( hNewInstance ) {
HRSRC hRsrc ;
if ( IsNT () ) hRsrc = FindResourceExW ( hNewInstance, MAKEINTRESOURCEW ( nDefaultRsrcType ), MAKEINTRESOURCEW ( nDefaultRsrcId ), (LANGID) nLangId ) ;
else hRsrc = FindResourceExA ( hNewInstance, MAKEINTRESOURCEA ( nDefaultRsrcType ), MAKEINTRESOURCEA ( nDefaultRsrcId ), (LANGID) nLangId ) ;
if ( hRsrc ) {
SetSatelliteResourceInstance ( hNewInstance ) ;
return 0 ;
}
FreeLibrary ( hNewInstance ) ;
}
return 1 ;
}
//////////////////////////////
// 弶婜壔 //
//////////////////////////////
static int GetAlternativeLangId ( int nLangId ) ;
static int InitResourceData ( const void *nType, int nId ) ;
static int InitMuiLangId ( const void *nType, int nId ) ;
static char *szDllDirectoryA ;
static wchar_t *szDllDirectoryW ;
static char *szDllPrefixA ;
static wchar_t *szDllPrefixW ;
static int FreeConfiguration ( void ) ;
static void __cdecl ExitProc ( void ) ;
static volatile long IsExitProcRegistered ;
typedef LANGID ( WINAPI *GETUSERDEFAULTUILANGUAGE ) ( void ) ;
// 僔僗僥儉偺尵岅傪専嵏偡傞乮ANSI斉乯
// 昁梫側傜偽懡尵岅梡 DLL 傪儘乕僪偡傞
// 惉岟偟偨傜 0 傪丄幐攕偟偨傜 0 埲奜傪曉偡
int InitMuiLibraryA ( const void *nType, int nId, const char *szDirectory, const char *szPrefix ) {
if ( (uintptr_t) nType > 0xFFFF ) return 1 ;
FreeConfiguration () ;
if ( szDirectory && ! ( szDllDirectoryA = strdup ( szDirectory ) ) ) return 1 ;
if ( szPrefix && ! ( szDllPrefixA = strdup ( szPrefix ) ) ) return 1 ;
if ( ! InterlockedExchange ( & IsExitProcRegistered, TRUE ) ) atexit ( ExitProc ) ;
InitResourceData ( nType, nId ) ;
return InitMuiLangId ( nType, nId ) ;
}
// 僔僗僥儉偺尵岅傪専嵏偡傞乮UNICODE斉乯
// 昁梫側傜偽懡尵岅梡 DLL 傪儘乕僪偡傞
// 惉岟偟偨傜 0 傪丄幐攕偟偨傜 0 埲奜傪曉偡
int InitMuiLibraryW ( const void *nType, int nId, const wchar_t *szDirectory, const wchar_t *szPrefix ) {
if ( (uintptr_t) nType > 0xFFFF ) return 1 ;
FreeConfiguration () ;
if ( szDirectory && ! ( szDllDirectoryW = wcsdup ( szDirectory ) ) ) return 1 ;
if ( szPrefix && ! ( szDllPrefixW = wcsdup ( szPrefix ) ) ) return 1 ;
if ( ! InterlockedExchange ( & IsExitProcRegistered, TRUE ) ) atexit ( ExitProc ) ;
InitResourceData ( nType, nId ) ;
return InitMuiLangId ( nType, nId ) ;
}
static int InitMuiLangId ( const void *nType, int nId ) {
int nLangId ;
if ( ! IsWin2000orLater () ) {
nLangId = GetSystemDefaultLangID () ;
}
else {
HINSTANCE hKernel32 = GetModuleHandleW ( L"KERNEL32.DLL" ) ;
GETUSERDEFAULTUILANGUAGE GetUserDefaultUILanguage = NULL ;
if ( GETPROCADDRESS ( hKernel32, GETUSERDEFAULTUILANGUAGE, GetUserDefaultUILanguage ) ) return 1 ;
nLangId = GetUserDefaultUILanguage () ;
}
if ( ! nLangId ) return 1 ;
if ( IsHaveOwnResource ( nLangId ) ) return 0 ;
if ( ! LoadMuiLibrary ( nLangId ) ) return 0 ;
nLangId = GetAlternativeLangId ( nLangId ) ;
if ( ! nLangId ) return 1 ;
if ( IsHaveOwnResource ( nLangId ) ) return 0 ;
if ( ! LoadMuiLibrary ( nLangId ) ) return 0 ;
return 1 ;
}
// 戙懼壜擻側尵岅ID傪曉偡
// 惉岟偟偨傜 0 埲奜傪曉偡
static int GetAlternativeLangId ( int nLangId ) {
if ( ! nLangId ) return 0 ;
int nPrimaryLangId = PRIMARYLANGID ( nLangId ) ;
int nSubLangId = SUBLANGID ( nLangId ) ;
if ( nPrimaryLangId == LANG_CHINESE ) {
if ( IsNT () ) {
wchar_t szBuffer [ 8 ] ;
if ( ! GetLocaleInfoW ( MAKELCID ( nLangId, SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, szBuffer, 8 ) ) *szBuffer = 0 ;
if ( ! wcscmp ( szBuffer, L"936" ) && nSubLangId != SUBLANG_CHINESE_SIMPLIFIED ) return MAKELANGID ( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ) ;
if ( ! wcscmp ( szBuffer, L"950" ) && nSubLangId != SUBLANG_CHINESE_TRADITIONAL ) return MAKELANGID ( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ) ;
}
else {
char szBuffer [ 8 ] ;
if ( ! GetLocaleInfoA ( MAKELCID ( nLangId, SORT_DEFAULT ), LOCALE_IDEFAULTANSICODEPAGE, szBuffer, 8 ) ) *szBuffer = 0 ;
if ( ! strcmp ( szBuffer, "936" ) && nSubLangId != SUBLANG_CHINESE_SIMPLIFIED ) return MAKELANGID ( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED ) ;
if ( ! strcmp ( szBuffer, "950" ) && nSubLangId != SUBLANG_CHINESE_TRADITIONAL ) return MAKELANGID ( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL ) ;
}
return 0 ;
}
if ( nPrimaryLangId == LANG_PORTUGUESE ) {
if ( nSubLangId != SUBLANG_PORTUGUESE ) return MAKELANGID ( LANG_PORTUGUESE, SUBLANG_PORTUGUESE ) ;
if ( nSubLangId != SUBLANG_PORTUGUESE_BRAZILIAN ) return MAKELANGID ( LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN ) ;
}
if ( nSubLangId != SUBLANG_DEFAULT ) return MAKELANGID ( nPrimaryLangId, SUBLANG_DEFAULT ) ;
return 0 ;
}
//////////////////////////////
// 儕僜乕僗 //
//////////////////////////////
#define LANGID_ARRAY_SIZE 0x80
static unsigned short nLangIdArray [ LANGID_ARRAY_SIZE ] ;
// 帺暘帺恎偺儕僜乕僗偺尵岅偐専嵏偡傞
static int IsHaveOwnResource ( int nLangId ) {
for ( int nCount = 0 ; nCount < LANGID_ARRAY_SIZE ; nCount ++ ) {
if ( nLangIdArray [ nCount ] == nLangId ) return 1 ;
if ( ! nLangIdArray [ nCount ] ) break ;
}
return 0 ;
}
// InitMuiResourceData 偺壓惪偗娭悢
static BOOL CALLBACK EnumResLangProcA ( HINSTANCE hInstance, const char *szType, const char *szName, unsigned short nLangId, LPARAM lParam ) {
for ( int nCount = 0 ; nCount < LANGID_ARRAY_SIZE ; nCount ++ ) {
if ( ! nLangIdArray [ nCount ] ) {
nLangIdArray [ nCount ] = nLangId ;
break ;
}
}
return TRUE ;
}
// InitMuiResourceData 偺壓惪偗娭悢
static BOOL CALLBACK EnumResLangProcW ( HINSTANCE hInstance, const wchar_t *szType, const wchar_t *szName, unsigned short nLangId, LPARAM lParam ) {
for ( int nCount = 0 ; nCount < LANGID_ARRAY_SIZE ; nCount ++ ) {
if ( ! nLangIdArray [ nCount ] ) {
nLangIdArray [ nCount ] = nLangId ;
break ;
}
}
return TRUE ;
}
// 帺暘帺恎偺儕僜乕僗偺尵岅傪弶婜壔偡傞
static int InitResourceData ( const void *nType, int nId ) {
nDefaultRsrcType = nType ;
nDefaultRsrcId = nId ;
HINSTANCE hInstance = GetResourceInstance () ;
#if ! defined _MSC_VER || _MSC_VER < 1300
EnumResourceLanguagesA ( hInstance, MAKEINTRESOURCEA ( nType ), MAKEINTRESOURCEA ( nId ), EnumResLangProcA, 0 ) ;
#else
if ( IsNT () ) EnumResourceLanguagesW ( hInstance, MAKEINTRESOURCEW ( nType ), MAKEINTRESOURCEW ( nId ), EnumResLangProcW, NULL ) ;
else EnumResourceLanguagesA ( hInstance, MAKEINTRESOURCEA ( nType ), MAKEINTRESOURCEA ( nId ), EnumResLangProcA, NULL ) ;
#endif
return 0 ;
}
//////////////////////////////
// 僼傽僀儖柤 //
//////////////////////////////
static char *GetDllDirectoryA ( char *szBuffer ) {
if ( szDllDirectoryA ) strcpy ( szBuffer, szDllDirectoryA ) ;
else if ( szDllDirectoryW ) WideCharToMultiByte ( CP_ACP, 0, szDllDirectoryW, MAX_PATH, szBuffer, MAX_PATH, NULL, NULL ) ;
else strcpy ( szBuffer, "lang" ) ;
return szBuffer ;
}
static wchar_t *GetDllDirectoryW ( wchar_t *szBuffer ) {
if ( szDllDirectoryW ) wcscpy ( szBuffer, szDllDirectoryW ) ;
else if ( szDllDirectoryA ) MultiByteToWideChar ( CP_ACP, 0, szDllDirectoryA, MAX_PATH, szBuffer, MAX_PATH ) ;
else wcscpy ( szBuffer, L"lang" ) ;
return szBuffer ;
}
static char *GetDllPrefixA ( char *szBuffer ) {
if ( szDllPrefixA ) strcpy ( szBuffer, szDllPrefixA ) ;
else if ( szDllPrefixW ) WideCharToMultiByte ( CP_ACP, 0, szDllPrefixW, MAX_PATH, szBuffer, MAX_PATH, NULL, NULL ) ;
else strcpy ( szBuffer, "" ) ;
return szBuffer ;
}
static wchar_t *GetDllPrefixW ( wchar_t *szBuffer ) {
if ( szDllPrefixW ) wcscpy ( szBuffer, szDllPrefixW ) ;
else if ( szDllPrefixA ) MultiByteToWideChar ( CP_ACP, 0, szDllPrefixA, MAX_PATH, szBuffer, MAX_PATH ) ;
else wcscpy ( szBuffer, L"" ) ;
return szBuffer ;
}
static int FreeConfiguration ( void ) {
free ( szDllDirectoryA ) ;
szDllDirectoryA = NULL ;
free ( szDllDirectoryW ) ;
szDllDirectoryW = NULL ;
free ( szDllPrefixA ) ;
szDllPrefixA = NULL ;
free ( szDllPrefixW ) ;
szDllPrefixW = NULL ;
return 0 ;
}
static void __cdecl ExitProc ( void ) {
FreeConfiguration () ;
return ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -