´Ù. ¸Þ½ÃÁöÅ©·¡Ä¿

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 Æú´õ¿¡ ¸Þ½ÃÁöÅ©·¡Ä¿¿¡ °üÇÑ ¹®¼­¸¦ ÂüÁ¶Çϵµ·Ï ÇÏÀÚ.