본문 바로가기
C & C++/MFC 컨트롤

[Tip] 메뉴에 '최근 사용한 파일 목록' 만들기

by izen8 2011. 3. 27.
반응형

1.요약

Dialog Based 로 만든 프로그램의 메뉴에 '최근 사용한 파일 목록'을 만들어 봅시다.


2.본문

SDI/MDI 의 경우 Doc/View 구조에 의해서 MFC 가 '최근 사용한 파일'에 대한 리스트를 메뉴에 보여주는 기능을 제공하고 있습니다. 하지만, 이러한 방법은 SDI/MDI 의 경우에만 제공되고 있기 때문에 Dialog Based 프로그램에서는 정상적으로 작동하지 않습니다. 따라서 CMRUList 라는 클래스를 만들어서 그 기능을 구현해 보았습니다.

CMRUList 는 아래와 같은 함수들을 제공합니다.

// nFileNum 번째 위치한 메뉴의 Path 를 얻습니다.
CString GetFilePath(int nFileNum, BOOL *pbEnable = NULL); 

CString GetMenuPath(int nFileNum, BOOL *pbEnable = NULL); 
: 첫번째 함수는 실제 파일의 경로를 얻기 위한 함수이며, 두번째 함수는 메뉴에 Path 를 뿌려주기 위해서 인덱스를 포함한 경로를 얻기 위한 함수입니다.

// 특정 Path 를 메뉴에 넣습니다.
void AddFilePath(CString strFilePath); 
: 파일을 Open 하는 메소드에서 새로운 경로를 추가하기 위해서 사용합니다. 중복 처리나 순서에 대한 처리는 클래스 내부에서 수행합니다.

// MRU 리스트를 저장합니다.
void Save(); 
: 현재 지정되어 있는 경로들을 저장합니다. (프로그램이 종료할때 사용하시면 됩니다.)

// 특정 위치의 Path 를 리스트에서 제거합니다.
void DeletePath(int nNum); 
: 이 함수는 실제로 파일을 Open 했을때 파일을 정상적으로 열지 못할경우 리스트에서 제거하기 위해서 사용합니다.

// 전체 Path의 갯수를 얻습니다.
int GetTotalPath(); 
: 현재 등록되어 있는 Path 의 갯수를 얻습니다.


3.예제

// [ 최근 사용한 파일 목록 ] 

// |----> [ IDM_MRU_FILE1 ] 

// |----> [ IDM_MRU_FILE2 ] 

// |----> [ IDM_MRU_FILE3 ] 

// |----> [ IDM_MRU_FILE4 ] 





// 2. Dialog 의 header 파일에 아래의 함수를 추가합니다. 

afx_msg void OnUpdateRecentFile(CCmdUI* pCmdUI); 

afx_msg void OnRecentFile(int nID); 





// 3. CMRUList 의 객체를 선언합니다. 

public: 

    CMRUList m_ctrMRUList; 

    int m_nTotalMruMenu;  // 전체 메뉴 갯수 

    

    

// 4. Dialog 의 cpp 파일의 메세지 핸들러를 추가합니다. 

ON_COMMAND_RANGE(IDM_MRU_FILE1, IDM_MRU_FILE4, OnRecentFile) 

ON_UPDATE_COMMAND_UI_RANGE(IDM_MRU_FILE1, IDM_MRU_FILE4 , OnUpdateRecentFile) 

        

        

// 5. 생성자에서 현재 초기화된 메뉴의 갯수를 저장합니다. 

m_nTotalMruMenu = m_ctrMRUList.GetTotalPath(); 

    

    

// 6. 메뉴를 업데이트 하기 위한 핸들러를 구현합니다. 

void CTestDlg::OnUpdateRecentFile(CCmdUI* pCmdUI) 

{ 

    BOOL bEnable; 

    

    // 새로 생긴 메뉴가 있다면 생성합니다. 

    if (m_nTotalMruMenu != m_ctrMRUList.GetTotalPath()) 

    { 

        switch(m_nTotalMruMenu) 

        { 

        case 0: 

            pCmdUI->m_pMenu->InsertMenu(IDM_MRU_FILE1, 

                MF_BYCOMMAND|MF_STRING, IDM_MRU_FILE1); 

        case 1: 

            pCmdUI->m_pMenu->InsertMenu(IDM_MRU_FILE2, 

                MF_BYCOMMAND|MF_STRING, IDM_MRU_FILE2); 

        case 2: 

            pCmdUI->m_pMenu->InsertMenu(IDM_MRU_FILE3, 

                MF_BYCOMMAND|MF_STRING, IDM_MRU_FILE3); 

        case 3: 

            pCmdUI->m_pMenu->InsertMenu(IDM_MRU_FILE4, 

                MF_BYCOMMAND|MF_STRING, IDM_MRU_FILE4); 

        } 

        

        m_nTotalMruMenu = m_ctrMRUList.GetTotalPath(); 

        

        return; 

    } 

    

    // 메뉴의 Text를 업데이트 합니다. 

    switch(pCmdUI->m_nID) 

    { 

    case IDM_MRU_FILE1: 

        pCmdUI->SetText(m_ctrMRUList.GetMenuPath(0, &bEnable)); 

        break; 

    case IDM_MRU_FILE2: 

        pCmdUI->SetText(m_ctrMRUList.GetMenuPath(1, &bEnable)); 

        break; 

    case IDM_MRU_FILE3: 

        pCmdUI->SetText(m_ctrMRUList.GetMenuPath(2, &bEnable)); 

        break; 

    case IDM_MRU_FILE4: 

        pCmdUI->SetText(m_ctrMRUList.GetMenuPath(3, &bEnable)); 

        break; 

    } 

    

    // 현재 Path 가 지정되어 있지 않은 메뉴라면, 삭제합니다. 

    if (bEnable == FALSE) 

        pCmdUI->m_pMenu->RemoveMenu(pCmdUI->m_nID, MF_BYCOMMAND); 

    else 

        pCmdUI->Enable(TRUE); 

} 





// 7. 메뉴를 눌렀을때 발생하는 이벤트에 대해서 처리합니다. 

void CTestDlg::OnRecentFile(int nID) 

{ 

    

    CString strPath; 

    int nIDNum; 

    

    switch(nID) 

    { 

    case IDM_MRU_FILE1: 

        nIDNum = 0; 

        break; 

    case IDM_MRU_FILE2: 

        nIDNum = 1; 

        break; 

    case IDM_MRU_FILE3: 

        nIDNum = 2; 

        break; 

    case IDM_MRU_FILE4: 

        nIDNum = 3; 

        break; 

    } 

    

    // strPath 에는 선택된 파일에 대한 경로가 들어있습니다. 

    strPath = m_ctrMRUList.GetFilePath(nIDNum); 

} 


4.참고



5.주의

처음에는 메뉴에 대한 Path가 없기 때문에, 모든 메뉴가 자동으로 삭제되도록 되어 있습니다. 따라서 처음으로 파일을 열어서 path를 추가하고자 하실때 ( AddFilePath() 호출할때..), 임의로 InsertMenu() 함수를 통해서 아래와 같은 방법으로 추가해 주셔야 합니다.

예)

C:\test.cpp

if (m_ctrMRUList.GetTotalPath() == 1) 

{ 

    GetMenu()->GetSubMenu(0)->GetSubMenu(6)->InsertMenu(

        IDM_MRU_FILE1, MF_BYCOMMAND|MF_STRING, IDM_MRU_FILE1); 

    m_nTotalMruMenu = 1; 

} 

반응형

댓글