.속성 추가

현재 검정색 펜에 흰색 브러시로만 도형을 그리므로 조금 썰렁한 감이 있는데 도형에 속성을 주어 선의 굵기와 색상, 면의 색상을 바꿀 있도록 보자. ApiEdit06 프로젝트를 새로 만들고 다음 실습을 진행한다. 속성은 도형별로 다르게 지정할 있어야 하므로 도형의 정보를 저장하는 DObject 구조체에 관련 멤버를 추가한다. 기억해야할 정보의 양이 늘어났으므로 자료 구조가 확장되어야 한다.

 

struct DObject

{

   DTool Type;

   RECT rt;

   unsigned short Flag;

   short LineWidth;

   COLORREF LineColor;

   COLORREF PlaneColor;

};

 

선의 굵기, 색상, 면의 색상을 지정할 있으며 색상의 경우 -1 특이값을 투명색으로 정의했다. 면을 채우지 않는 사각형과 타원을 그릴 필요도 있으므로 면의 투명 처리도 반드시 필요하다. 개별 도형의 속성들 외에 전역 옵션을 기억할 변수도 필요한데 옵션별로 따로 변수를 만들 수도 있지만 도형의 속성이 DObject 구조체에 포함되어 있으므로 DObject형의 구조체 변수 하나를 선언하고 변수의 옵션 멤버들을 전역 설정으로 사용하면 된다.

 

DObject Opt;

 

Opt 구조체의 나머지 멤버(Type, rt, Flag) 사용되지 않으며 속성과 관련된 정보만 사용된다. 도형의 속성을 지정하는 전역 옵션을 도형과 같은 구조체로 선언하면 이후 도형의 옵션이 늘어나도 전역 옵션 변수를 늘릴 필요가 없어 확장에 유리하다. OnCreate에서 다음과 같이 전역 옵션을 초기화한다.

 

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

{

   ....

   Opt.Type=(DTool)-1;

   Opt.LineWidth=3;

   Opt.LineColor=RGB(0,0,0);

   Opt.PlaneColor=RGB(0,255,0);

   return 0;

}

 

굵기 3 검정색 , 초록색의 면색상으로 설정했다. 통상 이런 속성은 스톡 오브젝트의 속성대로 굵기 1 검정색 선에 흰색의 면을 사용하는데 테스트의 편의를 위해 뚜렷하게 구분될 있는 속성을 사용했다. 최종 릴리즈할 때는 무난한 기본값으로 변경하는 것이 좋다. Opt Type -1 설정하는 이유는 구조체가 실제 도형 객체가 아니라 전역 옵션값을 기억하는 용도로 사용된다는 것을 표시한다. 값은 차후 설정 대화상자에서 전역 옵션이라는 것을 구분하기 위해 사용되는데 Opt 설정값은 새로 생성되는 도형의 속성값으로 사용된다. AppendObject에서 새로운 도형을 만들 옵션들을 도형에 기록한다.

 

BOOL AppendObject(DTool Type,int x1,int y1,int x2,int y2)

{

   ....

   arObj[arNum]->LineWidth=Opt.LineWidth;

   arObj[arNum]->LineColor=Opt.LineColor;

   arObj[arNum]->PlaneColor=Opt.PlaneColor;

   arNum++;

   return TRUE;

}

 

새로 추가되는 도형은 Opt 변수의 전역 속성을 그대로 대입받지만 도형이 생성된 개별적으로 속성을 변경할 수도 있다. OnPaint에서는 도형의 속성대로 출력하는데 도형의 속성에 기록되어 있는대로 펜과 브러시를 만들어 선택한 도형을 그리면 된다. 개별 도형마다 속성이 제각각일 있으므로 도형을 그릴 때마다 GDI 오브젝트를 생성해야 한다.

 

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

{

   HDC hdc;

   PAINTSTRUCT ps;

   int idx;

   HPEN hPen,hOldPen;

   HBRUSH hBrush,hOldBrush;

 

   hdc=BeginPaint(hWnd, &ps);

   for (idx=0;idx<arNum;idx++) {

      if (arObj[idx]->LineColor == (COLORREF)-1) {

          hPen=(HPEN)GetStockObject(NULL_PEN);

      } else {

          hPen=CreatePen(PS_INSIDEFRAME,arObj[idx]->LineWidth,arObj[idx]->LineColor);

      }

      hOldPen=(HPEN)SelectObject(hdc,hPen);

      if (arObj[idx]->PlaneColor == (COLORREF)-1) {

          hBrush=(HBRUSH)GetStockObject(NULL_BRUSH);

      } else {

          hBrush=CreateSolidBrush(arObj[idx]->PlaneColor);

      }

      hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);

      switch (arObj[idx]->Type) {

      case DT_LINE:

          ....

      }

      SelectObject(hdc,hOldPen);

      SelectObject(hdc,hOldBrush);

      if (arObj[idx]->LineColor != (COLORREF)-1) {

          DeleteObject(hPen);

      }

      if (arObj[idx]->PlaneColor != (COLORREF)-1) {

          DeleteObject(hBrush);

      }

   }

   if (NowSel != -1) {

      DrawTracker(hdc,NowSel);

   }

   EndPaint(hWnd, &ps);

   return 0;

}

 

색상이 -1 경우는 투명인 상태를 의미하므로 NULL_PEN, NULL_BRUSH 스톡 오브젝트를 적절히 활용해야 한다. 투명색의 개념이 없으면 속이 비어있는 타원과 사각형을 그릴 없을 것이다. 펜은 반드시 PS_INSIDEFRAME 사용해야 하는데 그렇지 않으면 도형의 영역 바깥으로 경계선이 삐져 나가게 된다. 여기까지 작성하면 모든 도형이 검정색 3픽셀선, 초록색 면을 가지게 것이다.