블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2737)
Unity3D (817)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-19 21:33

IME 관련

Programming/C/C++ / 2010. 9. 10. 17:14

이준곤(LeeChen)님이 작성하신 IME 관련 내용 풀 소스로 만들어본것입니다.

뭐 큰 변경은 없지만 잘잘한 것 조금 변경했습니다.

 

 

#pragma comment(lib,"imm32.lib")
#include <windows.h>


LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;

LPCTSTR lpszClass=TEXT("Ime1");

void putstring(HWND hWnd);
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
       ,LPSTR lpszCmdParam,int nCmdShow)
{
     HWND hWnd;
     MSG Message;
     WNDCLASS WndClass;
     g_hInst=hInstance;
    

     WndClass.cbClsExtra=0;
     WndClass.cbWndExtra=0;
     WndClass.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
     WndClass.hCursor=LoadCursor(NULL,IDC_IBEAM);
     WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
     WndClass.hInstance=hInstance;
     WndClass.lpfnWndProc=(WNDPROC)WndProc;
     WndClass.lpszClassName=lpszClass;
     WndClass.lpszMenuName=NULL;
     WndClass.style=CS_HREDRAW | CS_VREDRAW;
     RegisterClass(&WndClass);

 

     hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
          NULL,(HMENU)NULL,hInstance,NULL);

     ShowWindow(hWnd,nCmdShow);
     hWndMain=hWnd;
    

     while(GetMessage(&Message,0,0,0)) {
          TranslateMessage(&Message);
          DispatchMessage(&Message);
    putstring(hWnd);
     }
     return (int)Message.wParam;
}

 


#include <imm.h>

char Text[255];     // 텍스트를 저장하기위한 변수
char Cstr[10];      // 조합중인 문자!!
char CanText[200];   // 특수문자를 위한 변수
int CNumber=0;        // 현제의 특수문자 위치
int CanMax=0;         // 현제 특수문자 목록의 최대 겟수

