최상단 광고

2012년 4월 11일 수요일

CEGUI - 2


기본적인 내용들은 http://cafe.naver.com/cegui.cafe 참고 하시고 http://www.cegui.org.uk/ 참조 하시면
된다.

이번것은 CEGUI 폰트에 관한것이다.
5.0부터는 한글 출력이 조금 편해졌다. font 한글문자를 UTF-8형태로 만들어 주어야한다.

font 폴더에 font파을 열어보면
대충 이런식으로 적어서 저장하시고

Scheme파일에서 폰트를 등록해줄수있다. 그러면 자동으로 Scheme 파일을 읽을때 자동으로 폰트도 셋팅해준다.
다른 방법으로는 FontManager를 호출해줘서 CreateFont를 하면된다.

폰트등록후 LayoutEditor에서 자신이 만든 Scheme파일에 UI들을 생성하면 TEXT할때 할글도 써진다.

그리고 겜브리오와 CEGUI에서 IME 연동 부분을 하겠다. 

일단 IME 부분에서 WndProc MEssage를 받을때 한글을 칠때 IME메세지를 보내게된다. 기본적으로
Ime와 겜브리오를 연동할때

case WM_IMESETCONTEXT: // IME가 생성될때
case WM_IME_STARTCOMPOSITION: // IME 조합이 시작될때 Direct Input를 못들어가게 해줘야한다.
저같은 경우는 이안에 m_pIntance->m_bIME = true; 이런식으로 해줬다.
case WM_IME_ENDCOMPOSITION: // 다른키가 들어오던지 조합이 완료되었을때 처리해주는것으로
이때 Direct Input을 들어가게 해줘야한다. 그래서 m_pIntance->m_bIME = false로 해준다.
case WM_IME_COMPOSITION:// IME가 조합중이라는것이다.
GPG 참고 글을보면서 제작한것이다. GPG에서 CEGUI로 검색하면 될것이다.
// bool형으로 리턴해주는 이유는 true이면 DefaultWindow로 안빠지고 바로 Pass시키기위함이다.
bool GXUICore::IMEKeyInput( HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam )
{
/*
Editbox* GXUICore::IsEditBox( CEGUI::System &sys )
{
 Window* Parent = sys.getGUISheet();
 if(Parent->getActiveChild() == NULL)return NULL;
 if(Parent->getActiveChild()->getWindowRenderer()->getClass() == CEGUI::Editbox::EventNamespace)return static_cast(Parent->getActiveChild());
 return NULL;
}
 
*/
// IsEditBox는 윗에것처럼 시스템에 활동중인자식을 찾고 그것클래스가 에디트박스이면 리턴해주는것이다.
 
CEGUI::Editbox *pEditWindow  = IsEditBox(GXUISystem()); 
 
if(pEditWindow == NULL)return false;
 
if(m_hWnd == NULL) m_pkInstance->m_hWnd = hWnd;
 
 int nLength;     // 그냥 여기저기서 써먹을 변수!
 
HIMC hIMC=NULL;   // IME 핸들
 wchar_t wszComp[4] = {0,};
 
 switch(uiMsg)
 {
  case WM_IME_NOTIFY :
 
 break;
  case WM_IME_SETCONTEXT:  
  
 lParam = 0;
  break; 
 
 // IME 시작일때
  
case WM_IME_STARTCOMPOSITION:
 
  m_pkInstance->m_bIME = true;
 
  return true;
  break ;
 
 // 완성된 조합이 끝났거나 다른 임의키가 들어왔을때
 
 case WM_IME_ENDCOMPOSITION: 
 
  m_pkInstance->m_bIME = false;
  
 return true;
  break;
  // IME 조합중
 
 case WM_IME_COMPOSITION: 
 
  hIMC = ImmGetContext(hWnd);  // ime핸들을 얻는것 ime 함수를 쓰려면 꼭 얻어야해요!
  
 // IME 문자 조합이 완료되었다면
 
  if(lParam == GCS_RESULTSTR)
   {
 
   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)
    
  {
      
 GXUISystem().injectChar(wszComp[i]);
   
   }
  
   }  
 
    //// 문자 조합이 완료되었으면 조합중인 문자 선택해제
  
   size_t caretIndex = pEditWindow->getCaratIndex();
 
    pEditWindow->setSelection(caretIndex, caretIndex);
 
   }
 
  }
   
