实验六 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);

image

-----代码标色的插件有挂了,将就下先~

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;

image

熟悉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,管它俄文看不懂,坚决不涅都~~~呵呵

原文地址:https://www.cnblogs.com/Zephyroal/p/1949057.html