//WinAPI창에 출력
void putstring(HWND hWnd){
 //더블버퍼링 준비(백버퍼생성)
 HDC hDC = GetDC(hWnd);
 
 HDC hDCMem;
 RECT rect;
 HBITMAP BitMem, OldBitMap;

 hDCMem = CreateCompatibleDC(hDC);
 GetClientRect(hWnd, &rect);
 BitMem = CreateCompatibleBitmap(hDC, rect.right-rect.left, rect.bottom - rect.top);
 OldBitMap = (HBITMAP)SelectObject(hDCMem, BitMem);
 FillRect(hDCMem, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); // 전체를 하얗게

 //문자열 작성
 char Text1[255]; 
 memset(Text1,0,255);
 
 TextOut(hDCMem,0,60,CanText,strlen(CanText)); // 특수문자가 있음 찍어주기;.
 strcpy(Text1,Text);
 if(Cstr[0] != 0 ){
   strcpy(Text1 + strlen(Text), Cstr);
 }
 strcpy(Text1 + strlen(Text1), "_");
 TextOut(hDCMem,0,0,Text1,strlen(Text1));
 //ReleaseDC(hWnd,hDCMem);

 //백버퍼를 메인버퍼로 옮김
 BitBlt(hDC, rect.left,rect.top,rect.right - rect.left,rect.bottom - rect.top,hDCMem,0,0,SRCCOPY);
    BitMem = (HBITMAP)SelectObject(hDCMem, OldBitMap);
 //사용한 핸들 반환
 DeleteDC(hDCMem);
    ReleaseDC(hWnd, hDC);
    DeleteObject(BitMem);


}
//특수문자 처리
void GetCandi(HWND hWnd, WPARAM wParam, LPARAM lParam,int Number)
{
 DWORD       dwBufLen;    // 버퍼길이
 LPCANDIDATELIST lpCandList;   // 특수문자 리스트
 char aa[255];
 int i;
 LPCANDIDATELIST m_CandList;
 HIMC m_hIMC = ImmGetContext(hWnd);

    switch (wParam) {
        case IMN_OPENCANDIDATE:   // 처음 열렸을때.;;;;
   memset(CanText,0,100); //  특수문자가 들어갈 변수 초기화
   if(!(dwBufLen = ImmGetCandidateList(m_hIMC, 0, NULL,0)))break;//lpCandList, 0)))break;
            // 리스트의 길이 받기..
   m_CandList = (LPCANDIDATELIST)new char[dwBufLen];  // 길이만큼 메모리 얻기
   lpCandList = m_CandList;
   ImmGetCandidateList(m_hIMC, 0, lpCandList, dwBufLen);
            // 할당받은 데로 리스트를 받는다.
            // 아까도 그랬지만 인자에 따라서 같은 함수가 용도가 달라짐;;...
   CanMax=lpCandList->dwCount;
             // 특수문자 목록의 겟수를 넣는다!
   for(i=Number;i<Number+9; i++)                               // 한번에 9개만 보이니까 9개만받는다.
   {   
    if(i>=lpCandList->dwCount) break;
     // 모두 알다시피 더크면 뽀로롱~ 나간다!
     LPSTR lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[i];
     // 문자얻기;.
    strcpy(CanText + strlen(CanText), lpStr);
     // 특수문자 문자열에 넣는다;.
     // 근데 왜 두번이나 지나서 넣는거지? -_-;.
   }
     delete m_CandList;     // 만든걸 날린다!
     m_CandList=NULL;       // 널을 넣는다;.(안넣어도 무방하다;.)
     CNumber = 0;           // 현제의 특수문자 번호를 0으로 만든다;.
    break;
   case IMN_CHANGECANDIDATE:  // 딴 키를 눌러서 새로운 목록으로 바꾸기라면
    memset(CanText,0,100); // 또 다 날린다!
    if(!(dwBufLen = ImmGetCandidateList(m_hIMC, 0, NULL, 0)))break;// 길이를 얻는다
    m_CandList = (LPCANDIDATELIST)new char[dwBufLen]; // 또 메모리 할당한다;.
    lpCandList = m_CandList;// 역시 위와 마찬가지로 어느날 이렇게;;.
    ImmGetCandidateList(m_hIMC, 0, lpCandList, dwBufLen);
        // lpCandList에 목록을 얻는다;.
    for(i=Number;i<Number+9; i++)                               // 한번에 9개만 보이니까 9개만받는다.
    {
     if(i>=lpCandList->dwCount) break;   // 역시 더크면 뾰로롱 나간다~
        LPSTR lpStr = (LPSTR)lpCandList + lpCandList->dwOffset[i];  // 위처럼 lpStr에 문자를 넣고..
     strcpy(CanText + strlen(CanText), lpStr);

          }
    delete m_CandList;           // 역시 할당한것을 날리고
    m_CandList=NULL;             // 리스트에 널을 넣는다.
    break;                       // 빠져나온다..
      case IMN_CLOSECANDIDATE:         // 목록 리스트가 닫힐경우.
    CanText[0]=0;                // CanText젤 앞에 0을 넣어버린다;;.
    break;
 }
 ImmReleaseContext(hWnd, m_hIMC);
}

