출처 : 하이텔 게제동 강좌란
IME를 사용해서 한글입력기를 만들잣! -_-;;.
(천리안:kjm37 나우:kjm37 하이털:puriat)
홈피주소 : http://anoa.wo.to
-----------------------------------------------------------------------------
자 생일맞이 대 이벤뚜!! 초간단 IME 강좌를 시작합니닷!! 와아~ 짝짝짝~(박수웃)
p.s 강좌내에서는 존칭은 사양합니다;.
. IME란 무엇인가?
IME란 Input Method Editor의 약자로 한국 중국 일본어등 조합을 해야 사용할수
있는 언어 계열을 위한 에디터를 말한다고 한다.(배낀거다;. -_-;.)
. 어떻게 써야하는가?
IME란걸 직접 써보니 별것 아니였다;. 물론 어떤 부분에서 막혀서 몇일을 허비하
긴 했지만.. 일반적으로 들어오는 문자는 WM_CHAR 에서 받고.. 조합중인 글자만
IME함수를 사용해서 얻어오면 그뿐이다. 그리고 한자키 누르면 특수문자및 한자를
얻어와서 화면에 9개 찍어주면 그뿐이다.
. 왜 이런 허접강좌를 쓰게 됐는가?
내가알기론 소스는 널렸는데 강좌가 없어서;. 나처럼 강좌 없인 아무것도 할수없는
사람들을 위해서 자판을 들었다;. (-_-)~d 원츄! (바로 이것이 원츄정신!)
어차피 윈도우 메세지를 가지고 조작하는것이기 때문에 메세지 루틴안의 가공이
필요로 하다. 하지만 그렇게하면 뽀대도 안나고 하니 함수를 하나 만들어서 빼돌
리자! 저 함수는 메세지 루틴안에서 메세지 루틴안에 들어가기 전에 돌려 줘야한다
착한 주명군은 예제 소스까지;;..
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam){
if(GetText( hWnd, msg, wParam, lParam)==0) return 0;
switch(msg){
..
.
.
.
}
이런식으로 해주시면 됍니당.; imm32.lib 를 링크 해주셔야하구요..
char Text[255]; // 텍스트를 저장하기위한 변수
char Cstr[10]; // 조합중인 문자!!
char CanText[200]; // 특수문자를 위한 변수
int CNumber=0; // 현제의 특수문자 위치
int CanMax=0; // 현제 특수문자 목록의 최대 겟수
int GetText(HWND hWnd,UINT msg,WPARAM wparam, LPARAM lparam){
int len; // 그냥 여기저기서 써먹을 변수!
HIMC m_hIMC=NULL; // IME 핸들
switch (msg){
case WM_IME_COMPOSITION: //글씨조합중
return 0;
case WM_CHAR: // 문자 넘어오기
return 0;
case WM_IME_NOTIFY: // 한자입력...
return 0;
case WM_KEYDOWN: // 키다운..
return 0;
case WM_KEYDOWN:
break;
}
return 1;
}
자 주석대롭니다. 텍스트를 저장하기 위한 변수엔 말그대로 글이 들어가구요.
조합중인 문자라던가 특수문자를 위한 변수라던가 전부다 주석 그대로의 용도에
쓰입니다. 저 길이는요 제가 막 넣었던건데 왜 제가 저렇게 넣었는지 지금은 기억이
안납니다요;. 조합중인 문자
의 길이는4바이트 정도만 있어도 돼는걸로 기억하는데 제가 왜 10으로 했었죠?
-_-;. 어째뜬 넘어감돠~
저 글씨 조합중이란 메세지는 말그대로 글씨 조합중일때를 의미합니다 그땐. IME
함수를 사용해서 조합중인 글씨를 얻어오는거죠. 그리고 WM_CHAR는 영어면 그냥 넘
어오고 한글이라면 한글자가 완성이 되면 뿅~ 하고 넘어오게 돼는거죠. ^^;. 그리
고 그 아래에 있는 저 메세지는 한자키를 눌렸을때 나오는 메세지구요. 그 아래껀
한자키를 눌러서 나온 그 특수문자 박스의 왼쪽 오른쪽 이동(?)을 위해 사용합니다
(먼말인지 잘 모르시겠으면 지금 당장 아무 에디터에서나 가 라고 치고 한자키를
눌르셔서 왼쪽키 오른쪽키 눌러보시면 아시게 될껍니다)
case WM_IME_COMPOSITION: // 메때지 처리루틴;;.
m_hIMC = ImmGetContext(hWnd);
// ime핸들을 얻는것 ime 함수를 쓰려면 꼭 얻어야해요!
if (lparam & GCS_RESULTSTR){ // 까먹었음;. 완성되면과 비슷한;...
if ((len = ImmGetCompositionString(m_hIMC, GCS_RESULTSTR, NULL, 0)) >
0){
// 현제 IME의 스트링 길이를 얻는다;.(조합중인이라 생각하심이)
ImmGetCompositionString(m_hIMC, GCS_RESULTSTR, Cstr, len);
// Cstr에 조합중인 문자열을 받아낸다.
// 함수명은 똑같구 인자에 저게 붙으면 넘어온다는;;..
Cstr[len] = 0;
// 젤 끝에 0을 붙여서 깨끗히 해준돠!!
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 핸들 반환!!
* 주석 대롭니다;;.. case WM_IME_COMPOSITION: 메세지 안에 넣어주심 됩니다.
case WM_CHAR: // 한글 이외의 나머지 글은 이리로 들어옵니다. ^^;.
if(wparam == 8 ){ // 만약 8번(빽스페이스)라면..
if(strlen(Text) > 0){ // 길이가 0보다 길면
if(strlen(Text) < 0){ // 지울께 0보다 작으면(확장코드면;.)
// 완성형에서 한글 앞잔지 뒷잔지 알려주는 함수가있긴한데
// 귀찮아서 이걸로 때움;. -_-;.
Text[strlen(Text)-1] = 0; // 한자를 지운다. 뒤에서 또지우니
// 2바이트지우는셈..
}
Text[strlen(Text)-1] = 0; // 한자를 지운다;.
memset(Cstr,0,10); // 조합중문자를 초기화..(왜했지? 기억이.)
// 만약 글자 조합중 일때 빽스페이스가 들어오면 이리 메세지로 안들어
// 오고 조합중이란 메세지로 들어오니 염려 놓으시길;;..
}
}else{ // 빽스페이스가 아니면..
len = strlen(Text);
Text[len] = wparam & 0xff; // 넘어온 문자를 문자열에 넣기..
Text[len] = 0; // 뒤에 0붙이깃!!
}
* 자 이것도 별거 없었죠? ^^;. 다음 메세지로 넘어가기 전에 화면에 찍기부터
보여 드림덩!!
void putstring(HWND hWnd){
char Text1[255];
memset(Text1,0,255);
HDC hDC = GetDC(hWnd);
TextOut(hDC,0,60,CanText,strlen(CanText)); // 특수문자가 있음 찍어주기;.
strcpy(Text1,Text);
if(Cstr[0] != 0 ){
strcpy(Text1 + strlen(Text), Cstr);
}
strcpy(Text1 + strlen(Text1), "_");
TextOut(hDC,0,0,Text1,strlen(Text1));
ReleaseDC(hWnd,hDC);
}
// 자 찍기~ 주석필요 없이 간단하죠? -_-;. 알아서 꾸며주심 됩니다.; 여기까지만
해도 그냥 한글 입력은 이미 다 돼신 거에요.. 그럼 다음 메세지로 넘어가죠!
case WM_IME_NOTIFY: // 한자입력...
GetCandi(hWnd,wparam,lparam,0);
// 이건 좀 기니까 따로 함수로 빼놨습니다.;
break;
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, 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=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, lpCandList, 0)))break;
// 길이를 얻는다
m_CandList = (LPCANDIDATELIST)new char[dwBufLen];
// 또 메모리 할당한다;.
lpCandList = m_CandList;
// 역시 위와 마찬가지로 어느날 이렇게;;.
ImmGetCandidateList(m_hIMC, 0, lpCandList, dwBufLen);
//lpCandList에 목록을 얻는다;.
for(i=CNumber;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);
}
* 쿨럭 길군요; -_-;. 젤 구조화도 안돼있고 왜 저렇게 짰는지 이해가 안가는 부분
이 많은 함수;;... 어쩨뜬 이제 마지막 메세지 처리할 WM_KEYDOWN 함수만 남았군뇨
^^;.
case WM_KEYDOWN: // 키가 눌렸을때..
if(CanText[0]==0) break;
// 특수문자에 글씨가 없뜨면;;..
// 그러니까 창이 안열여뜨면!
if(wParam == VK_PROCESSKEY){
// 프로세스키로 들어가는거면..
// 특수문자 창이 열렸을경우 이렇게
// 들어가요;;..
if((lParam & 0xff0000) == 4915200) // 왼쪽이면;;. -_-;.
{
if(CNumber >0)CNumber -= 9; // 0보다 크면 9빼기
GetCandi(hWnd,wParam, lParam,CNumber);
break;
}
if((lParam & 0xff0000) == 5046272) // 오른쪽이면;;..
{
if(CNumber+9 < CanMax)CNumber += 9; // 구더하기..
GetCandi(hWnd,wParam, lParam,CNumber);
break;
}
}
break;
'Programming > API' 카테고리의 다른 글
WM_CHAR 메시지와 WM_KEYDOWN 메시지 (0) | 2013.08.08 |
---|---|
가상키코드 (0) | 2013.08.08 |
멀티바이트와 유니코드 (0) | 2013.08.06 |
메세지 박스 (0) | 2013.08.05 |
char*, LPCTSTR, TCHAR 의 차이 (0) | 2013.07.25 |