.크기 변경

도형의 크기를 변경할 시점은 마우스로 트래커를 눌러 드래그할 때이다. OnLButtonDown 다음 코드를 추가한다.

 

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

{

   int TempSel;

   int nHit;

 

   if (NowTool==DT_SELECT) {

      nHit=TrackerHitTest(LOWORD(lParam),HIWORD(lParam));

      if (nHit != 0) {

          oldx=LOWORD(lParam);

          oldy=HIWORD(lParam);

          dObj=*arObj[NowSel];

          SizeCorner=nHit;

          DrawTemp(&dObj);

          DragMode=DM_SIZE;

      } else {

          TempSel=FindObject(LOWORD(lParam),HIWORD(lParam));

          ....

 

FindObject 선택 도형을 바꾸는 처리보다 트래커 위에 있는지 점검하는 코드가 앞쪽에 있어야 한다. 트래커는 도형의 안쪽과 바깥쪽에 걸쳐 있는데 선택 처리를 먼저 하게 되면 도형 바깥의 트래커를 눌렀을 선택이 해제되어 버려 크기 조정이 어려워진다. 예를 들어 사각형의 오른쪽 위에 있는 3 트래커를 보자.

트래커의 왼쪽 아래 부분 1/4 영역은 도형의 내부이지만 나머지 3/4영역은 도형의 바깥에 있다. 영역도 크기 조정에 사용할 있어야 하는데 도형 선택을 변경하는 FindObject 함수는 영역이 도형의 일부가 아니므로 선택을 해제해 버릴 것이고 따라서 선택이 없는 상태에서는 도형의 크기를 변경할 없게 된다. TrackerHitTest 선택이 없는 상태일 무조건 0 리턴하도록 되어 있는데 가급적이면 선택을 유지한 채로 트래커 점검을 먼저 하도록 해야 한다.

이동은 선택 변경과 동시에 시작될 있지만 크기 변경은 그렇지 못해서 반드시 대상 도형을 선택해 놓고 크기를 변경해야 한다. 일단 트래커가 보여야 크기 변경이 가능하므로 선택이 없는 상태에서는 크기 변경을 없으며 사용자들도 이런 기대를 하지 않는다.

트래커 위에서 마우스 버튼을 눌렀으면 dObj 현재 도형의 사본을 작성하고 oldx, oldy 최초 클릭한 지점을, SizeCorner에는 드래그를 시작한 트래커 번호를 저장한다. 그리고 DragMode DM_SIZE 변경하여 OnMouseMove에서 크기 변경 처리를 하도록 한다.

 

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

{

   ....

   if (DragMode==DM_SIZE) {

      DrawTemp(&dObj);

      switch (SizeCorner) {

      case 1:

          dObj.rt.left+=ex-oldx;

          dObj.rt.top+=ey-oldy;

          break;

      case 2:

          dObj.rt.top+=ey-oldy;

          break;

      case 3:

          dObj.rt.right+=ex-oldx;

          dObj.rt.top+=ey-oldy;

          break;

      case 4:

          dObj.rt.left+=ex-oldx;

          break;

      case 5:

          dObj.rt.right+=ex-oldx;

          break;

      case 6:

          dObj.rt.left+=ex-oldx;

          dObj.rt.bottom+=ey-oldy;

          break;

      case 7:

          dObj.rt.bottom+=ey-oldy;

          break;

      case 8:

          dObj.rt.right+=ex-oldx;

          dObj.rt.bottom+=ey-oldy;

          break;

      }

      oldx=ex;

      oldy=ey;

      DrawTemp(&dObj);

   }

   return 0;

}

 

이동을 시작한 좌표인 oldx,oldy 현재 마우스 좌표인 ex,ey 차이로부터 마우스의 이동 거리를 구하고  거리를 임시 객체의 크기에 적용한다. 최초 드래그를 시작한 트래커 번호에 따라 크기 조정의 대상이 달라지는데 예를 들어 3 트래커의 경우 right, top 조정하고 5 트래커의 경우 right 조정하면 된다. switch 문이 너무 길어 보인다면 if 문으로 짧게 바꿀 수도 있다.

 

   if (DragMode==DM_SIZE) {

      DrawTemp(&dObj);

      if (SizeCorner==1 || SizeCorner==4 || SizeCorner==6) dObj.rt.left+=ex-oldx;

      if (SizeCorner==1 || SizeCorner==2 || SizeCorner==3) dObj.rt.top+=ey-oldy;

      if (SizeCorner==3 || SizeCorner==5 || SizeCorner==8) dObj.rt.right+=ex-oldx;

      if (SizeCorner==6 || SizeCorner==7 || SizeCorner==8) dObj.rt.bottom+=ey-oldy;

      oldx=ex;

      oldy=ey;

      DrawTemp(&dObj);

   }

 

switch문은 SizeCorner 따라 조정 대상을 개별 선택하지만 if문은 조정 대상에 해당하는 SizeCorner 값을 일괄 점검한다는 점이 다르다. if문이 짧기는 하지만 가독성은 switch문이 조금 좋은 편이다. 문장의 효율을 비교한다는 것은 도토리 키재기라 의미가 없지만 길이는 if문이 짧고 읽기에는 switch문이 좋다. 요즘 추세는 가독성을 가장 중요시하기 때문에 읽기 좋은 소스를 채택했다. 과정을 마우스 이동시마다 반복하다가 버튼을 놓을 선택 도형의 크기를 최종적으로 결정한다.

 

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

{

   ....

   if (DragMode==DM_MOVE || DragMode==DM_SIZE) {

      arObj[NowSel]->rt=dObj.rt;

      InvalidateRect(hWnd,NULL,TRUE);

   }

   DragMode=DM_NONE;

   ReleaseCapture();

   return 0;

}

 

크기 변경 종료 처리는 이동 종료 처리와 동일하므로 조건문만 하나 추가하면 된다. 임시 객체의 rt 도형의 rt 대입하고 무효화시키면 변경된 위치에 도형을 다시 그리는 것은 OnPaint 알아서 한다.