int GetText(HWND hWnd,UINT msg,WPARAM wparam, LPARAM lparam)
{
 int len;     // 그냥 여기저기서 써먹을 변수!
 HIMC m_hIMC=NULL;   // IME 핸들

 switch (msg){
  case WM_IME_COMPOSITION:   // 글씨조합중
  m_hIMC = ImmGetContext(hWnd); //현재윈도우핸들이 ime핸들을 얻는다.
  if(lparam & GCS_RESULTSTR) //조합이 완료되면
  {
   len = ImmGetCompositionString(m_hIMC,GCS_RESULTSTR,NULL,0);//현재 IME의(조합중인) 스트링 길이를 얻는다.
   if(len >0)
   {
    ImmGetCompositionString(m_hIMC,GCS_RESULTSTR,Cstr, len);//Cstr에 조합중인 문자열을 받아낸다,.
    Cstr[len] = 0; //젤 끝에 0을 붙여서 끝을 표시한다.
    //조합중인 문자는 완료된 상태이기때문에 최종 문자저장소에 넣는다.
    //strcpy(Text+strlen(Text),Cstr); //전체 내용(실제 보일 텍스트) 뒤에 붙여준다.
    strcpy(Text+strlen(Text),Cstr);
    memset(Cstr,0,10); //지움
   }
  }
  else if (lparam & GCS_COMPSTR){  // 조합중이면;.
   len = ImmGetCompositionString(m_hIMC, GCS_COMPSTR, NULL, 0);// 조합중인 길이를 얻는다.
   ImmGetCompositionString(m_hIMC, GCS_COMPSTR, Cstr, len);   // str에  조합중인 문자를 얻는다.
   Cstr[len] = 0;// 뒤에 0을 붙인다.
   // 이렇게 해두시고 글씨 찍을때 Text + Cstr 하셔서 찍어주시면 된다
   // 이건 쫌있다가 찍는 예제를 하나 보여드리죠!
  }
  ImmReleaseContext(hWnd, m_hIMC);// IME 핸들 반환!!
  return 0;
    case WM_CHAR:              // 한글 이외의 나머지 글은 이리로 들어옵니다. ^^;.
  if(wparam == 8 ){      // 만약 8번(빽스페이스)라면..
   if(strlen(Text) > 0){   // 길이가 0보다 길면
    //isDBCSLeadByte  //한글의 첫번째 바이트라면 true 두번째 바이트나 영어라면 false;로 체크
    if(strlen(Text)>1 && IsDBCSLeadByteEx(949,Text[strlen(Text)-1])) // 949 means Hangul code page
    {
     //if(!IsDBCSLeadByteEx(0,Text[strlen(Text)-1])) //만약 특수키체크(특수키 '\' '?'등등);
     //{
     // Text[strlen(Text)-1] = '\0';   // 한자를 지운
     //}else
     {
      Text[strlen(Text)-2] = '\0';   // 한자를 지운다;.
     }
    }
    else //영어
    {
     Text[strlen(Text)-1] = '\0';   // 한자를 지운다;.
    }
    memset(Cstr,0,10);         // 조합중문자를 초기화..(왜했지? 기억이.)
    // 만약 글자 조합중 일때 빽스페이스가 들어오면 이리 메세지로 안들어
    // 오고 조합중이란 메세지로 들어오니 염려 놓으시길;;..
   }
  }else{  // 빽스페이스가 아니면..
   len = strlen(Text);
   Text[len] = wparam & 0xff;   //  넘어온 문자를 문자열에 넣기..
   //Text[len+1] = 0;               //  뒤에 0붙이깃!!
  }
  return 0;
    case WM_IME_NOTIFY:  // 한자입력...
   GetCandi(hWnd,wparam,lparam,CNumber);
   return 0;
     case WM_PAINT:
   {
    PAINTSTRUCT ps;
       HDC hdc=BeginPaint(hWnd,&ps);
     EndPaint(hWnd,&ps);
    return 0;
   }
    case WM_KEYDOWN:    // 키다운..
    if(CanText[0]==0) break; 
        // 특수문자에 글씨가 없뜨면;;..
        // 그러니까 창이 안열여뜨면!
    if(wparam == VK_PROCESSKEY){
        // 프로세스키로 들어가는거면..
     // 특수문자 창이 열렸을경우 이렇게 // 들어가요;;..
     if((lparam & 0xff0000) == 4915200){ // 왼쪽이면
       if(CNumber >0)CNumber-=9;  
   break;
     }
     if((lparam & 0xff0000) == 5046272){ // 오른쪽이면;;..
     if(CNumber+9 < CanMax)CNumber+=9;// 구더하기..
   break;
     }
   }
   break;
 }
  return 1;
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
 if(GetText(hWnd, iMessage,wParam, lParam) == 0)return 0;

     switch(iMessage) {

      case WM_DESTROY:
          PostQuitMessage(0);

          return 0;
     }

     return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}

[출처] IME 관련|작성자 찐남자

반응형

'Programming > C/C++' 카테고리의 다른 글

[C++] 형변환 (Typecasting) - const_cast, reinterpret_cast, static_cast, dynamic_cast  (0) 2010.09.28
GameLoop (번역)  (0) 2010.09.16
TLS (Thread Local Strorage)  (0) 2010.08.30
TCHAR을쓰면 바뀌는 함수들  (0) 2010.07.27
TCHAR printf  (0) 2010.07.12
Posted by blueasa
, |