先来说下如何把中文输入进入。
先添加一个中文注入的函数:
/// 中文输入注入字符 (Added by Azure)
static bool ChnInjectChar(CEGUI::utf32 code_point);
///
static bool ChnInjectChar(CEGUI::utf32 code_point);
///
bool Win32AppHelper::ChnInjectChar(CEGUI::utf32 code_point)
{
#ifndef UNICODE
static char s_tempChar[3] = "";
static wchar_t s_tempWchar[2] = L"";
static bool s_flag = false;
unsigned char uch = (unsigned char)code_point;
if( uch >= 0xA1 )
{
if( !s_flag )
{
s_tempChar[0] = (char)uch; //第一个字节
s_flag = true;
return true;
}
else if( uch >= 0xA1 )
{
s_tempChar[1] = (char)uch; //第二个字节
s_flag = false;
MultiByteToWideChar( 0, 0, s_tempChar, 2, s_tempWchar, 1); //转成宽字节
s_tempWchar[1] = L'\0';
CEGUI::utf32 code = (CEGUI::utf32)s_tempWchar[0];
return CEGUI::System::getSingleton().injectChar( code );
}
else
{
return CEGUI::System::getSingleton().injectChar(code_point);
}
}
else
{
s_flag = false;
return CEGUI::System::getSingleton().injectChar(code_point);
}
#else
return CEGUI::System::getSingleton().injectChar(code_point );
#endif
}
{
#ifndef UNICODE
static char s_tempChar[3] = "";
static wchar_t s_tempWchar[2] = L"";
static bool s_flag = false;
unsigned char uch = (unsigned char)code_point;
if( uch >= 0xA1 )
{
if( !s_flag )
{
s_tempChar[0] = (char)uch; //第一个字节
s_flag = true;
return true;
}
else if( uch >= 0xA1 )
{
s_tempChar[1] = (char)uch; //第二个字节
s_flag = false;
MultiByteToWideChar( 0, 0, s_tempChar, 2, s_tempWchar, 1); //转成宽字节
s_tempWchar[1] = L'\0';
CEGUI::utf32 code = (CEGUI::utf32)s_tempWchar[0];
return CEGUI::System::getSingleton().injectChar( code );
}
else
{
return CEGUI::System::getSingleton().injectChar(code_point);
}
}
else
{
s_flag = false;
return CEGUI::System::getSingleton().injectChar(code_point);
}
#else
return CEGUI::System::getSingleton().injectChar(code_point );
#endif
}
然后在WndProc回调函数中添加:
case WM_CHAR:
// 不要这个
//CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
// 改用自己的注入
ChnInjectChar((CEGUI::utf32)wParam);
break;
// 不要这个
//CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
// 改用自己的注入
ChnInjectChar((CEGUI::utf32)wParam);
break;
下面我们来添加控制按键的处理。
由于wParam不能直接传入CEGUI中,我们必须写一个虚拟按键到扫描码的翻译函数,我们添加下面一个函数。
/// 虚拟按键转扫描码 (Added by Azure)
static UINT VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam);
static UINT VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam);
UINT Win32AppHelper::VirtualKeyToScanCode(WPARAM wParam, LPARAM lParam)
{
if(HIWORD(lParam) & 0x0F00)
{
UINT scancode = MapVirtualKey(wParam, 0);
return scancode | 0x80;
}
else
{
return HIWORD(lParam) & 0x00FF;
}
}
{
if(HIWORD(lParam) & 0x0F00)
{
UINT scancode = MapVirtualKey(wParam, 0);
return scancode | 0x80;
}
else
{
return HIWORD(lParam) & 0x00FF;
}
}
case WM_KEYDOWN:
{
//输入法跟随
IMEFollow(hWnd);
//输入法状态时,输入不传递到UI系统中去。
UINT vk = (UINT)ImmGetVirtualKey(hWnd);
if(vk == wParam)
break;
CEGUI::System::getSingleton().injectKeyDown((CEGUI::utf32)( VirtualKeyToScanCode(wParam, lParam)));
}
break;
case WM_KEYUP:
CEGUI::System::getSingleton().injectKeyUp((CEGUI::utf32)( VirtualKeyToScanCode(wParam, lParam)));
break;
{
//输入法跟随
IMEFollow(hWnd);
//输入法状态时,输入不传递到UI系统中去。
UINT vk = (UINT)ImmGetVirtualKey(hWnd);
if(vk == wParam)
break;
CEGUI::System::getSingleton().injectKeyDown((CEGUI::utf32)( VirtualKeyToScanCode(wParam, lParam)));
}
break;
case WM_KEYUP:
CEGUI::System::getSingleton().injectKeyUp((CEGUI::utf32)( VirtualKeyToScanCode(wParam, lParam)));
break;
关于输入法跟随的函数体为:
/// 获得输入框的坐标 (Added by Azure)
static bool getFocusedInputBoxCoord(POINT& point, float& height);
// 输入法跟随 (Added by Azure)
static bool IMEFollow(HWND hWnd);
static bool getFocusedInputBoxCoord(POINT& point, float& height);
// 输入法跟随 (Added by Azure)
static bool IMEFollow(HWND hWnd);
bool Win32AppHelper::getFocusedInputBoxCoord(POINT& point, float& height)
{
//寻找到有输入焦点的EditBox的左上坐标
//遍历所有窗口
CEGUI::WindowManager::WindowIterator wit = CEGUI::WindowManager::getSingleton().getIterator();
while(!wit.isAtEnd())
{
const CEGUI::Window* widget = (*wit)->getActiveChild();
//如果是EditBox或者MultiLineEditBox
if(widget)
{
CEGUI::String windowType = widget->getType();
if(windowType == "Vanilla/Editbox") //根据具体的scheme来修改。
{
const CEGUI::UVector2& winPos = widget->getPosition();
height = widget->getPixelRect().getHeight();
CEGUI::Vector2 winPos1 = CEGUI::CoordConverter::windowToScreen(*widget, winPos);
point.x = winPos1.d_x;
point.y = winPos1.d_y;
return true;
}
}
wit++;
}
return false;
}
bool Win32AppHelper::IMEFollow(HWND hWnd)
{
//判断输入法是否打开
if (!ImmIsIME(GetKeyboardLayout(0)))
return false;
//获得输入框左上坐标
bool result;
POINT point;
float height;
result = getFocusedInputBoxCoord(point, height);
if(!result)
return false;
//获得客户区的坐标
RECT rect;
GetClientRect(hWnd, &rect);
point.x+=rect.left;
point.y+=rect.top;
//设置输入法位置
HIMC hImc = ImmGetContext(hWnd);
if(hImc==NULL) return false;
COMPOSITIONFORM form;
ImmGetCompositionWindow(hImc, &form);
form.ptCurrentPos.x = point.x;
form.ptCurrentPos.y = point.y + height;
ImmSetCompositionWindow(hImc, &form);
return true;
}
{
//寻找到有输入焦点的EditBox的左上坐标
//遍历所有窗口
CEGUI::WindowManager::WindowIterator wit = CEGUI::WindowManager::getSingleton().getIterator();
while(!wit.isAtEnd())
{
const CEGUI::Window* widget = (*wit)->getActiveChild();
//如果是EditBox或者MultiLineEditBox
if(widget)
{
CEGUI::String windowType = widget->getType();
if(windowType == "Vanilla/Editbox") //根据具体的scheme来修改。
{
const CEGUI::UVector2& winPos = widget->getPosition();
height = widget->getPixelRect().getHeight();
CEGUI::Vector2 winPos1 = CEGUI::CoordConverter::windowToScreen(*widget, winPos);
point.x = winPos1.d_x;
point.y = winPos1.d_y;
return true;
}
}
wit++;
}
return false;
}
bool Win32AppHelper::IMEFollow(HWND hWnd)
{
//判断输入法是否打开
if (!ImmIsIME(GetKeyboardLayout(0)))
return false;
//获得输入框左上坐标
bool result;
POINT point;
float height;
result = getFocusedInputBoxCoord(point, height);
if(!result)
return false;
//获得客户区的坐标
RECT rect;
GetClientRect(hWnd, &rect);
point.x+=rect.left;
point.y+=rect.top;
//设置输入法位置
HIMC hImc = ImmGetContext(hWnd);
if(hImc==NULL) return false;
COMPOSITIONFORM form;
ImmGetCompositionWindow(hImc, &form);
form.ptCurrentPos.x = point.x;
form.ptCurrentPos.y = point.y + height;
ImmSetCompositionWindow(hImc, &form);
return true;
}
相关参考代码如下:
![](http://www.azure.com.cn/styles/default/images/icon_file.gif)