// IME 문자 조합중이라면
  
 else
   {
 
   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)
   
   {
   
    GXUISystem().injectChar(wszComp[i]);
   
   }
   
   else
   
   {
   
    break;
      }
     }  
 
    // 에디트 입력창을 위해 조합중인 문자가 선택되도록 함
 
    size_t caretIndex = pEditWindow->getCaratIndex();
     pEditWindow->setSelection(caretIndex - 1, caretIndex);
    }
   } 
  
 // IME 핸들 해제  
 
  ImmReleaseContext(hWnd, hIMC);
   return true;  
 
 break;
 
 case WM_CHAR: 
  
 if(!isLeadByte(wParam))
   {
  
  GXUISystem().injectChar((CEGUI::utf32)wParam); 

   }
   return true;
 
 break; 
 }
 return false;
}
 
// DX 겜브리오쪽 키처리이다.
 
if(pkMouse)
 {
  //MOUSE
  if(pkMouse->ButtonWasPressed(GXMouse::NIM_LEFT)) 
  {
 
/*
void NotifyIME()
{
 ImmNotifyIME(ImmGetContext(m_pkInstance->m_hWnd ), NI_COMPOSITIONSTR, CPS_CANCEL, 0); 
}*/
 
   NotifyIME(); // 에디트 박스가 2개 이상일때 다른 에디트 박스를 클릭하면 작업중인 IME 메세지를 없앤다.
  
 GXUISystem().injectMouseButtonDown(CEGUI::LeftButton);
  }

 }
 
if(pkKeyboard)
 {
 
//IME가 처리중일때는 키처리를 안해준다. 
  if(m_pkInstance->m_bIME == true)return ;
  unsigned char ucJustPressedKey = 0;
  if(ucJustPressedKey)
  {
   m_ucPreviouslyPressedKey = ucJustPressedKey;
   m_fTimeSinceEmitKey = m_fKeyRepeatRate - m_fKeyRepeatDelay;
  }
 
  if(ucJustPressedKey || (m_ucPreviouslyPressedKey && 
  
 m_fTimeSinceEmitKey > m_fKeyRepeatRate))
  {
   // Loop through each key
  
 for(int iKeyCode = GXKeyboard::KEY_NOKEY + 1; iKeyCode < GXKeyboard::KEY_TOTAL_COUNT; iKeyCode++)
  
 {
  
  GXKeyboard::KeyCode eKeyCode =  (GXKeyboard::KeyCode)iKeyCode;
   
 // Get DirectInput scancode from Gamebryo keycode.
   
 unsigned char ucDIK = m_pkInstance->m_aucNIIToDIMapping[iKeyCode];
  
  if(pkKeyboard->KeyIsDown(eKeyCode))
  
  {
  
   // if key was just pressed then notify CEGUI
     
GXUISystem().injectKeyDown(ucDIK);
  
   // a new key was pressed this frame.
   
  ucJustPressedKey = ucDIK;
    }
  
  if(pkKeyboard->KeyWasReleased(eKeyCode))
  
  {
  
   // if the key was released then notify CEGUI
   
  GXUISystem().injectKeyUp(ucDIK);    // the previously pressed key was released
   
  if(ucDIK == m_ucPreviouslyPressedKey)
   
   m_ucPreviouslyPressedKey = 0;
  
  }
   }
  
 // System keys like backspace can still repeat.
 
  if(m_fTimeSinceEmitKey > m_fKeyRepeatRate)
   {
 
   GXUISystem().injectKeyDown(m_ucPreviouslyPressedKey);
    m_fTimeSinceEmitKey = 0.0f;
  
 }
  }
  // Update key press delay time.
  m_fTimeSinceEmitKey += kfFrameRate;
 }
 
// IME 작업중에 다른 Editbox를 클릭 할 경우 조합중인 Caret을 리셋해줘야한다. 
Editbox::EventDeactivated를 일어날때 Caret을 리셋해주는 함수를 만들어주면된다.
메모장으로 수정하고 싶은데; 귀찮네; 암튼 IME처리시에는 겜브리오쪽 키를 죽이고
WM_CHAR과 다른메세지때일때는 살리면된다.

댓글 없음: