📄 imeui.cpp
字号:
ImeUiCallback_Free( (HANDLE)lpCandList );
_ImmReleaseContext(hWnd, himc);
// don't display selection in candidate list in case of Korean and old Chinese IME.
if ( GETPRIMLANG() == LANG_KOREAN ||
GETLANG() == LANG_CHT && !GetImeId() )
g_dwSelection = (DWORD)-1;
}
break;
}
case IMN_CLOSECANDIDATE:
if ( g_bUILessMode )
{
break;
}
CloseCandidateList();
*trapped = true;
break;
// Jun.16,2000 05:21 by yutaka.
case IMN_PRIVATE:
{
if ( !g_bCandList )
{
GetReadingString( hWnd );
}
// Trap some messages to hide reading window
DWORD dwId = GetImeId();
switch (dwId) {
case IMEID_CHT_VER42:
case IMEID_CHT_VER43:
case IMEID_CHT_VER44:
case IMEID_CHS_VER41:
case IMEID_CHS_VER42:
if ((lParam == 1) || (lParam == 2))
{
*trapped = true;
}
break;
case IMEID_CHT_VER50:
case IMEID_CHT_VER51:
case IMEID_CHT_VER52:
case IMEID_CHT_VER60:
case IMEID_CHS_VER53:
if ((lParam == 16) || (lParam == 17) || (lParam == 26) || (lParam == 27) || (lParam == 28))
{
*trapped = true;
}
break;
}
}
break;
default:
*trapped = true;
break;
}
break;
// fix for #15386 - When Text Service Framework is installed in Win2K, Alt+Shift and Ctrl+Shift combination (to switch
// input locale / keyboard layout) doesn't send WM_KEYUP message for the key that is released first. We need to check
// if these keys are actually up whenever we receive key up message for other keys.
case WM_KEYUP:
case WM_SYSKEYUP:
if ( !( lAlt & 0x80000000 ) && wParam != VK_MENU && ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) == 0 )
{
PostMessageA( GetFocus(), WM_KEYUP, (WPARAM)VK_MENU, ( lAlt & 0x01ff0000 ) | 0xC0000001 );
}
else if ( !( lCtrl & 0x80000000 ) && wParam != VK_CONTROL && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) == 0 )
{
PostMessageA( GetFocus(), WM_KEYUP, (WPARAM)VK_CONTROL, ( lCtrl & 0x01ff0000 ) | 0xC0000001 );
}
else if ( !( lShift & 0x80000000 ) && wParam != VK_SHIFT && ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 ) == 0 )
{
PostMessageA( GetFocus(), WM_KEYUP, (WPARAM)VK_SHIFT, ( lShift & 0x01ff0000 ) | 0xC0000001 );
}
// fall through WM_KEYDOWN / WM_SYSKEYDOWN
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
switch ( wParam )
{
case VK_MENU:
lAlt = lParam;
break;
case VK_SHIFT:
lShift = lParam;
break;
case VK_CONTROL:
lCtrl = lParam;
break;
}
}
break;
}
return 0;
}
void ImeUi_SetCaretPosition(UINT x, UINT y)
{
if (!g_bInitialized)
return;
g_CaretInfo.caretX = x;
g_CaretInfo.caretY = y;
}
void ImeUi_SetCompStringAppearance( CImeUiFont_Base* pFont, DWORD color, const RECT* prc )
{
if (!g_bInitialized)
return;
g_CaretInfo.pFont = pFont;
g_CaretInfo.margins = *prc;
if (0 == gSkinIME.candColorText)
g_CaretInfo.colorCand = color;
else
g_CaretInfo.colorCand = gSkinIME.candColorText;
if (0 == gSkinIME.compColorText)
g_CaretInfo.colorComp = color;
else
g_CaretInfo.colorComp = gSkinIME.compColorText;
}
void ImeUi_SetState( DWORD dwState )
{
if (!g_bInitialized)
return;
HIMC himc;
if ( dwState == IMEUI_STATE_ON )
{
ImeUi_EnableIme( true );
}
if (NULL != (himc = _ImmGetContext(g_hwndCurr)))
{
if (g_bDisableImeCompletely)
dwState = IMEUI_STATE_OFF;
bool bOn = dwState == IMEUI_STATE_ON; // for non-Chinese IME
switch ( GETPRIMLANG() ) {
case LANG_CHINESE:
{
// toggle Chinese IME
DWORD dwId;
DWORD dwConvMode = 0, dwSentMode = 0;
if ( ( g_bChineseIME && dwState == IMEUI_STATE_OFF ) || ( !g_bChineseIME && dwState != IMEUI_STATE_OFF ) )
{
_ImmSimulateHotKey( g_hwndCurr, IME_THOTKEY_IME_NONIME_TOGGLE );
_PumpMessage();
}
if ( dwState != IMEUI_STATE_OFF )
{
dwId = GetImeId();
if ( dwId )
{
_ImmGetConversionStatus( himc, &dwConvMode, &dwSentMode );
dwConvMode = ( dwState == IMEUI_STATE_ON )
? ( dwConvMode | IME_CMODE_NATIVE )
: ( dwConvMode & ~IME_CMODE_NATIVE );
_ImmSetConversionStatus( himc, dwConvMode, dwSentMode );
}
}
break;
}
case LANG_KOREAN:
// toggle Korean IME
if ( ( bOn && g_dwState != IMEUI_STATE_ON ) || ( !bOn && g_dwState == IMEUI_STATE_ON ) )
{
_ImmSimulateHotKey(g_hwndCurr, IME_KHOTKEY_ENGLISH);
}
break;
case LANG_JAPANESE:
_ImmSetOpenStatus(himc, bOn);
break;
}
_ImmReleaseContext(g_hwndCurr, himc);
CheckToggleState();
}
}
DWORD ImeUi_GetState()
{
if (!g_bInitialized)
return IMEUI_STATE_OFF;
CheckToggleState();
return g_dwState;
}
void ImeUi_EnableIme( bool bEnable )
{
if (!g_bInitialized || !g_hwndCurr)
return;
if (g_bDisableImeCompletely)
bEnable = false;
if (g_hwndCurr == g_hwndMain)
{
HIMC himcDbg;
himcDbg = _ImmAssociateContext( g_hwndCurr, bEnable? g_himcOrg : NULL );
}
g_bImeEnabled = bEnable;
if ( bEnable )
{
CheckToggleState();
}
CTsfUiLessMode::EnableUiUpdates(bEnable);
}
bool ImeUi_IsEnabled( void )
{
return g_bImeEnabled;
}
bool ImeUi_Initialize( HWND hwnd, bool bDisable )
{
if ( g_bInitialized )
{
return true;
}
g_hwndMain = hwnd;
g_disableCicero.Initialize();
g_osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
GetVersionExA(&g_osi);
bool bUnicodeImm = false;
// IMM in NT or Win98 supports Unicode
if ( g_osi.dwPlatformId == VER_PLATFORM_WIN32_NT ||
( g_osi.dwMajorVersion > 4 ) ||
( g_osi.dwMajorVersion == 4 ) && ( g_osi.dwMinorVersion > 0 ) ) {
bUnicodeImm = true;
}
g_hImmDll = LoadLibraryA( "imm32.dll" );
g_bDisableImeCompletely = false;
if ( g_hImmDll )
{
_ImmLockIMC = (LPINPUTCONTEXT2 (WINAPI*)(HIMC hIMC)) GetProcAddress(g_hImmDll, "ImmLockIMC");
_ImmUnlockIMC = (BOOL (WINAPI*)(HIMC hIMC)) GetProcAddress(g_hImmDll, "ImmUnlockIMC");
_ImmLockIMCC = (LPVOID (WINAPI*)(HIMCC hIMCC)) GetProcAddress(g_hImmDll, "ImmLockIMCC");
_ImmUnlockIMCC = (BOOL (WINAPI*)(HIMCC hIMCC)) GetProcAddress(g_hImmDll, "ImmUnlockIMCC");
BOOL (WINAPI* _ImmDisableTextFrameService)(DWORD) = (BOOL (WINAPI*)(DWORD))GetProcAddress(g_hImmDll, "ImmDisableTextFrameService");
if ( _ImmDisableTextFrameService )
{
_ImmDisableTextFrameService( (DWORD)-1 );
}
}
else
{
g_bDisableImeCompletely = true;
return false;
}
#ifdef UNICODE
if ( bUnicodeImm )
{
_ImmGetCompositionString = ImmGetCompositionStringW;
_ImmGetCandidateList = ImmGetCandidateListW;
_GetCandidateList = GetCandidateList;
}
else
{
_ImmGetCandidateList = ImmGetCandidateListA;
_ImmGetCompositionString = AW_ImmGetCompositionString;
_GetCandidateList = AW_GetCandidateList;
}
#else
if ( bUnicodeImm )
{
_ImmGetCompositionString = WA_ImmGetCompositionString;
_ImmGetCandidateList = ImmGetCandidateListA;
_GetCandidateList = WA_GetCandidateList;
}
else
{
_ImmGetCompositionString = ImmGetCompositionStringA;
_ImmGetCandidateList = ImmGetCandidateListA;
_GetCandidateList = GetCandidateList;
}
#endif
// There are the following combinations of code config, window type, and the method of sending characters.
// Wnd: Unicode, Code: Unicode, Method: SendMessageW (SendMessageW must be supported since RegisterClassW is successful)
// Wnd: non Uni, Code: Unicode, Method: AW_SendCompString (Send characters in multibyte after W->A conversion)
// Wnd: Unicode, Code: non Uni, Method: SendMessageA (System does A->W conversion) - possible, but unlikely to be used.
// Wnd: non Uni, Code: non Uni, Method: SendMessageA
#ifdef UNICODE
if ( !IsWindowUnicode( hwnd ) )
{
_SendCompString = AW_SendCompString;
}
else
#endif
{
_SendCompString = SendCompString;
#ifdef UNICODE
_SendMessage = SendMessageW;
#endif
}
// turn init flag on so that subsequent calls to ImeUi functions work.
g_bInitialized = true;
ImeUi_SetWindow( g_hwndMain );
g_himcOrg = _ImmGetContext( g_hwndMain );
_ImmReleaseContext( g_hwndMain, g_himcOrg );
if ( !g_himcOrg )
{
bDisable = true;
}
// the following pointers to function has to be initialized before this function is called.
if ( bDisable ||
!ImeUiCallback_Malloc ||
!ImeUiCallback_Free
)
{
g_bDisableImeCompletely = true;
ImeUi_EnableIme(false);
g_bInitialized = bDisable;
return false;
}
g_uCaretBlinkTime = GetCaretBlinkTime();
#ifndef UNICODE
// Check if system is SBCS system
CPINFO cpi;
BOOL bRc = GetCPInfo(CP_ACP, &cpi);
if (bRc) {
if (cpi.MaxCharSize == 1)
{
g_bDisableImeCompletely = true; // SBCS system. Disable IME.
}
}
#endif
g_CaretInfo.caretX = 0;
g_CaretInfo.caretY = 0;
g_CaretInfo.pFont = 0;
g_CaretInfo.colorComp = 0;
g_CaretInfo.colorCand = 0;
g_CaretInfo.margins.left = 0;
g_CaretInfo.margins.right = 640;
g_CaretInfo.margins.top = 0;
g_CaretInfo.margins.bottom = 480;
CheckInputLocale();
OnInputLangChangeWorker();
ImeUi_SetSupportLevel(2);
// SetupTSFSinks has to be called before CheckToggleState to make it work correctly.
g_bUILessMode = CTsfUiLessMode::SetupSinks() != FALSE;
CheckToggleState();
if ( g_bUILessMode )
{
g_bChineseIME = ( GETPRIMLANG() == LANG_CHINESE ) && CTsfUiLessMode::CurrentInputLocaleIsIme();
CTsfUiLessMode::UpdateImeState();
}
ImeUi_EnableIme(false);
return true;
}
void ImeUi_Uninitialize()
{
if ( !g_bInitialized )
{
return;
}
CTsfUiLessMode::ReleaseSinks();
if ( g_hwndMain )
{
ImmAssociateContext(g_hwndMain, g_himcOrg);
}
g_hwndMain = NULL;
g_himcOrg = NULL;
if ( g_hImmDll )
{
FreeLibrary(g_hImmDll);
g_hImmDll = NULL;
}
g_disableCicero.Uninitialize();
g_bInitialized = false;
}
//
// GetImeId( UINT uIndex )
// returns
// returned value:
// 0: In the following cases
// - Non Chinese IME input locale
// - Older Chinese IME
// - Other error cases
//
// Othewise:
// When uIndex is 0 (default)
// bit 31-24: Major version
// bit 23-16: Minor version
// bit 15-0: Language ID
// When uIndex is 1
// pVerFixedInfo->dwFileVersionLS
//
// Use IMEID_VER and IMEID_LANG macro to extract version and language information.
//
static DWORD GetImeId( UINT uIndex )
{
static HKL hklPrev = 0;
static DWORD dwRet[2] = {0, 0};
DWORD dwVerSize;
DWORD dwVerHandle;
LPVOID lpVerBuffer;
LPVOID lpVerData;
UINT cbVerData;
char szTmp[1024];
if ( uIndex >= sizeof( dwRet ) / sizeof( dwRet[0] ) )
return 0;
HKL kl = g_hklCurrent;
if (hklPrev == kl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -