写3d程序没个像样的GUI界面可不行,最近没啥事也来捣腾一下CEGUI。果然是个不错的东东,用起来很方便,新版本已经支持dx10了,就是对中文的支持还是那么“不主动”。
1,中文显示,这个到处都能找到解决方法。就是装载一个支持中文显示的font,然后保存程序代码的时候选择
正确的utf8编码。有的说保存成“带签名utf8”,可是我的保存成“不带签名utf8”才正确。
2,中文输入,这个似乎不是那么复杂了,只要在响应WM_CHAR消息的时候直接调用“injectChar
((CEGUI::utf32)wParam)”就行了(有的说要对中文的"wParam"进行合并,有的说要转成宽字符,而我是在DXUT
框架的MsgProc中调用injectChar的,直接传入就行)。另外还要注意的一个是injectKeyDown、injectKeyUp的
传参是键盘扫描码,要是字符的话就用MapVirtualKey转化一下。
3,让EditBox响应 Ctrl+C Ctrl+V 的复制粘贴事件。这个捣了好久,终于还是搞定了。主要是CEGUI自带的String和标准的string的中文编码不一致,要相互转换。
首先是提交一个响应“Window::EventCharacterKey”事件的函数,然后在函数里面判断输入的是否是ctrl+c,Ctrl+v 值再做相应的粘贴板处理。相应的处理代码及编码转化代码见下:
CEGUI::String CEGUIRender::encode(const char * c)
{
static CEGUI::String str;
WCHAR e;
str.clear();
int i = 0;
while(c[i])
{
if(unsigned char(c[i])>=161)
{
MultiByteToWideChar(0,0,c+i,2,&e,1);
str.append(1,e);
i+=2;
}
else
{
str.append(1,c[i]);
i++;
}
}
return str;
}
std::string CEGUIRender::decode(const CEGUI::String& str)
{
const char* chTemp = str.c_str();
WCHAR* strA;
int i= MultiByteToWideChar(CP_UTF8,0 ,(char*)chTemp,-1,NULL,0);
strA = new WCHAR[i];
MultiByteToWideChar(CP_UTF8,0,(char*)chTemp,-1,strA,i);
i= WideCharToMultiByte(CP_ACP,0,strA,-1,NULL,0,NULL,NULL);
char *strB = new char[i];
WideCharToMultiByte (CP_ACP,0,strA,-1,strB,i,NULL,NULL);
std::string strReturn = std::string(strB);
delete strA;
delete strB;
return strReturn;
}
bool CEGUIRender::OnEditBoxKeyDown(const CEGUI::EventArgs& e)
{
CEGUI::KeyEventArgs* kEvent = (CEGUI::KeyEventArgs*)&e;
Window* wBox = kEvent->window;
HGLOBAL clipbuffer;
char * buffer;
std::string strTemp;
CEGUI::String guiStr;
CEGUI::String guiStrTemp;
int iStart,iLen;
//WinLog("%d",kEvent->codepoint);
guiStr = wBox->getText();
iStart = ((Editbox*)wBox)->getSelectionStartIndex();
iLen = ((Editbox*)wBox)->getSelectionLength();
switch (kEvent->codepoint)
{
case 3://ctrl+c copy selected text to clipboard
if(iLen==0)break;
guiStr = guiStr.substr(iStart,iLen);
strTemp = decode(guiStr);
if(OpenClipboard(0))
{
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strTemp.length()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, strTemp.c_str());
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
break;
case 24: //ctrl+x cut the selected text to clipboard
if(iLen==0)break;
wBox->setText(guiStr.substr(0,iStart)+guiStr.substr(iStart+iLen,guiStr.length()-(iStart+iLen)));
((Editbox*)wBox)->setCaratIndex(iStart);
guiStr = guiStr.substr(iStart,iLen);
strTemp = decode(guiStr);
if(OpenClipboard(0))
{
EmptyClipboard();
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strTemp.length()+1);
buffer = (char*)GlobalLock(clipbuffer);
strcpy(buffer, strTemp.c_str());
GlobalUnlock(clipbuffer);
SetClipboardData(CF_TEXT,clipbuffer);
CloseClipboard();
}
break;
case 22://ctrl+v insert the clipboard data
if (!IsClipboardFormatAvailable(CF_TEXT)) break;
if (!OpenClipboard(0)) break;
HGLOBAL hMem = GetClipboardData(CF_TEXT);
if (hMem != NULL)
{
LPTSTR lpStr = (LPTSTR)GlobalLock(hMem);
if (lpStr != NULL)
{
strTemp = std::string((char*)lpStr);
GlobalUnlock(hMem);
}
else strTemp="";
}
else strTemp="";
CloseClipboard();
if( strTemp.length() == 0)break;
guiStrTemp = encode(strTemp.c_str());
wBox->setText(guiStr.substr(0,iStart)+guiStrTemp+guiStr.substr(iStart+iLen,guiStr.length()-(iStart+iLen)));
((Editbox*)wBox)->setCaratIndex(iStart+guiStrTemp.length());
break;
}
return true;
}