Ime4 ¿¹Á¦´Â Ime3°ú ±â´ÉÀûÀ¸·Î ¿ÏÀüÈ÷ µ¿ÀÏÇÏ´Ù. ´Ù¸¸ ¾ÕÀ¸·ÎÀÇ ½Ç½ÀÀ» À§ÇØ ¼Ò½º¸¦ È®Àå °¡´ÉÇϵµ·Ï Á¤¸®ÇÏ°í ÇÊ¿äÇÑ ¸Þ½ÃÁö ó¸® ÇÔ¼ö¸¦ ¹Ì¸® ¸¸µé¾î ³õ¾Ò´Ù´Â Á¡¸¸ ´Ù¸£´Ù. ÀÌ ¿¹Á¦´Â ¾ÕÀ¸·ÎÀÇ ½Ç½ÀÀ» À§ÇÑ ½ÃÀÛÁ¡ÀÌ µÇ¹Ç·Î Á÷Á¢ ÀÔ·ÂÇÏÁö ¸»°í ¸¸µé¾îÁ® ÀÖ´Â ¿¹Á¦¸¦ ±¸°æ¸¸ Çغ¸µµ·Ï ÇÏÀÚ.
#include <windows.h>
#include <windowsx.h>
#include <imm.h>
#include <stdio.h>
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
HINSTANCE g_hInst;
HWND hWndMain;
LPCTSTR lpszClass=TEXT("Ime4");
// Àü¿ªº¯¼ö
TCHAR *buf;
BOOL bComp;
int off;
int FontHeight;
// ÇÔ¼ö ¿øÇü
BOOL OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);
void OnChar(HWND hWnd, TCHAR ch, int cRepeat);
void OnKey(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UINT flags);
void OnPaint(HWND hWnd);
void OnSetFocus(HWND hWnd, HWND hwndOldFocus);
void OnKillFocus(HWND hWnd, HWND hwndNewFocus);
void OnDestroy(HWND hWnd);
LRESULT OnImeComposition(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT OnImeChar(HWND hWnd, WPARAM wParam, LPARAM lParam);
void OnLButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags);
void OnMouseMove(HWND hWnd, int x, int y, UINT keyFlags);
void OnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags);
void OnTimer(HWND hWnd, UINT id);
void OnSize(HWND hWnd, UINT state, int cx, int cy);
void OnHScroll(HWND hWnd, HWND hwndCtl, UINT code, int pos);
void OnVScroll(HWND hWnd, HWND hwndCtl, UINT code, int pos);
void OnContextMenu(HWND hWnd, HWND hwndContext, UINT xPos, UINT yPos);
void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify);
BOOL OnSetCursor(HWND hWnd, HWND hwndCursor, UINT codeHitTest, UINT msg);
UINT OnGetDlgCode(HWND hWnd, LPMSG lpmsg);
int GetCharWidth(HDC hdc, TCHAR *ch, int len);
void SetCaret();
inline BOOL IsDBCS(int nPos);
int GetPrevOff(int nPos);
int GetNextOff(int nPos);
void Insert(int nPos, TCHAR *str);
void Delete(int nPos, int nCount);
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);
while(GetMessage(&Message,0,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
switch(iMessage) {
HANDLE_MSG(hWnd, WM_CREATE, OnCreate);
HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy);
HANDLE_MSG(hWnd, WM_CHAR, OnChar);
HANDLE_MSG(hWnd, WM_KEYDOWN, OnKey);
HANDLE_MSG(hWnd, WM_KEYUP, OnKey);
HANDLE_MSG(hWnd, WM_PAINT, OnPaint);
HANDLE_MSG(hWnd, WM_SETFOCUS, OnSetFocus);
HANDLE_MSG(hWnd, WM_KILLFOCUS, OnKillFocus);
HANDLE_MSG(hWnd, WM_LBUTTONDOWN, OnLButtonDown);
HANDLE_MSG(hWnd, WM_LBUTTONDBLCLK, OnLButtonDown);
HANDLE_MSG(hWnd, WM_MOUSEMOVE, OnMouseMove);
HANDLE_MSG(hWnd, WM_LBUTTONUP, OnLButtonUp);
HANDLE_MSG(hWnd, WM_TIMER, OnTimer);
HANDLE_MSG(hWnd, WM_SIZE, OnSize);
HANDLE_MSG(hWnd, WM_HSCROLL, OnHScroll);
HANDLE_MSG(hWnd, WM_VSCROLL, OnVScroll);
HANDLE_MSG(hWnd, WM_CONTEXTMENU, OnContextMenu);
HANDLE_MSG(hWnd, WM_COMMAND, OnCommand);
HANDLE_MSG(hWnd, WM_SETCURSOR, OnSetCursor);
HANDLE_MSG(hWnd, WM_GETDLGCODE, OnGetDlgCode);
case WM_IME_COMPOSITION:
return OnImeComposition(hWnd, wParam, lParam);
case WM_IME_CHAR:
return OnImeChar(hWnd, wParam, lParam);
case WM_IME_STARTCOMPOSITION:
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
///////////////////////////////////////////////////////////////////////////////////
// ¸Þ½ÃÁö Çڵ鷯
BOOL OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
{
HDC hdc;
TEXTMETRIC tm;
bComp=FALSE;
buf=(TCHAR *)malloc(65536);
memset(buf,0,65536);
hWndMain=hWnd;
off=0;
hdc=GetDC(hWnd);
GetTextMetrics(hdc,&tm);
FontHeight=tm.tmHeight;
ReleaseDC(hWnd,hdc);
return TRUE;
}
void OnDestroy(HWND hWnd)
{
PostQuitMessage(0);
free(buf);
}
void OnSize(HWND hWnd, UINT state, int cx, int cy)
{
}
void OnKey(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
if (fDown==FALSE)
return;
switch (vk)
{
case VK_LEFT:
if (off > 0) {
off=GetPrevOff(off);
SetCaret();
}
return;
case VK_RIGHT:
if (off < (int)strlen(buf)) {
off=GetNextOff(off);
SetCaret();
}
return;
case VK_HOME:
off=0;
SetCaret();
return;
case VK_END:
off=lstrlen(buf);
SetCaret();
return;
case VK_DELETE:
if (IsDBCS(off)) {
Delete(off, 2);
} else {
Delete(off, 1);
}
InvalidateRect(hWnd,NULL,TRUE);
return;
case VK_BACK:
if (off == 0)
return;
off=GetPrevOff(off);
SendMessage(hWnd,WM_KEYDOWN,VK_DELETE,0);
SetCaret();
return;
}
}
void OnPaint(HWND hWnd)
{
HDC hdc;
PAINTSTRUCT ps;
hdc=BeginPaint(hWnd,&ps);
TextOut(hdc,0,0,buf,lstrlen(buf));
EndPaint(hWnd,&ps);
}
void OnSetFocus(HWND hWnd, HWND hwndOldFocus)
{
SetCaret();
}
void OnKillFocus(HWND hWnd, HWND hwndNewFocus)
{
DestroyCaret();
}
void OnChar(HWND hWnd, TCHAR ch, int cRepeat)
{
TCHAR szChar[3];
int i;
if (ch == 8)
return;
szChar[0]=ch;
szChar[1]=0;
for (i=0;i<cRepeat;i++) {
Insert(off,szChar);
off+=lstrlen(szChar);
}
bComp=FALSE;
InvalidateRect(hWnd,NULL,TRUE);
SetCaret();
}
LRESULT OnImeChar(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
TCHAR szChar[3];
if (IsDBCSLeadByte((BYTE)(wParam >> 8))) {
szChar[0]=HIBYTE(LOWORD(wParam));
szChar[1]=LOBYTE(LOWORD(wParam));
szChar[2]=0;
} else {
szChar[0]=(BYTE)wParam;
szChar[1]=0;
}
if (bComp) {
off-=2;
Delete(off,2);
}
Insert(off,szChar);
off+=lstrlen(szChar);
bComp=FALSE;
InvalidateRect(hWnd,NULL,TRUE);
SetCaret();
return 0;
}
LRESULT OnImeComposition(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
HIMC hImc;
TCHAR *szComp;
int len;
hImc=ImmGetContext(hWnd);
if (lParam & GCS_COMPSTR) {
len=ImmGetCompositionString(hImc,GCS_COMPSTR,NULL,0);
szComp=(TCHAR *)malloc(len+1);
ImmGetCompositionString(hImc,GCS_COMPSTR,szComp,len);
szComp[len]=0;
if (bComp) {
off-=2;
Delete(off,2);
}
if (len == 0) {
bComp=FALSE;
} else {
bComp=TRUE;
}
Insert(off,szComp);
off+=len;
ImmReleaseContext(hWnd,hImc);
free(szComp);
InvalidateRect(hWnd,NULL,TRUE);
SetCaret();
}
return DefWindowProc(hWnd,WM_IME_COMPOSITION,wParam,lParam);
}
void OnHScroll(HWND hWnd, HWND hwndCtl, UINT code, int pos)
{
}
void OnVScroll(HWND hWnd, HWND hwndCtl, UINT code, int pos)
{
}
void OnContextMenu(HWND hWnd, HWND hwndContext, UINT xPos, UINT yPos)
{
}
void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)
{
}
void OnLButtonDown(HWND hWnd, BOOL fDoubleClick, int x, int y, UINT keyFlags)
{
}
void OnMouseMove(HWND hWnd, int x, int y, UINT keyFlags)
{
}
void OnLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
{
}
void OnTimer(HWND hWnd, UINT id)
{
}
BOOL OnSetCursor(HWND hWnd, HWND hwndCursor, UINT codeHitTest, UINT msg)
{
return FORWARD_WM_SETCURSOR(hWnd,hwndCursor,codeHitTest,msg,DefWindowProc);
}
UINT OnGetDlgCode(HWND hWnd, LPMSG lpmsg)
{
return 0;
}
///////////////////////////////////////////////////////////////////////////////////
// ÀÏ¹Ý ÇÔ¼öµé
int GetCharWidth(HDC hdc, TCHAR *ch, int len)
{
SIZE sz;
GetTextExtentPoint32(hdc, ch, len, &sz);
return sz.cx;
}
void SetCaret()
{
SIZE sz;
HDC hdc;
int toff;
int caretwidth;
hdc=GetDC(hWndMain);
if (bComp) {
toff=off-2;
caretwidth=GetCharWidth(hdc,buf+toff,2);
} else {
toff=off;
caretwidth=2;
}
CreateCaret(hWndMain,NULL,caretwidth,FontHeight);
ShowCaret(hWndMain);
GetTextExtentPoint32(hdc,buf,toff,&sz);
SetCaretPos(sz.cx,0);
ReleaseDC(hWndMain,hdc);
}
inline BOOL IsDBCS(int nPos)
{
return (IsDBCSLeadByte(buf[nPos]));
}
int GetPrevOff(int nPos)
{
int n, size;
if (nPos==0) {
return 0;
}
for (n=0;;) {
if (IsDBCS(n)) {
size=2;
} else {
size=1;
}
n+=size;
if (n >= nPos)
break;
}
return n-size;
}
int GetNextOff(int nPos)
{
if (IsDBCS(nPos)) {
return nPos+2;
} else {
return nPos+1;
}
}
void Insert(int nPos, TCHAR *str)
{
int len;
int movelen;
len=lstrlen(str);
if (len==0) return;
movelen=lstrlen(buf+nPos)+1;
memmove(buf+nPos+len,buf+nPos,movelen);
memcpy(buf+nPos,str,len);
}
void Delete(int nPos, int nCount)
{
int movelen;
if (nCount == 0) return;
if (lstrlen(buf) < nPos+nCount) return;
movelen=lstrlen(buf+nPos+nCount)+1;
memmove(buf+nPos, buf+nPos+nCount, movelen);
}
ÇüÅ»óÀ¸·Î °¡Àå Å« º¯È´Â ¸Þ½ÃÁöÅ©·¡Ä¿¸¦ »ç¿ëÇß´Ù´Â Á¡ÀÌ´Ù. ÇÁ·ÎÁ§Æ®°¡ Á¶±Ý¸¸ Ä¿Áö¸é WndProc¿¡¼ ¸ðµç °ÍÀ» ´Ù ó¸®Çϱâ´Â ¾î·Æ°í ¶Ç ¾ÕÀ¸·Î Á¡Á¡ Äڵ尡 Ãß°¡µÉ °ÍÀ̹ǷΠ¾Æ¿¹ ±ò²ûÇÑ ¸Þ½ÃÁöÅ©·¡Ä¿·Î ±¸Á¶¸¦ ¹Ù²Ù¾ú´Ù. ÀÌÁ¦ ¸Þ½ÃÁö Çϳª´ç ó¸®ÇÏ´Â ÇÔ¼ö°¡ Çϳª¾¿ ¹èÁ¤µÇ¹Ç·Î Áö¿ªº¯¼ö¸¦ ¾²±â°¡ ÈξÀ ´õ ÀÚÀ¯·Î¿öÁ³´Ù.
Ime3ÀÇ WndProc¿¡ ÀÖ´ø ¸ðµç ÄÚµåµéÀÌ OnCreate, OnPaint µîÀÇ °³º° ¸Þ½ÃÁö ó¸® ÇÔ¼ö·Î À̵¿µÇ¾ú°í wParam, lParam ´ë½Å¿¡ ¸Þ½ÃÁöÅ©·¡Ä¿°¡ Àü´ÞÇÑ Àμö¸¦ »ç¿ëÇÏ¿´´Ù. ¿¹¸¦ µé¾î WM_CHAR ¸Þ½ÃÁö´Â wParamÀ¸·Î ÀÔ·ÂµÈ ¹®ÀÚ¸¦ ÀоúÁö¸¸ OnChar ÇÔ¼ö´Â ¸Þ½ÃÁöÅ©·¡Ä¿°¡ Àü´ÞÇÑ ch Àμö·ÎºÎÅÍ ÀÔ·Â ¹®ÀÚ¸¦ ±¸ÇÑ´Ù. ÇÏÁö¸¸ ¾îµð±îÁö³ª ÄÚµåÀÇ ÇüÅ°¡ Á¶±Ý ¹Ù²ï °ÍÀÏ »ÓÀÌÁö ³í¸®Àû º¯È´Â ÀüÇô ¾ø´Ù. ´Ù¸¸ ´ÙÀ½ ÇÑ °¡Áö°¡ Á¶±Ý ´Ù¸£°Ô 󸮵ȴÙ.
void OnKey(HWND hWnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
if (fDown==FALSE)
return;
¸Þ½ÃÁö Å©·¡Ä¿´Â Å° ´©¸§°ú ³õÀ½, ¸¶¿ì½º Ŭ¸¯°ú ´õºíŬ¸¯ µî ºñ½ÁÇÑ ¸Þ½ÃÁö¸¦ °°Àº ÇÔ¼ö¿¡ ¿¬°áÇϴ Ư¡ÀÌ ÀÖ´Ù. ½ÇÁ¦ ¾î¶² ¸Þ½ÃÁö°¡ Àü´ÞµÇ¾ú´ÂÁö´Â Àμö·Î ¾Ë·Á Áִµ¥ Å° ¸Þ½ÃÁöÀÇ °æ¿ì fDownÀ¸·Î WM_KEYUPÀÎÁö WM_KEYDOWNÀÎÁö¸¦ ±¸ºÐÇÑ´Ù. ÀÌ ¿¹Á¦´Â ¾ÆÁ÷ WM_KEYUPÀ» »ç¿ëÇÏ°í ÀÖÁö ¾ÊÀ¸¹Ç·Î fDownÀÌ FALSEÀÏ ¶§´Â ¾Æ¹« °Íµµ ó¸®ÇÏÁö ¾Êµµ·Ï ÇØ¾ß ÇÑ´Ù. ±×·¸Áö ¾ÊÀ¸¸é <BS>³ª <Del>Å°¸¦ ´·¶´Ù ¶¿ ¶§ µÎ ±ÛÀÚ¾¿ Áö¿öÁú °ÍÀÌ´Ù.
ÀϹÝÇÔ¼öµéÀº ¸ðµÎ ¼Ò½º ¾ÕÂÊ¿¡ ¿øÇü ¼±¾ðÀ» Çصξú´Ù. ±×¸®°í ÀÌÈÄ ¿©·¯ºÐÀÇ ½Ç½À ÆíÀǸ¦ À§ÇØ Ime3¿¡¼ ó¸®ÇÏ´Â ¸Þ½ÃÁö ¿Ü¿¡ ¾ÕÀ¸·Î Ãß°¡ÇÒ ¸Þ½ÃÁöµéµµ ¹Ì¸® Çڵ鷯¸¦ ÀÛ¼ºÇصξú´Ù. ¸Þ½ÃÁöÅ©·¡Ä¿ Çü½ÄÀÇ ÇÔ¼ö¸¦ Ãß°¡ÇÏ´Â °ÍÀº Á÷Á¢ Çϱ⿡´Â Á» ±î´Ù·Ó±â ¶§¹®ÀÌ´Ù. ¸¸¾à Ime3¿¡¼ Ime4·ÎÀÇ º¯È¸¦ µµÀúÈ÷ ÀÌÇØÇÒ ¼ö ¾ø´Ù¸é ¸Þ½ÃÁöÅ©·¡Ä¿¿¡ ´ëÇØ ¸ÕÀú ¿¬±¸Çغ¸±â ¹Ù¶ó¸ç CD-ROMÀÇ Doc Æú´õ¿¡ ¸Þ½ÃÁöÅ©·¡Ä¿¿¡ °üÇÑ ¹®¼¸¦ ÂüÁ¶Çϵµ·Ï ÇÏÀÚ.