반응형

출처 : http://blog.naver.com/edun81?Redirect=Log&logNo=40010803227

* 파일열기및 파일저장..

   오늘한거는 화면에 마우스로 점찍은 위치 파일로 저장하고 열기.

- Serialize 함수

   클래스 데이터 내용을 파일에 저장하거나 읽을 수 있도록 한다.

   MFC 최고 대빵 클래스 CObject에 구현되어있다.

   그래서 밑에 넘들이 오버라이딩하여 자신들이 필요한내용을 추가하여 사용한다.


   Serialize 함수는 처음에 프로젝트 만들면 적당한 때에 자동으로 호출이 되도록 AFX가

   이미 만들어져 있다. Doc에 처음엔 껍데기만 있다.


   일단 메뉴의 파일의 열기를 클릭할때의 동작을 알아보면..

  1.  ID_FILE_OPEN  커맨드 메세지 발생..  

   2.  CWinApp 의 멤버함수인 OnFileOpen 함수 가 실행되면...

   3.  OnFileOpen함수는 파일열기의 다이얼로그박스를 실행시켜서 파일명을 입력받은후..

   4.  도큐먼트를 새로 생성하고, 입력받은 파일명을 인자로 넘겨주면서 새로 생성된

   5.  CDocument 파생클래스의 OnOpenDocument 함수를 호출해준다.

   6.  CDocument 의 OnOpenDocument는 Serialize 함수를 호출한다.

   * CDocucment 파생클래스와 CDocument ... 말을 잘 구분해야한다.


   파일열기도 마찬가지..


<< 오늘 소스 >>

void CRtTestDoc::Serialize(CArchive& ar)
{
 if (ar.IsStoring())        // 읽기, 쓰기, 상태를 알아본다.

 {                                        // 세이브 루틴..
  // TODO: add storing code here      // m_PtList 는 CPoint 를 데이타로 한 CList 형 멤버변수
  ar<<m_PtList.GetCount();               // 맨처음에 갯수부터 넣는다.  

  POSITION pos = m_PtList.GetHeadPosition();
  while(pos)
  {
   ar<<m_PtList.GetNext(pos);   // '<<'  파일에 쓰기..   ㅡㅡ;
  }
 }
 else                         // 로드 루틴..
 {
  // TODO: add loading code here
  int count;
  ar>>count;                  // '>>' 파일읽기 란다.. 종니 편하다..   ar에서 읽어서 count에 넣는다.
  CPoint pt;
  while(count--)
  {
   ar>>pt;
   m_PtList.AddTail(pt);
  }
 }
}


*CArchive 클래스

Serialize 함수의 인자로 넘어오는데 데이타를 읽거나 저장할때 사용하는 클래스이다.

파일 입출력 또는 소켓의 리시브,샌드 또는 메모리 입출력 에

연결하여 사용한다. ( CFile, CSocketFile, CMemFile )


* 위의소스에서 IsStoring 함수는 현재 데이터를 읽는중인지 저장하는중 인지 알아내는 함수.

즉, OnSaveDocument함수에서 Serialize가 호출되었으면 TRUE 반환,

     OnOpenDucument함수에서 Serialize가 호출되었으면 FALSE 반환.


* 파일을 읽거나 저장할때 Seriallize 함수는 안좋단다. 간단한 텍스트파일 저장같은거나

  할때 쓰라고 한다.수업시간에한거  혼자서 다시해보니깐 먼가 삐리하다.. ㅡㅡ; 

그래서 결론은 CWinAppOnFileOpen함수와 OnFileSave함수를 오버라이딩해서 쓴다.


저장하기 부분..

void CRtTestDoc::OnFileSave()
{
 // TODO: Add your command handler code here
 LPCTSTR lpszFilter ="pt파일(*.pt)|*.pt|모든파일|*.*||";

/// 파일 공용컨트롤 대화상자 인스턴스 생성.. 첫번째 인자가 TRUE 이면 읽기 FALSE 이면 쓰기.
 CFileDialog dlg(FALSE,".pt",NULL,OFN_HIDEREADONLY |

                                                  OFN_OVERWRITEPROMPT,lpszFilter);
 
 if(dlg.DoModal() == IDOK)                 // 세이브 OK버튼눌럿을때..
 {
  OnSave(dlg.GetFileName());             // 별도로 만든 OnSave 함수 호출..
 }
}

