SDL系列教程:SDL和IME
作者:Daniel Vogel
翻译:akinggw
前言
最近这段时间一直在为SDL不能输入中文而烦心。于是到处找这方面的文章,找是找到了,有一个台湾的朋友搞了一个SDL—IM,但是没有提供相关的设计原理,只知道要在WIN32环境下要输入中文必须使用一个叫IME(Input method editor)的东西。于是又找了一下关于IME的文章,有关于DX的,但就是没有关于SDL的。
好不容易,终于在SDL的邮件列表中发现了一个关于SDL和IME 使用的帖子,但还是不太明白,特此翻译过来与大家分享交流。
SDL和IME
当我试图让我的输入代码支持亚洲语言时,我便到处去搜集文章,可惜的是这方面的文章实在是太少了。为此,我将我自己在这方面的研究成果承上来,也许对你有所帮助。
下面的代码可以很好的工作在日语,中文和韩文窗口上。
首先,让我们定义一些全局的。
Int SupportsIME, CurrentIMESize;
然后建立IME窗口。
HIMC hImc=ImmGetContext(Window->hWnd);
If(!hImc)
{
debugf(TEXT(“Creating IME context.”));
hImc=ImmCreaeContext();
if(hImc)
ImmAssociateContext(Window->hWnd,hImc);
Else
Debugf(TEXT(“OS doesn’t support IME.”));
}
else
ImmReleaseContext(Window->hWnd,hImc);
SupportsIME=hImc !=NULL;
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);
}
下面的代码是用来处理IME窗口消息的。
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);
}
// Snd 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;
}
// Compsition 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;
}
如果你只是希望IME缓冲用于聊天,那么你可以象下面这样写。
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);
}
}
}
|