实验六 CeGUI与中文支持的这点破事
用的是0.7.5版本,问题其实早已不难,自己瞎捣鼓半天,虽然搞定,但终究不得正法,
还是好好静下来看下前辈们的文章好,顺便进行一些无脑的Ctrl+C/V操纵,纯当烂笔头:
1,首先是中文显示:
这个其实都差不多,其实就是一个utf8转换的问题,
估计是旧时代遗留下来节约内存的习惯吧,问题虽然不大,改天有空我一定要重新编一个Unicode版本的CeGUi(ms也有前辈做过,可惜未找到共享),
我的具体解决方法:
首先加载字体(改动schema也行):
FontManager::getSingleton().createFreeTypeFont("JianTi", 10/*pt*/, true, "jianti.ttf"); System::getSingleton().setDefaultFont("JianTi");
然后,转换utf8:(如在FalagardDemo1中:)
CEGUI::Window *quit = winMgr.createWindow("Vanilla/Button", "CEGUIDemo/QuitButton");
quit->setText("Quit");
quit->setSize(CEGUI::UVector2(CEGUI::UDim(0.15, 0), CEGUI::UDim(0.05, 0)));
background->addChildWindow(quit);
std::wstring aa = L"我管你123还是abc就算あいうえお也可以!";
char buff[128] = "";
WideCharToMultiByte(CP_UTF8, 0, aa.c_str(), aa.size(), buff, sizeof(buff), 0, 0);
quit->setText((CEGUI::utf8*)buff);
-----代码标色的插件有挂了,将就下先~
2,基本原理(抓住本质才能解决根本问题):
痞子龙3D编程(unicode,ANSI,UTF-8的故事):
http://blog.csdn.net/pizi0475/archive/2010/03.aspx
中文编码之间的转换:
http://blog.csdn.net/s030702614/archive/2010/06/27/5698026.aspx
3,中文输入:
CEGUI学习笔记四-- 如何输入中文 - 踏入神的领域 :
http://blog.csdn.net/kun1234567/archive/2008/04/15/2294125.aspx
一个总结:CEGUI说明文档_百度文库:
http://wenku.baidu.com/view/fd635312a216147917112858.html
CEGUI与其他程序剪切复制粘帖的实现(支持中文)~~~ - 李素颙~Harry的专栏:
http://blog.csdn.net/harr999y/archive/2010/06/02/5643269.aspx
研究cegui,写脚本 - lonelyfish的日志 :
http://songxiaoyu8.blog.163.com/blog/static/2081812820096232432677/
CEGUI学习笔记:
http://blog.csdn.net/feiyun1987/archive/2009/05/29/4224488.aspx
其实问题的关键很简单,就是预留一个字符,
把CeGUI对字符输入的响应截取下来即可:
好吧,动手!
修改common\src\Win32AppHelper.cpp
#include <imm.h>
#pragma comment(lib,"imm32.lib")
加入有输入法时的处理函数:
namespace CEGUI{
bool _injectChar(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';
utf32 code = (utf32)s_tempWchar[0];
//Font* fnt = System::getSingleton().getDefaultFont();
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
}
}
再改下:
case WM_CHAR:
if (ImmIsIME(GetKeyboardLayout(0)))
{
CEGUI::_injectChar(wParam);
}
else
{
CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
}
break;
熟悉win32的话这一切就实在是so easy了~~
4,Bug
引用一下:“
还有一个问题就是关于BackSpace的:如果你在输入框里有字,这个时候输入法输入框里输入错了一个字符,当你按backspace的时候,CEGUI里的输入框上的字也被删了一个。这不是我们期望的行为,解决这个问题有很多途径,你可以在中间渲染层进行这些输入事件插入之前进行判断,也可以注册监听事件进行处理,但是我认为最正确的方法是在需要进行输入法输入的地方,比如EditBox的事件处理函数里特别处理backspace,当然,这需要修改CEGUIEditbox的源代码,不过这件事并不困难。。。。”
好吧,我承认还不了解CEGUIEditbox,但我会尽快KO的!
(ps:虽然绕了不少弯路,憋气斗气不少,但是多看了许多CeGUi的源代码,就像江湖好汉似的不打不相识,了解其些许的内部,如此亦为甚妙,心得体会真还算不上,就暂且厚颜先贴些网址上来吧,相信,很快会到运用自如的境界的,兔年,好运,奋斗~~O(∩_∩)O哈哈~~)
5,Bug解决——110204补充:
网上乱逛,无意中看了一些MyGUI对中文输入处理的代码,
眉头一皱计上心来,
问题的关键还是在于在用输入法时截取退格(Code:8)对EditBox的注入,
首先还是对Win32AppHelper的改造:
毛早就毛躁点吧,首先标记下:
bool g_bImming=false;
再在Win32AppHelper::wndProc
case WM_IME_STARTCOMPOSITION:
g_bImming =true;
break;
case WM_IME_ENDCOMPOSITION:
g_bImming =false;
break;
本以为接下来会很简单的,可接下来跟踪,很是莫名奇妙,看源代码,原来是退格的消息不仅在WM_CHAR中响应,还直接注入了EditBoxz中,
case Key::Backspace:
handleBackspace();
break;
尝试在这里修改,出bug,而且也不合适,
估摸着自己玩网游时候打字不就是禁用了其他快捷键的响应,于是直接hack:
在Win32AppHelper::doDirectInputEvents中修改:
if (itemCount > 0)
{
if (LOBYTE(devDat.dwData) & 0x80)
{
// force quit on ESCAPE key
if (devDat.dwOfs == CEGUI::Key::Escape)
{
PostQuitMessage(0);
}
else
{
if(!g_bImming)
CEGUI::System::getSingleton().injectKeyDown(devDat.dwOfs);
}
}
else
{
CEGUI::System::getSingleton().injectKeyUp(devDat.dwOfs);
}
}
问题成功解决,
ps:
发现窗口最小化后会有时丢失,不知道是不是在Debug的缘故,还待深究,
另外,被网友说动了,去试试MyGUI,管它俄文看不懂,坚决不涅都~~~呵呵