#14. Modal Status와 Modeless Status의 차이

지난번에 우리는 대화 상자를 DoModal()로 수행하였다. 이것은 말 그대로 모달 대화 상자를 수행하도록 요구하는 구문이다. 이번에는 모달리스에 대해서 알아보도록 하겠다.


이 둘의 용어 정리가 우선 필요할 것이다.



  • 모달 상태의 대화 상자 : 메인 프레임 어플리케이션과 대화 상자가 있다고 할 때에, 모달 상태의 대화 상자가 실행중일 때에는 메인 프레임이 Idle 상태가 된다. 즉, 사용이 불가능한 상태가 된다. 이 때, 대화 상자에서 확인이나 취소를 클릭함으로서 메인 프레임으로 제어권이 넘어가게 된다. 이것이 모달 대화 상자의 형식이다.
  • 모달리스 상태의 대화 상자 : 메인 프레임 어플리케이션과 대화 상자가 있다고 할 때에, 모달리스 상태의 대화 상자가 실행중일때에도 메인 프레임은 별개로 동작한다.

그렇다면 실제 코딩할 때에 어떤식으로 함수를 써야하는지를 알아야 할 것이다.



  • Modal Dialog Box



    • 생성함수 : DoModal();
    • 종료함수 : EndDialog();
    • 인스턴스의 선언 : 멤버 변수의 형태로 선언됨.


  • Modeless Dialog Box



    • 생성함수 : Create();
    • 종료함수 : DestroyWindow();
    • 인스턴스의 선언 : 동적 할당.

이제 실제로 모달리스 대화 상자를 수행해보도록 하자. 일반적인 MFC 어플리케이션 프로젝트에서 모달리스 대화 상자를 수행하도록 하는 메뉴를 리소스 에디터에서 작성한 후 클래스 위저드로 등록시켜두자. 물론, 대화 상자도 만들어두고 클래스 위저드에 새 클래스로 등록시켜야 한다.


모달리스 대화 상자 클래스의 멤버 함수중에서 Create()라고 하는 것이 있다. 이것을 클래스 위저드에서 오버라이딩시켜야 하는데 초기 설정은 아래와 같이 되어있다.



    class C(대화상자ID) : public CDialog


    {


    //…


    BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL);


    //…


    }

    BOOL C(대화상자ID)::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)


    {


    // TODO: Add your specialized code here and/or call the base class


    return CDialog::Create(IDD, pParentWnd);


    }


이것을 아래와 같이 간결하게 재편집하여야 한다. 간결하게 만드는 것 또한 오버라이딩의 방법이다.



    class C(대화상자ID) : public CDialog


    {


    //…


    BOOL Create(CWnd* pParentWnd);


    //…


    }

    BOOL C(대화상자ID)::Create(CWnd* pParentWnd)


    {


    // TODO: Add your specialized code here and/or call the base class


    return CDialog::Create(IDD, pParentWnd);


    }


return CDialog::Create(IDD, pParentWnd);에서 pParentWnd 파라미터만이 환원되므로 기타의 것들은 삭제하였다. 하지만, 좀 더 부가적인 옵션을 사용할 생각이라면 이렇게 하는 것은 권장하고 싶지 않다. 하지만, 적당히 필요없는 부분을 걸러내어 어플리케이션의 코드를 최적화시키는 것도 프로그래밍의 전략이다.


이제 출력을 위하여 메인 프레임의 헤더 파일 클래스 선언에서 아래와 같이 입력해 두자.



    class C(대화상자ID);


    class CMainFrame:public CFrameWnd


    {


    //…


    C(대화상자ID)* m_pDlg;


    //…


    }

    그리고, 위에서 선언된 멤버 변수를 생성자에서 초기화하는 것을 잊지 말기를 바란다.

    CMainFrame::CMainFrame()


    {


    m_pDlg = NULL;


    }


메뉴의 항목중 모달리스 대화 상자를 띄울 항목에 대해서 클래스 위저드로 연결시켜 해당 함수에 아래의 내용을 입력하자.



    if(m_pDlg != NULL) // 이미 대화 상자가 나타나 있을 경우…


    {


    m_pDlg->SetFocus(); // 시스템 포커스를 대화 상자로 맞춘다.


    }


    else // 만약 그렇지 않다면…


    {


    m_pDlg = new C(대화상자ID); // 새로 변수를 할당한다.


    m_pDlg->Create(this); // 생성한다.


    m_pDlg->ShowWindow(SW_SHOW); // 대화 상자를 표시하고 포커스를 맞춘다.


    }


이제, 닫는 부분을 처리해야 한다. 이것은 C(대화상자ID) 클래스의 OnClose() 함수에 DestroyWindow();를 입력하는 것으로 끝난다. 그리고, 가장 중요한 것이 남아있는데 동적 할당된 메모리를 원래대로 해지시켜야 하는 일이다.


C(대화상자ID) 클래스에서 사용할 수 있는 메시지 중에는 PostNcDestroy가 있는데 이것을 오버라이딩하여 아래와 같이 코딩하여 준다. 참, 코딩하기전에 메인 프레임에 대한 정보를 가져와야 하므로 #include 선행 처리문을 입력하는 것도 잊으면 안되겠다.



    #include “MainFrm.h”

    void C(대화상자ID)::PostNcDestroy()


    {


    ((CMainFrame *)AfxGetMainWnd())->m_pDlg = NULL;


    delete this;


    }  

댓글 남기기