MFC파일 입출력

작성자: 김동영

작성일: 2011.02.28

제목 : MFC 그림판

 

1.  클래스 다이어그램

 

기본적으로 생성되는 MainWnd, App, ViewWnd를 제외한 클래스에 대해 설명하겠습니다.

DiagramManager View 클래스에서 너무 많은 일을 하게 되니깐 DiagramManager에서 실질적인 처리를 하게됩니다.  View 클래스는 어떤 일이 발생하게 되면 DiagramManager의 메시지를 호출 하게됩니다. Document Diagram을 관리합니다. Pen2, Rectangle2, Ellipse2, Line2 Diagram을 상속받았습니다. MyFile 클래스는 packettizingserialrize를 하기 위한 클래스입니다.

 

 

 

 

 

 =================================================================================

 

 

2.시퀀스 다이어그램 및 소스

 

2-1. 도형 선택

 

도형 선택 버튼을 클릭 하였을 때, DiagramManager 클래스의 ChangeDiagram 메소드를 호출 하여 DiagramManager에서 도형의 타입을 관리해줍니다. Diagram을 생성 할 때, 어떤 타입의 도형인지 알아야 하기 때문입니다. 저는 Rectangle 1,Ellipse2,Line 3으로, Pen 4로 값을 주었습니다.

void DiagramManager::ChangeDiagram(int _dtype)

{

        dtype=_dtype;

}

 

 

 

 

 

 

 

 

  =================================================================================

 

2-2. 마우스 왼쪽 버튼 클릭

 

 

마우스 왼쪽 버튼을 클릭 하였을 때는 도형의 시작점을 관리해주어야합니다. 마우스 왼쪽 버튼을 클릭 하고 마우스를 이동하여 버튼에서 손을 떼는 순간 도형이 그려지기 때문에, 마우스 왼쪽 버튼을 눌렀을 때의 위치를 관리해주고 readymove true값을 줍니다.

void DiagramManager::StartPoint(CPoint point,bool _readymove)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        if(dtype==4)

        {

               did=1;

               doc->MakePolyLine(did,point,did);

               did=0; 

        }

        startpoint=point;

        readymove=_readymove;

}

 

 

 

 

 

 

펜을 제외한 나머지 도형들은 시작점만 관리해주면 되지만, 펜의 경우 클릭 하였을 때 객체를 생성하게 하였습니다.
 did
1이면 객체를 생성하고 0이면 펜 객체의 벡터에 점을 추가 하도록 하였습니다.

int C그림판Doc::MakePolyLine(int did,CPoint spt,CPoint npt)

{

        if(did)

        {

               vt.push_back(new Pen2(spt));

               count++;

        }

        else

        {

               vt[vt.size()-1]->AddPoint(npt);

        }

        return did;

}

 

 

 

=================================================================================

 

2-3. 마우스 이동

 

 

StateReadyMove는 클릭한 상태인지를 확인하는 메소드입니다. 만약 true라면 MouseMove메소드를 호출합니다. WM_PAINT에서 그리는게 아니니 CDC값과 이동한 위치를 인자로 넘겨줍니다. 그리고 이동전의 점을 가져온후 점을 펜에 보관해주고 그려줍니다.MakePolyLine은 클릭 하였을 때 did 0으로 변경해주었으므로 AddPoint메소드만 호출하여 펜의 벡터에 점을 보관해줍니다.

void DiagramManager::MouseMove(CDC *dc,CPoint point)

{

        if(dtype==4)

        {

               C그림판Doc *doc=C그림판Doc::GetDocument();

              

               CPoint oldpoint = doc->GetOldPoint();

               doc->MakePolyLine(did,startpoint,point);

               dc->MoveTo(oldpoint);

               dc->LineTo(point)

        }

}

 

 

=================================================================================

 

2-4. 마우스 왼쪽 버튼 UP

 

 

마우스 왼쪽 버튼을 클릭하고, 마우스를 이동하고, 마우스의 버튼을 떼었을 때, 펜을 제외한 나머지 도형들은 생성되어야합니다. 버튼이 UP 되었을때 DiagramManager EndPoint 메소드를 호출하는데, InvalidateRect의 영역을 지정해주기 위해 RECT의 주소값을 넘겨주었습니다. 도형을 만들려면 타입과 시작점과 끝점을 알아야 하기 때문에  MakeDiagram의 인자로 넘겨주었습니다.

도형의 타입에 따라 해당 개체를 생성해줍니다.

 

 

  

================================================================================= 

 

2-4. OnPaint

도형을 생성하고 실질적으로 보여주는 부분입니다. WM_PAINT가 발생하면 DrawAll메시지에 CPaintDC 의 주소값을 인자로 넘겨줍니다. GetDiagramCnt는 도형의 개수를 리턴해주며 GetDiagramType은 벡터의 해당 인덱스의 타입을 리턴한 후 도형의 개수만큼 반복문을 실행합니다. 펜을 제외한 나머지 도형의 RECT 값을 GetDiagram메소드를 통해 가져와서 각각의 타입에 맞게 그려줍니다. 펜의 경우 펜의 점의 개수를 GetPointCnt메소드를 통해가져와 그 개수만큼 GetPoint메소드를 통해 그려줍니다.

void DiagramManager::DrawAll(CPaintDC *dc)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        int count=doc->GetDiagramCnt();

 

        for(int i=0;i<count;i++)

        {

               int type=doc->GetDiagramType(i);

               RECT rect=doc->GetDiagram(i);

               switch(type)

               {

               case 1:        DrawRect(dc,rect);break;

               case 2:        DrawEllipse(dc,rect);break;

               case 3:        DrawLine(dc,rect);break;

               case 4:        DrawPen(dc,i);break;

               }

        }

}

 

 

 

void DiagramManager::DrawPen(CPaintDC *dc,int i)

{

        C그림판Doc *doc=C그림판Doc::GetDocument();

        int pointcnt=doc->GetPointCntDoc(i);

       

        CPoint startpoint;

        CPoint endpoint;

        int j=0;

        int a=0;

        for(j=1;j<pointcnt;j++)

        {

               doc->GetPointDoc(i,a,&startpoint);

               doc->GetPointDoc(i,j,&endpoint);

               dc->MoveTo(startpoint);

               dc->LineTo(endpoint);

 

               a++;

        }

}

 

 

void DiagramManager::DrawLine(CPaintDC *dc,RECT rect)

{

        dc->MoveTo(rect.left,rect.top);

        dc->LineTo(rect.right,rect.bottom);

}

 

 

void DiagramManager::DrawRect(CPaintDC *dc,RECT rect)

{

        CBrush* pBrOld = (CBrush*)dc->SelectStockObject(NULL_BRUSH);

        CPen* pPenOld = (CPen*)dc->SelectStockObject(BLACK_PEN);

 

        dc->Rectangle(&rect);

 

        dc->SelectObject(pPenOld);

        dc->SelectObject(pBrOld);

}

 

 

void DiagramManager::DrawEllipse(CPaintDC *dc,RECT rect)

{

        CBrush* pBrOld = (CBrush*)dc->SelectStockObject(NULL_BRUSH);

        CPen* pPenOld = (CPen*)dc->SelectStockObject(BLACK_PEN);

 

        dc->Ellipse(&rect);

 

        dc->SelectObject(pPenOld);

        dc->SelectObject(pBrOld);

}

 

 

 

나머지 Undo,Redo와 파일저장,파일 로드 부분은 Reference를 참고해주시길 바랍니다.


+ Recent posts