[GD-Windows] Asian language support (IME)
Brought to you by:
vexxed72
From: Daniel V. <vo...@ep...> - 2002-10-25 05:01:31
|
As I couldn't find much useful documentation/ examples when I was looking for a way to add Asian language support to our input code I thought I should post what works for us now so other people might have it easier than I did :) The below snippet should work fine with Japanese, Chinese and Korean Windows (even Win98) though YMMV. BTW, as a little hint - make sure you have your Korean keyboard plugged in before installing Korean Windows if you don't speak the language as otherwise you won't be able to use the IME key... had to learn that the hard way ;) Some globals. INT SupportsIME, CurrentIMESize; After creating the window. HIMC hImc = ImmGetContext( Window->hWnd ); if( !hImc ) { debugf(TEXT("Creating IME context.")); hImc = ImmCreateContext(); if( hImc ) ImmAssociateContext( Window->hWnd, hImc ); else debugf(TEXT("OS doesn't support IME.")); } else ImmReleaseContext( Window->hWnd, hImc ); SupportsIME = hImc != NULL; Once per frame (could possibly be done by handling some message but I didn't have time to look into this closer and hey, it works ;)). // IME stuff. if( SupportsIME ) { HIMC hImc = ImmGetContext( Window->hWnd ); if( !hImc ) { debugf(TEXT("Creating IME context.")); hImc = ImmCreateContext(); if( hImc ) ImmAssociateContext( Window->hWnd, hImc ); else SupportsIME = 0; CurrentIMESize = 0; } else ImmReleaseContext( Window->hWnd, hImc ); } Below is some code that handles the IME windows message. case WM_IME_COMPOSITION: { // Final composition string. if( lParam & GCS_RESULTSTR ) { HIMC hImc = ImmGetContext(Window->hWnd); if( !hImc ) appErrorf( TEXT("No IME context") ); // Get the size of the result string. INT Size = ImmGetCompositionString( hImc, GCS_RESULTSTR, NULL, 0 ); TCHAR* String = new TCHAR[Size+1]; appMemzero( String, sizeof(TCHAR) * (Size+1) ); // Get the result strings that is generated by IME. Size = ImmGetCompositionString( hImc, GCS_RESULTSTR, String, Size ); Size /= sizeof( TCHAR ); // Send backspaces. for( INT i=0; i<CurrentIMESize; i++ ) { CauseInputEvent( IK_Backspace, IST_Press ); CauseInputEvent( IK_Backspace, IST_Release ); } // Send key to input system. for( INT i=0; i<Size; i++ ) { INT Key = String[i]; if( Key ) Client->Engine->Key( this, IK_Unicode, String[i] ); } delete [] String; ImmReleaseContext(Window->hWnd, hImc); CurrentIMESize = 0; } // Composition in progress. else if( lParam & GCS_COMPSTR ) { HIMC hImc = ImmGetContext(Window->hWnd); if( !hImc ) appErrorf( TEXT("No IME context") ); // Get the size of the result string. INT Size = ImmGetCompositionString( hImc, GCS_COMPSTR, NULL, 0 ); TCHAR* String = new TCHAR[Size+1]; appMemzero( String, sizeof(TCHAR) * (Size+1) ); // Get the result strings that is generated by IME. Size = ImmGetCompositionString( hImc, GCS_COMPSTR, String, Size ); Size /= sizeof( TCHAR ); // Send backspaces. for( INT i=0; i<CurrentIMESize; i++ ) { CauseInputEvent( IK_Backspace, IST_Press ); CauseInputEvent( IK_Backspace, IST_Release ); } // Send key to input system for( INT i=0; i<Size; i++ ) { INT Key = String[i]; if( Key ) Client->Engine->Key( this, IK_Unicode, String[i] ); } delete [] String; ImmReleaseContext(Window->hWnd, hImc); CurrentIMESize = Size; } else return DefWindowProcX( Window->hWnd, iMessage, wParam, lParam ); return 0; } You only want IME stuff for chatting and not for controlling the player so here's some code that toggles it on the fly. InParamter: bool Enable if( SupportsIME ) { if( !Enable ) { ImmAssociateContext( Window->hWnd, NULL ); CurrentIMESize = 0; } else { HIMC hImc = ImmGetContext( Window->hWnd ); if( !hImc ) { debugf(TEXT("Creating IME context.")); hImc = ImmCreateContext(); if( hImc ) ImmAssociateContext( Window->hWnd, hImc ); else SupportsIME = 0; CurrentIMESize = 0; } else { ImmAssociateContext( Window->hWnd, hImc ); ImmReleaseContext( Window->hWnd, hImc ); } } } Hope this of help to someone out there :) -- Daniel, Epic Games Inc. |