. 덧붙이기

윈도우즈의 클립보드는 단 하나의 데이터만 저장할 수 있으며 새로운 데이터를 복사하면 클립보드에 들어있던 원래 데이터는 파괴된다. 그래서 분리되어 있는 여러 개의 텍스트를 하나로 합치려면 일일이 복사, 붙이기를 반복해야만 한다. 덧붙이기 기능은 클립보드에 이미 들어 있는 데이터와 새로 복사된 데이터를 하나로 합쳐 다시 클립보드에 넣는 기능이다. 흩어진 텍스트를 하나로 합쳐서 다른 곳으로 복사하고자 할 때 유용하게 사용할 수 있다.

이 기능은 문서의 내용과 클립보드의 내용을 합치는 것이므로 컨트롤이 직접 제공해야 한다. ApiEdit는 클립보드 관련 명령을 WM_COMMAND로 메시지를 보내 처리하므로 덧붙이기 명령도 같은 방식으로 처리하도록 하자. ApiEdit.h의 선두에 정의된 명령 ID에 다음 두 개를 더 추가한다.

 

#define IDM_AE_CUT 40001

#define IDM_AE_COPY 40002

#define IDM_AE_PASTE 40003

#define IDM_AE_SELALL 40004

#define IDM_AE_COPYAPPEND 40005

#define IDM_AE_CUTAPPEND 40006

 

각각 복사해서 추가하기, 잘라서 추가하기 명령이다. CApiEdit::OnCommand에 이 두 명령에 대한 코드를 작성한다.

 

void CApiEdit::OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify)

{

     TCHAR *ptr2;

 

     switch (id) {

     ....

     case IDM_AE_CUTAPPEND:

          if (!IsClipboardFormatAvailable(CF_TEXT)) {

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

              return;

          }

          if (SelStart != SelEnd && bReadOnly==FALSE && bCapture==FALSE) {

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

              DeleteSelection();

              Invalidate(FindParaStart(off));

              SetCaret();

          }

          return;

     case IDM_AE_COPYAPPEND:

          if (!IsClipboardFormatAvailable(CF_TEXT)) {

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

              return;

          }

          if (SelStart != SelEnd) {

              OpenClipboard(hWnd);

              hmem=GetClipboardData(CF_TEXT);

              ptr=(TCHAR *)GlobalLock(hmem);

              GlobalUnlock(hmem);

              CloseClipboard();

 

              SelFirst=min(SelStart,SelEnd);

              SelSecond=max(SelStart,SelEnd);

              hmem=GlobalAlloc(GHND, lstrlen(ptr)+SelSecond-SelFirst+1);

              ptr2=(TCHAR *)GlobalLock(hmem);

              lstrcpy(ptr2,ptr);

              memcpy(ptr2+lstrlen(ptr2),buf+SelFirst,SelSecond-SelFirst);

              GlobalUnlock(hmem);

              if (OpenClipboard(hWnd)) {

                   EmptyClipboard();

                   SetClipboardData(CF_TEXT,hmem);

                   CloseClipboard();

              }

          }

          return;

 

기능의 개념이 간단하기 때문에 코드도 아주 원론적이다. 클립보드의 텍스트를 먼저 읽어 놓고 여기에 선택영역의 텍스트를 덧붙여서 다시 클립보드로 밀어 넣으면 된다. 별 특별한 기교 같은 것은 없고 아주 평범한 코드일 뿐이다. 잘라서 추가하기는 복사해서 추가한 후 선택영역을 삭제하면 된다. 만약 클립보드에 텍스트가 없다면, 즉 덧붙일 원본이 없다면 추가 기능은 취소되고 복사, 자르기와 동일해진다. 이때는 메시지를 복사, 자르기로 바꿔서 다시 자신에게 보내면 된다.

ApiEdit가 덧붙이기 기능을 구현하고 이 기능에 대한 명령 ID를 정의하고 있으므로 호스트는 명령 ID와 함께 WM_COMMAND 메시지만 보내주면 된다. 다음 코드를 추가하도록 하자.

 

void OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

     ....

     case IDM_EDIT_COPYAPPEND:

          SendMessage(pSi->Ae.hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_COPYAPPEND,0),0);

          break;

     case IDM_EDIT_CUTAPPEND:

          SendMessage(pSi->Ae.hWnd,WM_COMMAND,MAKEWPARAM(IDM_AE_CUTAPPEND,0),0);

          break;

 

다른 클립보드 명령과 마찬가지로 이 두 기능도 선택영역이 있어야만 사용할 수 있다. OnInitMenu에서 이 두 메뉴 명령을 관리해야 한다.

 

void OnInitMenu(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

          ....

          if (s == e) {

              EnableMenuItem(hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);

              EnableMenuItem(hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);

           EnableMenuItem(hMenu, IDM_EDIT_CUTAPPEND, MF_BYCOMMAND | MF_GRAYED);

           EnableMenuItem(hMenu, IDM_EDIT_COPYAPPEND, MF_BYCOMMAND | MF_GRAYED);

              ....

          } else {

              EnableMenuItem(hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_ENABLED);

              EnableMenuItem(hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);

           EnableMenuItem(hMenu, IDM_EDIT_CUTAPPEND, MF_BYCOMMAND | MF_ENABLED);

           EnableMenuItem(hMenu, IDM_EDIT_COPYAPPEND, MF_BYCOMMAND | MF_ENABLED);

               ....

 

이 기능에 대해서는 <Ctrl+Shift+C>, <Ctrl+Shift+X> 액셀러레이터가 정의되어 있으므로 단축키로도 실행할 수 있다. 하지만 ApiEdit 컨트롤 자체는 이 명령에 대한 UI를 제공하지 않으므로 호스트가 지원하지 않으면 이 기능은 사용할 수 없도록 되어 있다. 만약 ApiEdit 컨트롤이 자체적으로 이 명령을 지원하고자 한다면 팝업메뉴에 명령 항목을 넣거나 아니면 OnChar에서 단축키 처리를 해야 한다.