. 단축키

클립보드 관련 명령은 텍스트 편집중에 아주 자주 사용되는 기능인데 일일이 팝업메뉴를 선택하는 것은 무척 번거로운 일이다. 그래서 편집중에 곧바로 클립보드 액션을 할 수 있도록 단축키를 제공하는데 클립보드 관련 명령의 단축키는 통상 <Ctrl+C>(복사), <Ctrl+X>(잘라내기), <Ctrl+V>(붙여넣기), <Ctrl+A>(모두 선택)로 정의한다. 모든 편집기들이 이 단축키를 클립보드용으로 정의하고 있으며 또한 사용자들도 이 단축키에 익숙하므로 그대로 적용하도록 하자.

단축키라면 액셀러레이터를 만들어 두면 편리하겠지만 ApiEdit는 컨트롤이기 때문에 직접 액셀러레이터를 쓰기가 어렵다. 그래서 OnChar에서 단축키를 입력받았을 때 해당 명령을 수행하도록 하였다.

 

void OnChar(HWND hWnd, TCHAR ch, int cRepeat)

{

     TCHAR szChar[3];

     int i;

 

    if (ch == 1) {

        SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_SELALL,0),0);

        return;

    }

    if (ch == 3) {

        SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_COPY,0),0);

        return;

    }

    if (ch == 22) {

        SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_PASTE,0),0);

        return;

    }

    if (ch == 24) {

        SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_CUT,0),0);

        return;

    }

 

     if ((ch < ‘ ‘ && ch != ‘\r’ && ch != ‘\t’) || ch==127)

          return;

 

<Ctrl+C>의 문자코드가 3번이므로 이 코드가 입력되었을 때 IDM_AE_COPY 메시지를 보내면 된다. 현재 입력모드가 한글이더라도 <Ctrl+C>는 항상 3번 문자를 보내므로 이 코드는 액셀러레이터 대신 사용해도 전혀 무리가 없다.

클립보드 관련 단축키는 이외에 <Ctrl+Ins>, <Shift+Ins>, <Ctrl+Del>키가 있으며 이 키도 일반적으로 많이 사용된다. 이 키에 대해서도 단축키를 정의하도록 하자. VK_DELETE, VK_BACK은 수정하고 VK_INSERT는 새로 추가하였다.

 

     case VK_DELETE:

        if (bShift) {

            SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_CUT,0),0);

            return;

        }

          if (DeleteSelection()==FALSE) {

               if (IsDBCS(off)) {

                   Delete(off, 2);

               } else {

                   Delete(off, 1);

               }

          }

          InvalidateRect(hWnd,NULL,TRUE);

          SetCaret();

          return;

     case VK_BACK:

          if ((off==0 && SelStart==SelEnd) || (bShift && bControl))

               return;

 

          if (DeleteSelection()==FALSE) {

               if (bControl) {

                   OldOff=off;

                   off=GetPrevWord(OldOff);

                   Delete(off,OldOff-off);

               } else {

                   off=GetPrevOff(off);

                   if (IsDBCS(off)) {

                        Delete(off, 2);

                   } else {

                        Delete(off, 1);

                   }

               }

          }

          InvalidateRect(hWnd,NULL,TRUE);

          SetCaret();

          return;

     case VK_INSERT:

          if (bShift) {

               SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_PASTE,0),0);

          } else if (bControl) {

               SendMessage(hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_COPY,0),0);

          }

          return;

 

<Shift>키와 <Del>키를 같이 누르면 문자를 지우는 대신 IDM_AE_CUT 메시지를 보내 잘라내기를 하도록 하였다. VK_DELETE가 이런 식으로 기능이 수정됨으로 해서 이 키의 기능을 빌려쓰고 있는 VK_BACK의 코드가 불가피하게 영향을 받게 되는데 이 상태에서 <Shift+BS>를 누르면 이것도 잘라내기가 되어 버릴 것이다. 어쨌든 삭제는 되겠지만 클립보드에 들어 있는 내용이 파괴된다는 문제점이 있다.

그래서 <BS>는 더 이상 VK_DELETE의 코드를 빌려 쓰지 못하게 되었고 자신만의 삭제 코드를 가지게 되었다. 선택영역이 있는 상태에서는 선택영역만 삭제하며 <Ctrl+BS>는 앞 단어의 선두까지 삭제한다. <Shift>키가 눌러졌는지는 특별히 점검하지 않았으므로 <Shift+BS> <BS>와 동일하며 <Ctrl+Shift+BS>는 아무 동작도 하지 않도록 하였다. 현재 위치가 문서의 선두이면 앞쪽으로 삭제할 수 없으므로 그냥 리턴하되 단 선택영역이 있으면 삭제할 수 있도록 하였다.

VK_INSERT키는 고유의 기능은 없고 단축키만 제공한다. <Ctrl+Ins>는 복사 명령과 동일하며 <Shift+Ins>는 붙여넣기 명령과 동일하다. 눌러진 조합키에 따라 메시지만 바꿔서 다시 보내면 된다. 이 단축키도 일반적으로 많이 사용되므로 같이 지원하는 것이 좋다.

이상 여기까지 마우스와 키보드로 선택영역을 만드는 실습을 했는데 예문을 짧게 넣었음에도 불구하고 너무 느려서 테스트해보기가 무척 어려웠을 것이다. 다음 장에서는 기능 추가없이 속도를 개선해보고 프로젝트의 전체 코드를 한 번 정리해보도록 하자.