void CRtTestDoc::OnSave(CString fileName)
{
 CFile file(fileName,CFile::modeWrite|CFile::modeCreate);  // 쓰기모드 없으면 맹근다.
 
 int count = m_PtList.GetCount();                // 찍은 점의 갯수를 알아와서
 file.Write(&count, sizeof(int));                   // 파일 맨 앞에 쓴다.
 
 POSITION pos = m_PtList.GetHeadPosition();
 CPoint pt;
 while (pos)                            // 리스트 끝까지 돌면서
 {
  pt = m_PtList.GetNext(pos);      
  file.Write(&pt, sizeof(CPoint)); // 점의 위치를 파일에 쓴다.
 }
 
 file.Close();                           // 파일닫고..
 SetTitle(fileName);                  // 파일이름 타이틀 바에 달아주고..
 SetModifiedFlag(FALSE);       // 갱신이 일어났는지 검사를 헤제한다..
}

파일열기 부분..

void CRtTestDoc::OnFileOpen()
{
 // TODO: Add your command handler code here
 
 if(IsModified())
 {
  CString prompt;
  AfxFormatString1(prompt, AFX_IDP_ASK_TO_SAVE, GetTitle());
  switch (AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_SAVE))
  {
  case IDCANCEL:
   return;     // don't continue
   
  case IDYES:
   // If so, either Save or Update, as appropriate
   if(GetTitle() == "제목없음")
   {
    OnFileSave();
   }
   else
   {
    OnSave(GetTitle());
   }
   break;
 case IDNO:
   // If not saving changes, revert the document
   break;
  }
 }


////SaveModified();
LPCTSTR lpszFilter ="pt파일(*.pt)|*.pt|모든파일|*.*||";   

/// 파일 공용컨트롤 대화상자 인스턴스 생성.. 첫번째 인자가 TRUE 이면 읽기 FALSE 이면 쓰기.
CFileDialog dlg(TRUE,".pt",NULL,OFN_HIDEREADONLY |        

                                                OFN_OVERWRITEPROMPT,lpszFilter);

  if(dlg.DoModal() == IDOK)       // 확인을 눌르면...
 {
  DeleteContents();                 // 기존의 데이타 초기화
  CFile file(dlg.GetFileName(),CFile::modeRead);   // 파일 인스턴스.. 읽기 모드
   
  int count;
  file.Read(&count, sizeof(int));    // 처음에 저장한 갯수를 읽는다.

  CPoint pt;
  while (count--)                         // 갯수만큼 돌리고
  {
   file.Read(&pt, sizeof(CPoint));   // CPoint 형으로 읽는다.
   m_PtList.AddTail(pt);                // 읽은거 CList형 멤버변수에 추가..
  }

  file.Close();                             // 파일 닫고..
  SetTitle(dlg.GetFileName());      // 타이틀바에 표시 해주고..
 }

 UpdateAllViews(NULL);            // 뷰를 갱신..
}

 

* 위에 소스에 LPCTSTR lpszFilter ="pt파일(*.pt)|*.pt|모든파일|*.*||";  

요거는 파일필터이다. 파일읽기나 저장시에 지정파일들만 나오게 한다는..


Serialize 함수 사용시..

리소스뷰에 StringTable에 IDR_MAINFRAME 의 내용을 수정해도 되는데 '\n' 을 구분으로

맨첫번째가 타이틀바에 표시될문자이고 네번째가 파일읽기저장시 보여질 파일필터이고

다섯번째가 실제로 확장자 이다.  참고.. ㅡㅡ;



지금 위의 소스에서 이해가 안간부분.. 주석이 안달린 부분인데..

파일을 불러온다음에 거기에 수정을 한다음 다시 불러오기를하면 저장할거냐고 물어보는

처리를 하는 루틴인데..  이따가 정리 ㅡㅡ;


void CRtTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
 // TODO: Add your message handler code here and/or call default

 CRtTestDoc *pDoc = GetDocument();
 pDoc->m_PtList.AddTail(point);
 pDoc->SetModifiedFlag();                  // 갱신이 일어나는지 검사..

 DrawCircle(point);                             // 별도로 만든 쪼꼬만 원 그리는 함수
 
 CView::OnLButtonDown(nFlags, point);
}


* SetModifiedFlag()

  파라메터를 안넣으면 디폴트 값으로 TRUE.. 갱신이 일어났는지 검사를 한다.

  이것을 안하면 새문서 클릭후 화면에 점찍고 종료를 하면 저장할거냐고 물어보지도 않고

  그냥 종료한다. 문서에 갱신이 일어난후에 종료를 하면 저장할거냐고 묻는게 예의다..


<< 파일 설명 >>


RtTest.zip   :  수업내용소스 ( 마우스위치값 파일로 저장및 열기.)

반응형
Posted by Real_G