.도형 삭제하기

선택된 도형은 편집 대상으로 사용되는데 가장 간단한 삭제 기능부터 작성해 보자. 도형을 삭제하는 것은 아주 간단해서 배열에서 도형에 대한 정보를 지우기만 하면 된다. 배열 요소가 구조체 포인터이므로 포인터가 가리키는 구조체를 먼저 해제하고 memmove 함수로 뒤쪽 도형 정보를 앞쪽으로 한칸씩 이동시켜 포인터를 지운다. 그리고 arNum 1감소시켜 전체 도형 개수도 하나 감소시킨다. 동작을 하는 함수를 작성한다.

 

void DelObject(int idx)

{

   free(arObj[idx]);

   memmove(arObj+idx,arObj+idx+1,(arNum-idx-1)*sizeof(DObject *));

   arNum--;

}

 

WM_COMMAND에서 삭제 명령을 내릴 함수를 호출하여 선택된 도형을 삭제한다. 물론 선택된 도형이 있을 때만 삭제해야 하며 도형이 삭제된 선택을 해제한다. 배열에서 도형을 삭제한 작업 영역을 무효화시키기만 하면 OnPaint 방금 지워진 도형만 빼고 모든 도형을 다시 그리므로 화면에서도 도형이 사라질 것이다.

 

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

{

   switch(LOWORD(wParam)) {

   case IDM_POPUP_DELETE:

      if (NowSel != -1) {

          DelObject(NowSel);

          NowSel=-1;

          InvalidateRect(hWnd,NULL,TRUE);

      }

      break;

   }

   return 0;

}

 

캔버스는 메인 메뉴는 가지지 않으며 대신 팝업 메뉴를 가지고 있다. 아직 팝업 메뉴는 붙이지 않았는데 IDM_POPUP_DELETE라는 ID 팝업 메뉴의 삭제 항목이다. 명령 외에 메인 메뉴에도 삭제 명령이 있으므로 여기서도 똑같은 동작을 해야 한다. 메뉴가 같은 명령을 처리할 때는 한쪽 메뉴에만 코드를 작성하고 다른쪽에서는 메시지를 보내도록 하는 것이 좋다.

 

LRESULT Main_OnCommand(HWND hWnd,WPARAM wParam,LPARAM lParam)

{

   switch(LOWORD(wParam)) {

   case IDM_FILE_EXIT:

      DestroyWindow(hWnd);

      break;

   case IDM_EDIT_DELETE:

      SendMessage(hCanvas,WM_COMMAND,MAKEWPARAM(IDM_POPUP_DELETE,0),0);

      break;

 

메인 윈도우는 캔버스에게 WM_COMMAND 보내 팝업 메뉴의 삭제 처리 코드를 호출한다. 메인 메뉴의 삭제 명령은 사용자와 캔버스를 이어주는 중계 역할만 하고 있는데 이렇게 삭제 명령을 양쪽에 두어야 하는 이유는 차일드는 부모의 기능에 상관없는 독립성을 가져야 하기 때문이다. 또한 차일드가 액셀러레이터를 직접 처리할 없기 때문에 부모가 액셀러레이터 입력을 대신 받아 주어야 한다.