본문 바로가기

old drawer/C, C++, MFC

[MFC] 기본 열기 동작(ID_FILE_OPEN 리소스) 재정의 하기

 

MFC에서 기본적으로 새파일,열기는 아래와 같이 구현됩니다.

BEGIN_MESSAGE_MAP(CSpriteWndApp, CWinApp)
// Standard file based document commands
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
// Standard print setup command
ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

CWinApp 라는 Base 클래스의 OnFileOpen() 함수를 호출하게 되는 것이죠. 위 과정에서 통해서 일어나는 일을 순서대로 정리하자면 다음과 같습니다.

1. 기본 메뉴/툴바를 통한 파일열기(ID_FILE_OPEN) 작업이 선택
2. CWinApp 클래스의 기본 메시지맵을 통해 CWinApp::OnFileOpen 함수가 호출
3. CWinApp::OpenDocumentFile 함수가 호출
4. CDocManger::OpenDocumentFile 함수가 호출
5. CSingleDocTemplate::OpenDocumentFile 함수가 호출
6. CDocument::OnOpenDocument 함수가 호출
 
생각보다 복잡한 호출을 이루고 있죠? 우리는 CWinApp::OnFileOpen() 함수를 쓰지 않고 우리가 재정의한 OnFileOpen() 함수를 사용하려는 것이 이번 포스팅의 목적입니다. 그런고로 위 작업목록에서 2번 과정을 변화시켜 보도록 하겠습니다. 

일단 ID_FILE_OPEN 리소스에 대한 처리기를 재정의 하게되면 다음과 같은 변화가 생깁니다.

[ 변경 전 ]
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)

[ 변경 후 ]
ON_COMMAND(ID_FILE_OPEN, &CSpriteWndApp::OnFileOpen)

void CSpriteWndApp::OnFileOpen()
{
// TODO: Add your command handler code here
}


그 이후에 재정의 된  OnFileOpen() 함수 내부에 파일을 여는 새로운 루틴을 추가시켜주면 되는데, 이 루틴에서 아까 위에서 보았던 3,4,5,6번 과정들이 일어나도록 설계를 해야합니다. 그중에 가장 간단한 방법은 이 함수 내부에서 OpenDocumentFile() 함수를 호출하는 방법이 있습니다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void CSpriteWndApp::OnFileOpen()
{
    // TODO: Add your command handler code here
    // 파일 형식 콤보박스에 등록할 필터를 정의한다. (*.*, *.cpp, *.txt)
    char name_filter[] = "All Files (*.*)|*.*|C++ Files (*.cpp)|*.cpp|Text Files (*.txt)|*.txt||";
  
    // TRUE -> 열기대화상자, "cpp" -> 사용자가 확장자 없이 파일명만 입력했을때 자동으로 추가될 확장자명이다.
    // 즉, stdafx 까지만 입력하면 stdafx.cpp라고 입력한것과 동일하게 하고 싶을때 사용한다.
    // "*.cpp" 파일이름 에디트에 출력될 기본 문자열이다. 
    // OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT -> 파일 대화상자에 추가적으로 사용할 속성이다.
    // name_filter -> 파일 형식 콤보박스에 등록할 필터정보를 담고있는 메모리의 주소이다.
    CFileDialog ins_dlg(TRUE, "cpp", "*.cpp"
        OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR, name_filter, NULL);
  
    // 파일 형식 콤보박스에 나열된 필터들 중에서 2번째 항목(*.cpp)을 선택한다.
    ins_dlg.m_ofn.nFilterIndex = 2;
  
    if(ins_dlg.DoModal() == IDOK){
        // 선택된 파일의 경로명을 이용하여 도큐먼트 정보를 재구성한다.
        OpenDocumentFile(ins_dlg.GetPathName());
    } else {
        // 원래 "파일 열기" 기능에서는 파일 열기를 취소했을 때, 특별한 메시지가 나오지 않지만
        // 재정의한 효과를 나타내기 위해서 파일 열기를 취소했을때, 취소했다는 메시지가 나오도록
        // 재구성 했습니다.
        ::MessageBox(NULL, "파일 열기를 취소하였습니다.", "알림", MB_ICONINFORMATION);
    }
}
  
</FONT>


 

이 외에도 복잡한 방법이 있지만, 특별히 복잡하게 쓰지 않는 이상 이정도로도 충분할 듯 싶습니다.

 

<출처> http://nnnyyy.tistory.com/47