비영어인 한글의 입력을 제어하기 위해서 IME의 메세지를 처리 합니다.
(EX: 조합중인 초,중,종성의 입력을 제어하는 경우..)
Visual C++ project 에서 환경 설정 2가지
1. #include <imm.h>
2. project properties에서 "Linker > Input > Additional Dependencies" 에 imm32.lib 추가
IME에 대해 처리 할 수 있는 메세지는 다음과 같습니다.
WM_IME_SETCONTEXT
WM_IME_NOTIFY
WM_IME_CONTROL
WM_IME_COMPOSITIONFULL
WM_IME_SELECT
WM_IME_CHAR
WM_IME_REQUEST
WM_IME_KEYDOWN
WM_IME_KEYUP
WM_IME_STARTCOMPOSITION
WM_IME_ENDCOMPOSITION
WM_IME_COMPOSITION
WM_IME_KEYLAST
이 중에 쓸만한 아이들은 다음과 같습니다.
WM_IME_STARTCOMPOSITION
문자 조립 직전의 메세지.
아무 값도 얻을 수 없으며 단순 통지용 메세지입니다.
WM_IME_ENDCOMPOSITION
문자 조립 직후의 메세지.
아무 값도 얻을 수 없으며 단순 통지용 메세지입니다.
WM_IME_COMPOSITION
문자 조립중인 경우의 메세지.
조립중인 문자를 확인 할 수 있습니다.
wParam에 조립중인 글자값이 들어오며
lParam에 조립 상태를 나타내며 값은 다음과 같습니다.
<표. WM_IME_COMPOSITON의 lParam 값...>
Value | Description |
---|---|
GCS_COMPATTR | Retrieves or updates the attribute of the composition string. |
GCS_COMPCLAUSE | Retrieves or updates clause information of the composition string. |
GCS_COMPREADATTR | Retrieves or updates the attributes of the reading string of the current composition. |
GCS_COMPREADCLAUSE | Retrieves or updates the clause information of the reading string of the composition string. |
GCS_COMPREADSTR | Retrieves or updates the reading string of the current composition. |
GCS_COMPSTR | Retrieves or updates the current composition string. |
GCS_CURSORPOS | Retrieves or updates the cursor position in composition string. |
GCS_DELTASTART | Retrieves or updates the starting position of any changes in composition string. |
GCS_RESULTCLAUSE | Retrieves or updates clause information of the result string. |
GCS_RESULTREADCLAUSE | Retrieves or updates clause information of the reading string. |
GCS_RESULTREADSTR | Retrieves or updates the reading string. |
GCS_RESULTSTR | Retrieves or updates the string of the composition result. |
이 중에서도 쓸만한 아이들은 아래 두 아이 입니다.
GCS_COMPSTR 는 현재 조립중임을 나타내며
GCS_RESULTSTR 는 조립이 완성되었음을 의미합니다.
WM_IME_CHAR
하나의 문자가 완성되면 wParam으로 문자를 받습니다.
유니코드 사용시 WM_CHAR와 동일한 기능이지만 유니코드가 아닐 경우
DBCS(Double Byte Character System)일 수 있으며 1 byte만 전달되는 WM_CHAR와 다르게 동작하게 됩니다.
유니코드를 사용합시다.
WM_IME_SETCONTEXT
wParam이 true일 경우 응용 프로그램의 활성화를 뜻합니다. false는 비활성화.
커스텀 IME 윈도우 생성시 이 메세지를 받을 때 ImmIsUIMessage 함수를 호출하여
조립 윈도우와 후보 윈도우를 보이도록 해야 합니다. (네??.. 음..)
WM_IME_NOTIFY
IME 윈도우 변경시를 알리는 메세지입니다.
입력 모드(한글->영문) 변경시, 후보 윈도우 오픈, 후보 목록 변경 등의 이벤트를 얻을 수 있습니다.
wParam로 다음과 같은 이벤트를 잡을 수 있습니다.
IMN_CHANGECANDIDATE
IMN_CLOSECANDIDATE
IMN_CLOSESTATUSWINDOW
IMN_GUIDELINE
IMN_OPENCANDIDATE
IMN_OPENSTATUSWINDOW
IMN_SETCANDIDATEPOS
IMN_SETCOMPOSITIONFONT
IMN_SETCOMPOSITIONWINDOW
IMN_SETCONVERSIONMODE
IMN_SETOPENSTATUS
IMN_SETSENTENCEMODE
IMN_SETSTATUSWINDOWPOS
메세지들이 참 많고 복잡해 보입니다. java가 참 아름다워 보입니다.
어쨋든,
WM_IME_COMPOSITION와 그 안의 GCS_COMPSTR, GCS_RESULTSTR
WM_IME_CHAR
만 잘 써도 성공할 것 같습니다.
한글 입력 SAMPLE
단순히 버퍼도 고정(1024)되어있고 enter, backspace 등 처리는 안되어있는 심플한 소스입니다.
message craker(windowsx.h)를 사용하고 class 화 된 소스입니다.
LRESULT CTest::onMessage(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch (iMessage) {
HANDLE_MSG(hWnd, WM_CREATE, onCreate);
HANDLE_MSG(hWnd, WM_PAINT, onPaint);
//.. 생략 ..
case WM_IME_COMPOSITION:
return onImeComposition(hWnd, wParam, lParam);
case WM_IME_CHAR:
return onImeChar(hWnd, wParam, lParam);
case WM_IME_STARTCOMPOSITION:
return 0;
case WM_MOUSEWHEEL:
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
TCHAR tmp[1024]; //입력받는 문자열을 담을 버퍼
bool bComposite; //입력 중이라 문자 조합 중인지 아닌지 판별하기 위한 변수
void CTest::onPaint(HWND hWnd){
HDC hdc;
PAINTSTRUCT ps;
hdc=BeginPaint(hWnd,&ps);
TextOut(hdc, 10, 10, tmp, lstrlen(tmp)); //입력되는 문자들 출력
EndPaint(hWnd,&ps);
}
bool CTest::onCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct){
bComposite = false; //초기화
ZeroMemory(tmp, sizeof(tmp)); //초기화
return TRUE;
}
LRESULT CTest::onImeComposition(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
TCHAR inChar[2];
inChar[0] = wParam;
inChar[1] = 0;
HIMC hImc;
int pos = lstrlen(tmp);
if (lParam & GCS_COMPSTR) //조립중이라면..
{
if (bComposite) pos--;
hImc = ImmGetContext(hWnd); //IME 사용
int lenIMM = ImmGetCompositionString(hImc, GCS_COMPSTR, NULL, 0); //조합 중인 문자에 길이를 받습니다.
ImmReleaseContext(hWnd,hImc); //IME 자원 해제
//조합중에 backspace를 누르는 경우 길이가 0일 수 있습니다.
//이런 경우가 없다면 ImmGetContext를 사용 안해도 될 것 같습니다.
if (0 == lenIMM)
{
pos--;
bComposite = false;
}
else
{
bComposite = true;
}
memcpy(tmp+pos, inChar, (lstrlen(inChar)+1) * sizeof(TCHAR));
}
InvalidateRect(hWnd, NULL, TRUE);
return DefWindowProc(hWnd,WM_IME_COMPOSITION,wParam,lParam);
}
LRESULT CTest::onImeChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
int pos = lstrlen(tmp);
if (bComposite) pos--;
TCHAR szChar[2];
szChar[0] = wParam;
szChar[1] = 0;
memcpy(tmp+pos, inChar, (lstrlen(inChar)+1) * sizeof(TCHAR));
bComposite = false;
InvalidateRect(hWnd, NULL, TRUE);
return 0;
}
|
:D
'C++' 카테고리의 다른 글
Random 난수 생성하기 (0) | 2010.10.13 |
---|---|
SOCKET (0) | 2010.10.09 |
Windows Thread 와 Synchronization(동기화) (0) | 2010.10.06 |
자료구조 (0) | 2010.09.30 |
VC++ 수행시간 체크 (1) | 2010.09.15 |
Visual C++ : window 생성 template (0) | 2010.09.10 |
C++ 포인터 및 레퍼런스 (0) | 2010.09.02 |
PE (portable executable) 파일 (0) | 2010.08.20 |