Use WM_CHAR to support other natural language(Chinese) input
by Yanzheng · in Technical Issues · 09/09/2007 (4:20 am) · 13 replies
TGEA support unicode,but inputting other natural languages(except english) is difficult.Now i will show you a easy way to use the WM_CHAR message to support language input,for example chinese.
first,we should understand one thing,that when macro UNICODE is difined,the WM_CHAR will return the combination char of the Languages, decided by Locales, and Keyboard Layouts,not the keycode user pressed.
The WM_CHAR message uses Unicode transformation format (UTF)-16.
The TranslateMessage function generates a WM_CHAR message when the user presses any of the following keys:
Any character key
BACKSPACE
ENTER (carriage return)
ESC
SHIFT+ENTER (linefeed)
TAB
about WM_CHAR,it is enough.So let us see the code can support input.
first i add a new event type ,which is used to point when the message to be processed,in event.h,i add
/// Input device types
second:
i change some code in the winwindows.cpp to support transfer the WM_CHAR
1,Add a variable to store the language input state
first,we should understand one thing,that when macro UNICODE is difined,the WM_CHAR will return the combination char of the Languages, decided by Locales, and Keyboard Layouts,not the keycode user pressed.
The WM_CHAR message uses Unicode transformation format (UTF)-16.
The TranslateMessage function generates a WM_CHAR message when the user presses any of the following keys:
Any character key
BACKSPACE
ENTER (carriage return)
ESC
SHIFT+ENTER (linefeed)
TAB
about WM_CHAR,it is enough.So let us see the code can support input.
first i add a new event type ,which is used to point when the message to be processed,in event.h,i add
/// Input device types
enum InputDeviceTypes
{
UnknownDeviceType,
MouseDeviceType,
KeyboardDeviceType,
JoystickDeviceType,
#ifdef TORQUE_OS_WIN32 // XInput support for Windows (Xbox 360 Controllers) -- jason_cahill
XInputDeviceType,
#endif
ImmCharInput, //imm char input
};the enum ImmCharInput is used to point a wm_char message is to be dealed with.second:
i change some code in the winwindows.cpp to support transfer the WM_CHAR
1,Add a variable to store the language input state
bool chineseInput = false; //global variable when chinese is inputing
#2
in GuiTextEditCtrl::onKeyDown(const GuiEvent &event) ,we add some code :
oh,sorry i forget a very import message to control the language input state .
back to the winwindows.h,add some code in void OurDispatchMessages() function:
in the last of the function,i add some code:
09/09/2007 (4:23 am)
3,change code in the onkeydown function to avoid deal with some unwanted keydown messagein GuiTextEditCtrl::onKeyDown(const GuiEvent &event) ,we add some code :
//-------------new code----------------// if(chineseInput) return true; //--------------end---------------------// if ( mFont->isValidChar( event.ascii ) )
oh,sorry i forget a very import message to control the language input state .
back to the winwindows.h,add some code in void OurDispatchMessages() function:
in the last of the function,i add some code:
switch(message)
{
case WM_INPUTLANGCHANGE:
{
switch( LOWORD(lParam))
{
case LID_TRADITIONAL_CHINESE:
case LID_JAPANESE:
case LID_KOREAN:
case LID_SIMPLIFIED_CHINESE:
chineseInput = true;
break;
default:
chineseInput = false;
break;
};
}
break;
case WM_CHAR:
{
if(chineseInput)
{
processWmCharMessage(message, wParam, lParam);
}
}
break;
}now,every thing is ok,input your chinese now,of course,In theory korean,japanese can work too.but i didn't test them.
#3
09/09/2007 (4:24 am)
I lost language id,which is defined by windows:// Define language ID #define LID_TRADITIONAL_CHINESE 0x0404 #define LID_JAPANESE 0x0411 #define LID_KOREAN 0x0412 #define LID_SIMPLIFIED_CHINESE 0x0804
#4
09/10/2007 (1:12 am)
Of course,you should also define onWmChar(const GuiEvent &event) in GuiControl your self
#5
09/10/2007 (6:10 am)
In GuiCanvas.cpp,we add else if(event->deviceType == ImmCharInput)
{
if (mFirstResponder)
{
mLastEvent.ascii = event->ascii;
mLastEvent.modifier = event->modifier;
mLastEvent.keyCode = event->objInst;
if(mFirstResponder->onWmChar(mLastEvent))
return true;
}
}in the end of the function processInputEvent function
#6
11/09/2008 (11:02 pm)
作者辛苦了
#7
11/10/2008 (12:36 am)
What's that
#8
11/15/2008 (5:36 am)
It's Chinese, thank you for your contribution. I thought your post should be in Chinese instead of English, because it is really for Chinese developers.
#9
02/16/2009 (5:57 pm)
Hi!Yanzheng, I'm a Chinese developer,so i want to input in chinese and have something to resoved.Thank for your contribution,But i don't understand about "Game->postEvent(event)".
#10
you should read more code of the engine.it is the basic Mechanism of torque.if you don't post the event,the loop will not process the event,and you will not get the result.
02/16/2009 (6:03 pm)
Game->postEvent(event)?you should read more code of the engine.it is the basic Mechanism of torque.if you don't post the event,the loop will not process the event,and you will not get the result.
#11
I know how to input chinese in TGE. I'm having some difficulty understanding how to input chinese in TGEA.I expect you give me suggestion. Very ths
02/16/2009 (11:12 pm)
I'm very glad to see your reply. And thank you for replying my question.I know how to input chinese in TGE. I'm having some difficulty understanding how to input chinese in TGEA.I expect you give me suggestion. Very ths
#12
It is the basic of IME Windows
02/18/2009 (1:14 am)
HI Yanzheng,I have knew how to input chinese in TGEA, and resoved it.It is the basic of IME Windows
#13
02/18/2009 (1:18 am)
congratulation!
Torque Owner Yanzheng
//-------------------------------------- static void processWmCharMessage(UINT message, WPARAM wParam, LPARAM lParam) { switch(wParam) { case 0x08: //backspace case 0x0A: //linefeed case 0x09: //escape case 0x1B: //table case 0x0D: //enter return; //because the torque support the keydown process,so we don't transfer it to the wm_char process function break; } InputEvent event; event.deviceInst = 0; event.deviceType = ImmCharInput; event.objType = 0; event.objInst = 0; event.action = 0; event.modifier = 0; event.ascii = wParam; event.fValue = 0.0; Game->postEvent(event); }now ,everything is ok,what we will do is changing code in the GuiTextEditCtrl.cpp to support chinese input:
1,add code :
2,add wm_char process function
bool GuiTextEditCtrl::onWmChar(const GuiEvent &event) { if(! isActive()) return false; S32 stringLen = mTextBuffer.length(); if ( mFont->isValidChar( event.ascii ) ) { // Get the character ready to add to a UTF8 string. UTF16 conv[2] = { event.ascii, 0 }; StringBuffer convertedChar(conv); //see if it's a number field if ( mProfile->mNumbersOnly ) { if (event.ascii == '-') { //a minus sign only exists at the beginning, and only a single minus sign if ( mCursorPos != 0 ) { playDeniedSound(); return true; } if ( mInsertOn && ( mTextBuffer.getChar(0) == '-' ) ) { playDeniedSound(); return true; } } // BJTODO: This is probably not unicode safe. else if ( event.ascii < '0' || event.ascii > '9' ) { playDeniedSound(); return true; } } //save the current state saveUndoState(); //delete anything highlighted if ( mBlockEnd > 0 ) { mTextBuffer.cut(mBlockStart, mBlockEnd-mBlockStart); mCursorPos = mBlockStart; mBlockStart = 0; mBlockEnd = 0; } if ( ( mInsertOn && ( stringLen < mMaxStrLen ) ) || ( !mInsertOn && ( mCursorPos < mMaxStrLen ) ) ) { if ( mCursorPos == stringLen ) { mTextBuffer.append(convertedChar); mCursorPos++; } else { if ( mInsertOn ) { mTextBuffer.insert(mCursorPos, convertedChar); mCursorPos++; } else { mTextBuffer.cut(mCursorPos, 1); mTextBuffer.insert(mCursorPos, convertedChar); mCursorPos++; } } } else playDeniedSound(); //reset the history index mHistoryDirty = true; //execute the console command if it exists execConsoleCallback(); return true; } //not handled - pass the event to it's parent return Parent::onWmChar( event ); }