전에 인턴으로 일할때 TGEA에서 한글을 입력할 수 있게 하는 작업을 했었는데

 

네이버 토크게임엔진 개발자 모임 카페에 내가 했었던 작업과 비슷한 게시물이 올라와

 

전에 작업했던 방식을 참고해서 조금 개량해보았다.

 

 

시작하기 전에 지금 구현하려고 하는 방식의 목적에 대해 간략히 설명하겠다.

 

네이버 방식은 WM_IME_CHAR 메시지가 발생할 때마다 해당 문자를 윈도우에 찍어주나

 

한글 입력시 조립 윈도우가 화면 좌상단에 나타나 입력화면이 그리 유쾌하지 못하다.

 

화면 좌상단의 조립윈도우가 보이십니까?

 

위 스샷처럼 조립 윈도우를 따로 표시하지 않고 조립중인 문자도 표시하게 하는 것이 이번 개량의 목적이다.

 

 

먼저 \TGEA_1_7_0\engine\source\windowManager\win32\win32Window.cpp의

 

WindowProc() 함수의 switch문 안에 다음 구문을 추가한다.

 

case WM_IME_SETCONTEXT:
     DefWindowProc(hWnd,WM_IME_SETCONTEXT,true,ISC_SHOWUICANDIDATEWINDOW);
   return 0;

 

이걸 하는 이유는 조립윈도우는 나타내지 않고 후보윈도우만 표시하게 하기 위해서이다.

(후보윈도우는 한자나 특수문자 입력할때 나오는 작은 윈도우를 말한다)

 

둘 다 표시 안하게 할 거라면 뭐 그냥 return 0; 해버려도 된다.

(이경우, 사용자가 한자키를 누르면 어떻게 처리할 것인지 생각해놔야 한다^^;)

 

 

그리고 같은 폴더의 winDispatch.cpp 파일의

 

_dispatch()함수에 switch() 바로 윗줄에 다음 구문을 추가한다.

 

static bool bComp = FALSE;


지금 IME가 조립중인지 아닌지 구별하는 변수이다.

 

조립을 시작할때, 즉 글자가 처음 찍히게 될 때(bComp == FALSE)는 그냥 출력하면 되지만

 

글자가 조립중일때는 앞에 출력된 글자를 지우고 출력해야 되는데 이 상태를 구별할때 사용한다.

 

그리고 바로 밑의 switch()문에 다음 구문을 추가한다.

 

case WM_IME_STARTCOMPOSITION:
    bComp = FALSE;
    break;
case WM_IME_CHAR:
    if (window)
    {
      if(IsDBCSLeadByte((BYTE)(wParam >> 8)) || bComp)
        _keyboardEvent(window,WM_KEYDOWN,0x00000008,0xC00E0001);
     window->charEvent.trigger(window->getDeviceId(),0,wParam);
     bComp = FALSE;
    }
    break;  
case WM_IME_COMPOSITION:
  if (window  && (lParam & GCS_COMPSTR))
  {
      if(bComp)
       _keyboardEvent(window,WM_KEYDOWN,0x00000008,0xC00E0001);
      window->charEvent.trigger(window->getDeviceId(),0,wParam);
      bComp = TRUE;    
  }
  break;


WM_IME_STARTCOMPOSITION은 문자조립이 시작될 때 발생한다.

 

위에 적었듯이 문자조립이 시작될 때는 앞에 출력한 문자를 지울 필요가 없기에 bComp 값을 FALSE로 셋팅한다.

 

 

WM_IME_CHAR는 문자조립이 완성되었을 때 발생하는 메세지인데

 

한글입력중에 숫자나 특수 문자, 공백을 입력했을 경우에도 발생한다.

 

숫자, 특수문자, 공백의 경우 앞에 출력한 문자를 지우면 안되는데

 

이를 구별하기 위해 IsDBCSLeadByte() 함수로 wParam이 멀티바이트의 첫글자인지 확인하였다.

(숫자, 특수문자, 공백은 1byte 문자)

 

wParam이 멀티바이트 문자이고, 현재 조립중이라면 부담없이 앞에 출력한 문자를 하나 지운다.

 

_keyboardEvent() 함수는 키보드 이벤트를 강제로 발생시키는데, 백스페이스 이벤트를 발생시켰다.

 

하나의 문자 입력이 끝났으므로 bComp의 값을 FALSE로 바꾼다.

 

안바꾸면 무슨 일이 벌어지는지 한번씩 실험해보자 ㅎㅎㅎ

 

 

마지막으로 WM_IME_COMPOSITION는 문자 조립상태가 변할때 발생하는데

 

특히 lParam이 GCS_COMPSTR이면 문자가 아직 조립중이라는 얘기다.

 

목표는 조립중인 문자도 표시하는 것이니까 이벤트가 발생할 때마다 문자를 출력한다.

 

다만 문자 조립이 처음 발생한 것인지, 아닌지 bComp값에 따라서 앞 문자를 지워주기만 하면 된다.

 

 

 

실행화면

 

 

 

덤으로 한문이랑 특수문자 입력도 된다.

 

 

 

p.s - 지금 이방식이 완벽한 것은 아니다. 채팅창에서 한글입력으로 IME 변환을 한 후 게임화면으로

        돌아가 '감'을 입력한 후 u 버튼으로 채팅창을 호출해보자. (ctrl + u 가 아니라 그냥 u)

        채팅창에 '며감'이 찍힐 것이다ㅡㅡ; 이걸 해결하는 방법은 여러가지가 있을 수 있다.

        예를들어, 채팅창이 닫힐때마다 IME상태를 강제로 바꿔준다거나,

        한글 입력을 받으면 다른 처리과정을 거치게 한다거나..

        어쨌건, 각자 제작하려는 게임 환경에 맞춰 알맞은 방법으로 처리하자.    

 

 

참고 : http://www.winapi.co.kr/

         http://cafe.naver.com/tgedev

         http://msdn.microsoft.com/en-us/default.aspx

2009/05/24 16:36 2009/05/24 16:36