OGRE 네이버 카페에서 CEGUI 이용해서 한글 채팅을 구현하기위한 방법을 찾다가 팀원이 이 자료를 활용해 한글입력 처리를 하는데 성공했다. 영어와 달리 한글은 자음과 모음을 조합하는 과정이 필요하기때문에, 입력처리에 까다로움이 있다.
이는 일본어와, 한자같은 것들도 동일할것이라 본다. 일단 글 전체를 포스팅 했다. 참고하자
아래의 소스를 활용하기 위해서는 imm32.lib를 추가해줘야 한다. 이는 비쥬얼스튜디오에 포함되어 있으니 따로 받을 필요는 없다.
CEGUI와 Ogre에 몇가지 추가 하면 간단(?)하게 해결 할수 있습니다.
글재주가 없어서 자세한 설명은 패스... 소스 뿌리도록 하겠습니다. ㅡ.ㅡ
CEGUISystem.h
// 입력중인 carat에 위치에 포커싱을 해주며 셀렉한다.
void injectCharSelect(bool select);
CEGUISystem.cpp
CEGUIEditbox.h
void System::injectCharSelect(bool select)
{
if (d_activeSheet)
{
Window* dest = getKeyboardTargetWindow();if(dest) //에디트 박스인 경우
{
if(dest->getWindowRenderer()->getClass() == Editbox::EventNamespace)
{
Editbox* pEditBox = (Editbox*)dest;
if(select)
pEditBox->setSelection(pEditBox->getCaratIndex() - 1,pEditBox->getCaratIndex());
pEditBox->setIMEInputting(select); //IME조합중이면 backspace가 DirectX Input에서 직접 들어오는것을 무시한다.
}
}
}
}
CEGUIEditbox.cpp
// IME조합중이면 backspace가 DirectX Input에서 직접 들어오는것을 무시한다.
bool m_IMEInputting;
void setIMEInputting(bool select) { m_IMEInputting = select; }
Editbox::Editbox(const String& type, const String& name) :
{
.
.
// 추가
m_IMEInputting = false;
}
void Editbox::onKeyDown(KeyEventArgs& e)
{
// base class processing
Window::onKeyDown(e);if (hasInputFocus() && !isReadOnly())
{
WindowEventArgs args(this);
switch (e.scancode)
{
..
case Key::Backspace:
///////////////////////////////////////////////////////////////////////////////
// 추가
// IME조합중이면 backspace가 DirectX Input에서 직접 들어오는것을 무시한다.
if(!m_IMEInputting)
///////////////////////////////////////////////////////////////////////////////
handleBackspace();
break;.
.
}
}
그리고 Ogre소스를 수정해주면 언제든지 한글 처리가 가능 합니다.
OreWindowEventUtilities.h
// 한/영 키 체크를 위해서 추가.
static bool _msisHangul;
OreWindowEventUtilities.cpp
///////////////////////////////////////////////////////////////////////
// 추가
// 한/영 키 체크를 위해서 추가.
#include <CEGUI/CEGUI.h>
#include < ctype.h >//line int __cdecl isLeadByte(int _C) {return ((unsigned char)(_C) & 0x80); }
bool WindowEventUtilities::_msisHangul = false;
///////////////////////////////////////////////////////////////////////
// 한글 조합할때 보이게 해주는 루틴
void imeComposition(HWND hWnd, LPARAM lParam)
{
if( !CEGUI::System::getSingletonPtr() ) return;
// IME 핸들얻기. 실패하면 IME 입력처리 안함
HIMC hImc = ImmGetContext(hWnd);
if(hImc == NULL)
return;// 변수 설정
int nLength = 0;
wchar_t wszComp[4] = {0,};if(lParam & GCS_RESULTSTR) // IME 문자 조합이 완료되었다면
{
nLength = ImmGetCompositionStringW(hImc, GCS_RESULTSTR, NULL, 0);if(nLength > 0)
{
ImmGetCompositionStringW(hImc, GCS_RESULTSTR, wszComp, nLength);for(int i = 0; i < nLength; i++)
{
if(wszComp[i] != 0)
{
CEGUI::System::getSingleton().injectChar(wszComp[i]);
}
}
//CEGUI::System::getSingleton().injectCharSelect(false);
}
}
else if(lParam & GCS_COMPSTR) //IME 조합중
{
nLength = ImmGetCompositionStringW(hImc, GCS_COMPSTR, NULL, 0);if(nLength > 0)
{
ImmGetCompositionStringW(hImc, GCS_COMPSTR, wszComp, nLength);for(int i = 0; i < nLength; i++)
{
if(wszComp[i] != 0)
{
CEGUI::System::getSingleton().injectChar(wszComp[i]);
CEGUI::System::getSingleton().injectCharSelect(true);
}
}
}
}// IME 핸들 해제
ImmReleaseContext(hWnd, hImc);
}
///////////////////////////////////////////////////////////////////////
LRESULT CALLBACK WindowEventUtilities::_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
..
switch( uMsg )
{
..
/////////////////////////////////////////////////////////////////////////////////////////////
// 추가
// 한글 처리를 위해 추가
case WM_KEYDOWN:
{
switch( wParam )
{
case VK_PROCESSKEY:
{
DWORD conv, sentence;HIMC h_imc = ImmGetContext(hWnd);
ImmGetConversionStatus(h_imc, &conv, &sentence);if(conv & IME_CMODE_LANGUAGE)
_msisHangul = true; // 한글 상태임...
else
_msisHangul = false; // 영문 상태임...ImmReleaseContext(hWnd, h_imc);
}
break;
}
}
break;
case WM_CHAR:
// 영문 글자
//if(!_msisHangul || wParam == VK_SPACE || wParam == VK_BACK )
if( CEGUI::System::getSingletonPtr() )
{
CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
}
//////////////////////////////////////////////////////////////////////////////////////////
// CEGUI를 손대지 않고 한글 출력.. 하지만. 조합중인 글자는 보이지 않는다.
//{
// if( CEGUI::System::getSingletonPtr() )
// {
// static char MultiByte[2]={0};
// static bool isHaveMultiByte = false;
// if(isHaveMultiByte)
// {
// isHaveMultiByte = false;
// MultiByte[1] = (unsigned char) wParam;
// wchar_t szUnicode;
// MultiByteToWideChar(CP_ACP, 0, (char*)MultiByte, 2, &szUnicode, 1);
// CEGUI::System::getSingleton().injectChar((CEGUI::utf32)szUnicode);
// break;
// }
// else
// {
// if(isLeadByte(wParam))
// {
// isHaveMultiByte = true;
// MultiByte[0] = (unsigned char)wParam;
// }
// else
// {
// CEGUI::System::getSingleton().injectChar((CEGUI::utf32)wParam);
// break;
// }
// }
// }
//}
return 0;
///////////////////////////////////////////////////////////////////////
// 한글 조합할때 보이게 해주는 루틴
///////////////////////////////////////////////////////////////////////
case WM_IME_SETCONTEXT:
//CEGUIOutputDebugString("WM_IME_SETCONTEXT\n");
lParam = 0;
break;case WM_IME_STARTCOMPOSITION:
//CEGUIOutputDebugString("WM_IME_STARTCOMPOSITION\n");
break;case WM_IME_COMPOSITION:
//CEGUIOutputDebugString("WM_IME_COMPOSITION\n");
imeComposition(hWnd, lParam);
return 0L;case WM_IME_ENDCOMPOSITION:
//CEGUIOutputDebugString("WM_IME_ENDCOMPOSITION\n");
CEGUI::System::getSingleton().injectCharSelect(false); //IME조합이 끝나면 셀렉을 해제 시킨다.
break;case WM_IME_NOTIFY: //입력기가 뜨면 처리// 특수키
//CEGUIOutputDebugString("WM_IME_NOTIFY\n");
//imeNotify(hWnd, wParam, lParam);
break;/////////////////////////////////////////////////////////////////////////////////////////////
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
적고 보니 생각 보다는 좀 길군요.. ㅡ.ㅡ
그럼.. 즐거운 주말 잘 마무리 하세요..
[출처] 한글 채팅 입력에 관한 질문 (OGRE3D) |작성자 자유의지