|
在OSG中使用CEGUI时中文输入是比较麻烦的,必须自己建立Hook,经过了一天的研究终于弄出来了,在这里与大家分享一下- #include <Imm.h>
- #include <stdio.h>
- HHOOK Chinese_hHook = NULL;
- HHOOK Input_hook = NULL;
- void InitHook()
- {
- Input_hook = SetWindowsHookEx(WH_CALLWNDPROC ,IMM_GetMsgProc,GetModuleHandle( NULL ),GetCurrentThreadId());
- Chinese_hHook = SetWindowsHookEx(WH_GETMESSAGE,ChineseCharHookProc,NULL,GetCurrentThreadId());
- }
- void ReleaseHook()
- {
- if(Input_hook && Chinese_hHook)
- {
- UnhookWindowsHookEx(Input_hook);
- UnhookWindowsHookEx(Chinese_hHook);
- }
- }
- LRESULT CALLBACK IMM_GetMsgProc( int nCode, WPARAM wParam, LPARAM lParam )
- {
- CWPSTRUCT* cw = (CWPSTRUCT*)lParam;
- if (nCode < 0)
- {
- return CallNextHookEx(Input_hook, nCode, wParam, lParam);
- }
- HIMC hIMC;
- HWND hWnd;
- DWORD dwSize;
- HGLOBAL hstr;
- LPSTR lpstr;
- if (nCode == HC_ACTION /*&& wParam != 0*/)
- {
- switch (cw->message)
- {
- case WM_IME_STARTCOMPOSITION:
- {
- CEGUI::Editbox * eb = (CEGUI::Editbox *)CEGUI::WindowManager::getSingleton().getWindow("IME/Composition");
- eb->setVisible(true);
- CEGUI::Editbox * win = (CEGUI::Editbox *)CEGUI::WindowManager::getSingleton().getWindow("Root/show");
- win->setVisible(true);
- //以上是现实输入法输入框
- }
- //可以自己建立一个CEGUI::EditBox来接收输入的数据
- break;
- case WM_IME_ENDCOMPOSITION:
- {
- CEGUI::Editbox * eb = (CEGUI::Editbox *)CEGUI::WindowManager::getSingleton().getWindow("IME/Composition");
- eb->setVisible(false);
- CEGUI::Editbox * win = (CEGUI::Editbox *)CEGUI::WindowManager::getSingleton().getWindow("Root/show");
- win->setVisible(false);
- //以上是隐藏输入法输入框
- }
- break;
- case WM_IME_COMPOSITION:
- {
- //1.获得并设置输入框
- //先获取当前正在输入的窗口的输入法句柄
- HIMC hIMC = ImmGetContext(GetActiveWindow());
- // 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
- LONG dwSize = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
- WCHAR * lpstr = new WCHAR[dwSize + 1];
- // 再调用一次.ImmGetCompositionString获取字符串
- ImmGetCompositionStringW(hIMC, GCS_COMPSTR , lpstr, dwSize);
- lpstr[dwSize] = L'\0';
- //int num = MultiByteToWideChar(CP_ACP, NULL, lpstr, dwSize, NULL, 0);
- //WCHAR * pstr = new WCHAR[num + 1];
- //MultiByteToWideChar(CP_ACP, NULL, lpstr, dwSize, pstr, num);
- //pstr[num] = L'\0';
- int utf8Num = WideCharToMultiByte(CP_UTF8, NULL, lpstr, dwSize, NULL, 0, NULL, NULL);
- char * str = new char[utf8Num + 1];
- WideCharToMultiByte(CP_UTF8, NULL, lpstr, dwSize, str, utf8Num, NULL, NULL);
- str[utf8Num] = '\0';
- CEGUI::String string((CEGUI::utf8*)str);
- CEGUI::Editbox * eb = (CEGUI::Editbox *)CEGUI::WindowManager::getSingleton().getWindow("IME/Composition");
- float weight = eb->getFont()->getTextExtent(string);//getTextExtent(string.data());
- eb->setWidth(CEGUI::UDim(0.018f,weight));
- eb->setText(string.data());
- LONG cursorIndex = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
- eb->setCaratIndex(cursorIndex);
- //2.获得并设置候选框
- CEGUI::Window * win = CEGUI::WindowManager::getSingleton().getWindow("Root/show");
- LPCANDIDATELIST pList;
- dwSize = ImmGetCandidateListA(hIMC,0,NULL,0);
- pList = (LPCANDIDATELIST)GlobalAlloc( GPTR, dwSize);
- ImmGetCandidateListA(hIMC,0,pList,dwSize);
- //dwSize /= 2;
- DWORD * dwOffset = &pList->dwOffset[0];
- dwOffset += pList->dwPageStart;
- char buf[355];
- DWORD j = 0;
- for (DWORD i=0;i<pList->dwCount;i++)
- {
- LPSTR s = (LPSTR)pList + *dwOffset++;
- sprintf( buf + j,"%d.%s ",i+1,s);
- j += strlen(s) + 3;
- }
- buf[j + 1] = '\0';
- int num = MultiByteToWideChar(CP_ACP, NULL, buf, j + 1, NULL, 0);
- WCHAR * pstr = new WCHAR[num + 1];
- MultiByteToWideChar(CP_ACP, NULL, buf, strlen(buf), pstr, num);
- pstr[num] = L'\0';
- utf8Num = WideCharToMultiByte(CP_UTF8, NULL, pstr, wcslen(pstr), NULL, 0, NULL, NULL);
- char * str2 = new char[utf8Num + 1];
- WideCharToMultiByte(CP_UTF8, NULL, pstr, wcslen(pstr), str2, utf8Num, NULL, NULL);
- str2[utf8Num] = '\0';
- CEGUI::String string2((CEGUI::utf8*)str2);
- weight = win->getFont()->getTextExtent(string2);
- win->setWidth(CEGUI::UDim(0.018f,weight));
- win->setText(string2.data());
- }
- break;
- }
- }//if (nCode == HC_ACTION)
- return 0;
- }
- LRESULT CALLBACK ChineseCharHookProc( int nCode, WPARAM wParam, LPARAM lParam )
- {
- if(nCode < 0)
- return CallNextHookEx(Chinese_hHook,nCode,wParam,lParam);
- // if(!ImmIsIME(GetKeyboardLayout(0)))
- // return CallNextHookEx(g_hHook,nCode,wParam,lParam);
- MSG* msg = (MSG*)lParam;
- switch(msg->message)
- {
- case WM_CHAR:
- {
- switch(msg->wParam)
- {
- //输入状态下的特殊功能键位处理
- case VK_RETURN:
- {
- CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Return);
- break;
- }
- case VK_TAB:
- {
- CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Tab);
- break;
- }
- case VK_BACK:
- {
- CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Backspace);
- break;
- }
- case VK_SPACE:
- {
- CEGUI::System::getSingleton().injectKeyDown(CEGUI::Key::Space);
- CEGUI::System::getSingleton().injectChar((CEGUI::utf32)msg->wParam);
- break;
- }
- default:
- {
- //IMMFollow();//窗口跟随,暂时还没有实现
- ChnInjectChar((CEGUI::utf32)msg->wParam);
- return true;
- }
- break;
- }
- }
- }
- return CallNextHookEx(Chinese_hHook,nCode,wParam,lParam);
- }
- bool 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 >= 0x80 )
- {
- if( !s_flag )
- {
- s_tempChar[1] = (char)uch; //第二个字节
- s_flag = true;
- return true;
- }
- else if( uch >= 0x80 )
- {
- s_tempChar[0] = (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
- }
复制代码 |
|