1. 도큐먼트
도큐먼트의 주요 기능
- 도큐먼트 데이터에 접근하기 위한 인터페이스 제공
- 데이터를 저장하고 읽어오는 기능
- 저장 매체와 뷰 사이의 매개 역할
CDocument 클래스(여기 안에 많은 함수가 들어있음)
- 데이타를 관리하는 클래스(저장매체에 있는 데이타를 끌어와서 뷰 클래스에 보여주거나, 뷰에 있는 데이타를 저장 매체에 저장)
- CDocument 클래스는 주로 저장 매체(파일, 데이터베이스 등)에 있는 데이터를 가져와서 뷰 클래스에 보여주거나, 뷰에 있는 데이터를 저장 매체에 저장하는 등의 작업을 수행합니다.
- 클래스 내의 함수 종류 4가지(응용프로그램 마법사에 의해 생성됨)
- OnNewDocument() 함수: 새로운 도큐먼트를 만드는 기능
- Serialize() 함수: 도큐먼트의 내용을 디스크로부터 읽어오고, 저장하는 기능, 밑의 두 함수에 의해서 자동 호출함
- OnSaveDocument() 함수: 파일에 데이터를 저장하는 함수
- OnOpenDocument() 함수: 파일로부터 데이터를 읽기 위한 함수
CArchive 클래스
- 표준 C++ 라이브러리 iostream과 유사
- CArchive ar 객체 형태로 Serialize() 함수의 매개변수에 들어감!
- 도큐먼트의 데이터를 읽고 쓰는 연산자를 정의
- 이진 삽입(<<): 데이터를 순차적으로 저장, "저장"의 의미는 메모리에 있는 데이터가 파일로 전송
- 이진 추출(>>): 순차적으로 데이터를 읽어 들일 때 사용, "열기"의 의미는 파일에 있는 데이타가 메모리로 전송
- CObject 클래스(MFC 최사위)로부터 상속된 클래스로, 객체를 읽고 쓰기 위한 두 개의 멤버 함수를 가지고 있음(ReadObject(), WriteObject()) -> 객체를 서술하기 위해 필요한 정보를 읽고 쓰는 것 관장함
- CArchive 클래스의 멤버 함수 IsStoring() 현재 데이타를 저장하고 있는 중인지, 데이타를 읽고 오고 있는 중인지 알아내는 함수 -> 데이타 저장 중이면 TRUE, 읽어오는 중이면 FALSE 반환
Serialize() 함수
- 직렬화: 하드디스크와 같은 저장 매체에 데이타를 저장하고 읽어 들이는 과정
- 기본적인 기능은 CObject클래스(MFC 최상위 claas)의 Serialize() 함수에 정의
- 도큐먼트 클래스가 자기 자신의 데이타를 관리하므로 도큐먼트 클래스에 Serialize() 함수를 오버라이딩하여 사용
- 매개변수로 들어오는 CArchive& ar가 load인지 store 형태인지에 따라서 저장하거나 쓰기 진행
2. 파일 입출력
데이타를 저장할 때
- OnSaveDocument() 함수가 실행
- CFile 클래스를 이용하여 해당하는 파일을 열어 -> CArchive 클래스를 통로로 데이타 저장
데이타 읽어올 때
- OnOpenDocument() 함수가 실행
- CFile 클래스를 이용하여 해당하는 파일을 열어 -> CArchive 클래스를 통로로 데이타 읽어 옴
Serialize() 함수
- 파일을 저장하거나 읽어올 경우 최후에 데이타를 저장하거나 읽어오는 함수
- OnSaveDocument() 나 OnOpenDocument() 함수에 의해서 자동적으로 호출됨 !!!
//MyDocument 클래스에 오버라이딩하여 사용
//lpszPathName는 파일명임
//새로운 파일에 도큐먼트 데이터를 저장하고 싶어!!
//해당 함수 내에서 CFile 클래스와 CArchive 클래스를 사용하여 파일을 열고 데이터를 저장
BOOL MyDocument::OnSaveDocument(LPCTSTR lpszPathName)
{ //lpszPathName 파일을 쓰기 모드로 열기
CFile file(lpszPathName, CFile::modeCreate | CFile::modeWrite);
//CArchive 객체를 생성하고, 해당 객체를 파일에 연결
//CArchive::store 매개변수는 CArchive가 데이터를 저장하는 모드임을 나타냄
CArchive ar(&file, CArchive::store);
// Serialize() 함수를 호출하여 데이터를 CArchive에 저장할 때 사용
Serialize(ar); // 도큐먼트 데이터를 CArchive에 저장, 함수 호출
ar.Close();
file.Close();
SetModifiedFlag(FALSE); // 도큐먼트의 수정 플래그를 초기화
return TRUE;
}
//저장된 파일로부터 도큐먼트 데이터를 읽어오고 싶어 !!
//해당 함수 내에서 CFile 클래스와 CArchive 클래스를 사용하여 파일을 열고 데이터를 읽어옴
BOOL MyDocument::OnOpenDocument(LPCTSTR lpszPathName)
{
CFile file(lpszPathName, CFile::modeRead);
CArchive ar(&file, CArchive::load);
Serialize(ar); // CArchive에서 도큐먼트 데이터를 읽어옴
ar.Close();
file.Close();
SetModifiedFlag(FALSE); // 도큐먼트의 수정 플래그를 초기화
return TRUE;
}
//따라서 Serialize() 함수 내에서 IsStoring() 함수를 사용하여 데이터를 저장할지 읽어올지를 판단
//->각각의 경우에 맞게 데이터를 처리
//마지막 Serialize 함수는 읽거나 쓰고 싶을 때 위의 함숭에서 자동적으로 호출됨 !!
// CObject 클래스의 가상 함수로, 도큐먼트의 데이터를 직렬화(저장 또는 읽기)하는 역할을 함
//도큐먼트의 데이터가 ar 객체로서 Serialize 함수 매개변수로 들어옴
//CArchive 객체를 인자로 받아, CArchive 객체를 통해 데이터를 저장하거나 읽어옴
//-> 이걸 읽어올지? 저장할지?는 IsStoring() 함수로 판단 !!
void MyDocument::Serialize(CArchive& ar)
{
//ar.IsStoring() 함수는 현재 저장 모드인지를 확인하는 역
//즉, 데이터를 저장하는 작업인지 읽어오는 작업인지를 판단하기 위해 사용
//데이터를 저장할 때(ar.IsStoring()가 TRUE인 경우)
if (ar.IsStoring())
{
// 데이터를 저장하는 코드 작성(CArchive 객체에 데이터를 저장하는 코드)
ar << m_data1; // m_data1을 CArchive에 저장, 도큐먼트에 있는 데이타를 ar 파일에 저장
ar << m_data2; // m_data2를 CArchive에 저장
// ...
}
else
{//(ar.IsStoring()가 FALSE인 경우)
// 데이터를 읽어오는 코드 작성
ar >> m_data1; // CArchive에서 m_data1을 읽어옴, ar 파일로부터 도큐먼트에 있는 데이타 읽어옴
ar >> m_data2; // CArchive에서 m_data2를 읽어옴
// ...
}
}
m_data1, m_data2는 MyDocument 클래스의 멤버 변수로 저장하고자 하는 데이터를 나타냅니다. OnSaveDocument() 함수에서 Serialize() 함수를 호출하여 데이터를 저장하고, OnOpenDocument() 함수에서 Serialize() 함수를 호출하여 데이터를 읽어옵니다.
이러한 방식으로 도큐먼트 클래스와 파일 입출력을 통해 데이터를 저장하고 읽어올 수 있습니다. Serialize() 함수는 저장하거나 읽어올 데이터의 형식에 따라 필요한 코드를 작성하여 사용하면 됩니다.
3. 학생 카드 작성하기 실습
CDocument 클래스 멤버함수
- GetFirstViewPosition() 함수: 도큐먼트와 관련된 뷰들의 리스트에서 첫번째 뷰의 위치 가져오기 위해 호출되는 함수
- GetNextView() 함수: rPosition 도큐먼트의 뷰를 호출하는 함수
3. SDI 탬플릿
- 탬플릿 클래스: 애플리케이션의 여러 자원들과 메인 프레임 클래스, View 클래스, Document 클래스 등을 하나의 묶음으로 가지는 클래스
- SDI(Single Document Inerface) 탬플릿 클래스: 하나의 도큐먼트를 갖는 프로그램 (EX) 메모장, 그림장
- 어떻게 구성되어있니?? CWinApp(애플리케이션 클래스) + CMainFrame(메인 프레임 클래스) + CView(뷰 클래스) + CDocument(도큐먼트 클래스)
-
- CWinApp: 애플리케이션 클래스입니다. 이 클래스는 MFC 응용 프로그램의 진입점인 WinMain 함수에서 상속받아 사용됩니다. 주요한 역할은 애플리케이션의 초기화와 이벤트 루프 등을 관리하는 것입니다.
- CMainFrame: 메인 프레임 클래스입니다. 이 클래스는 주 창(Main Window)을 나타내며, 메뉴, 도구 모음 등의 UI 요소를 포함할 수 있습니다. 주로 메인 창의 생성과 레이아웃, 사용자 인터페이스의 이벤트 처리 등을 담당합니다.
- CView: 뷰 클래스입니다. 이 클래스는 주 창에서 표시되는 내용을 담당합니다. 주로 그래픽, 텍스트, 이미지 등의 데이터를 화면에 표시하고, 사용자 입력에 대한 이벤트를 처리합니다. 애플리케이션에서 여러 개의 뷰를 사용할 수도 있습니다.
- CDocument: 도큐먼트 클래스입니다. 이 클래스는 응용 프로그램의 데이터를 관리합니다. 파일에서 데이터를 로드하고 저장하거나, 데이터의 변경 및 상태를 관리하는 역할을 수행합니다. 도큐먼트 클래스는 뷰 클래스와 밀접한 관계를 가지며, 뷰 클래스를 통해 데이터를 표시하고 수정할 수 있습니다.
(1) 애플리케이션 클래스의 인스턴스 얻기
//애플리케이션 클래스의 포인터 변수 생성->AfxGetApp()이란 함수 이용
//AfxGetApp()은 원래 CWinApp의 포인터 반환함.. 따라서 형변화나 필요!!
CExSDIApp *pApp =(CExSDIApp*)AfxGetApp();
- 클래스의 인스턴스를 얻으면 인스턴스 값으로 얻어온 클래스의 멤버변수나 멤버 함수를 이용할 수 있음
- AfxGetApp() 함수 이용
- 형변환 필요
(2) 메인 프레임 클래스의 인스턴스 얻기
CMainFrame *pFrame =(CMainFrame*)AfxGetMainWnd();
- 메뉴와 툴바, 상태바 등의 상태를 바꾸기 위해서는 메인 프레임 클래스에 접근해야 함
- AfxGetMainWnd() 함수 이용
- 형변환 필요
(3) 뷰 클래스의 인스턴스 얻기
//pFrame은 앞서서 mainFrame의 포인터로 선언했음
CExSDIView *pView = (CExSDIView*)pFrame->GetActiveView();
- GetActiveView() 함수 사용
- 이 함수는 메인 프레임 클래스의 멤버 함수임 -> 먼저 메인 프레임 클래스의 인스턴스 얻고 이 클래스의 멤버 함수 GetActiveView() 사용해야 함
(4) 도큐먼트 클래스의 인스턴스 얻기
CExSDIDoc *pDoc = (CExSDIDoc* )pFrame->GetActiveDocument();
- GetActiveDocument() 함수 사용
- 뷰 클래스의 인스턴스 얻어오는 방법과 동일함
4. MDI 탬플릿
- 하나의 프로그램에서 여러 개의 문서 객체를 가지는 애플리케이션 형태
- 애플리케이션 클래스, 메인 프레임 클래스, 뷰 클래스, 도큐먼트 클래스의 인스턴스 얻는 방법은 SDI 탬플릿과 동일 !!
(1) 자식 프레임 클래스의 인스턴스 얻기
CChildFrame *pChild = (CChildFrame*)pFrame->GetActiveFrame();
- 자식 프레임 클래스의 인스턴스를 얻기 위해 메인 프레임의 멤버함수인 GetActiveFrame() 함수 이용
- 먼저 CMainFrame 클래스를 얻고(pFrame) -> 이 클래스의 멤버 함수인 GetActiveFrame() 함수 사용
5. MDI 기반의 문자열 출력하기 실습
'윈도우프로그래밍' 카테고리의 다른 글
[윈도우 프로그래밍] 사용자 인터페이스 (0) | 2023.06.06 |
---|---|
[윈도우 프로그래밍 7장] 그래픽 객체의 사용 (0) | 2023.06.05 |
[윈도우 프로그래밍] 대화상자 (0) | 2023.04.16 |
[윈도우 프로그래밍] 윈도우 프로그래밍의 이해 (0) | 2023.04.16 |
[윈도우 프로그래밍] MFC 개요 및 아키텍처 (0) | 2023.04.16 |