* 프로젝트 이름은 Test라고 가정.
* 중간에 참조되는 모든 클래스의 헤더파일이 인클루드 되어야 함.
* 뷰의 헤더가 인클루드 된다면 반드시 그 앞에 도큐먼트의 헤더가 인클루드 되어야 함.

1. 애플리케이션 클래스의 포인터를 얻을 때

    CWinApp* AfxGetApp()

2. 메인프레임 클래스의 포인터를 얻을 때

    CWnd* AfxGetMainWnd()

         이들 두 함수는 MFC의 전역함수로써 프로그램을 작성하는 도중 어디에서나  사용할수

         있다. MFC에서는 Afx~로 시작하는 함수들은 모두 전역함수를 의미한다.

         물론 타입 캐스팅을 해야하며, 사용법은 다음과 같다.

    CTestApp *pApp = (CTestApp *)AfxGetApp();
    CMainFrame *pFr = (CMainFrame *)AfxGetMainWnd();

         이 외에 뷰 클래스에서 그 뷰를 둘러싸고 있는 프레임 윈도우를 참조때는

    CFrameWnd* GetParentFrame() const

         함수를 사용할 수 있다. 물론 뷰 클래스뿐만이 아니라 일반적인 윈도우를 둘러싸는

         틀로써 프레임 윈도우가 사용될 수 있기 때문에 GetParentFrame() 함수는 CWnd() 클래스

         의 멤버함수로 되어있다.

         이 함수와 AfxGetMainWnd() 함수는 SDI에서는 같은 기능을 하지만,

         MDI에서는 메인 프레임 윈도우와 뷰를 둘러싸고 있는 프레임 윈도우가 다르기 때문에

         그 각각을 구하는 역할을 한다.

3. 도큐먼트 클래스의 포인터를 얻을 때는 몇 가지 경우

    (a) 뷰 클래스에서 도큐먼트 클래스에 접근할 때.

    이때는 말할 필요도 없이 GetDocument() 함수 사용. 뷰에 이미 정의되어 있는 함수죠. 하지만 사용자가 임의로 뷰를 추가한 경우에는 이 GetDocument() 함수가 포함되어 있지 않다.

    이럴 경우 기존에 있는 뷰에서 GetDocument() 함수 부분을 복사해다가 넣으면 된다. 이 부분은 Debug 모드와 Release 모드 두 가지의 함수가 있으므로 모두 복사해 넣아야 한다.

    (b) 임의의 클래스에서 도큐먼트 클래스에 접근할 때.

    CFrameWnd *pFr = (CFrameWnd *)AfxGetMainWnd();
    CTestDoc *pDoc = (CTestDoc *)pFr->GetActiveDocument();

    다음처럼 한 줄로 줄여써도 된다.

    CTestDoc *pDoc = (CTestDoc *) ((CFrameWnd *)AfxGetMainWnd())->GetActiveDocument();

4. 뷰 클래스의 포인터를 얻을 경우

      (a) 임의의 클래스에서 뷰 클래스에 접근할 때

        뷰 클래스의 포인터를 얻어야 하는 경우는 대부분 다이얼로그에서 뷰에 접근하거나,

        스플릿을 사용한 경우 다른 뷰 클래스에서 접근하는 경우가 대부분이다.

        뭐 어떻든 상관없이 다음과 같이 하면 어디서든 뷰에 접근할 수 있다.

    CTestView *pView = (CTestView *) ((CMainFrame *)AfxGetMainWnd())->GetActiveView();

    물론 위의 3번의 경우처럼 두 줄로 나누어 써도 상관 없다.

    (b) 도큐먼트 클래스에서 뷰 클래스에 접근을 할 때

    도큐먼트 클래스에서 뷰 클래스의 인스턴스 포인터를 얻으려면 GetFirstViewPosition() 함수와 GetNextView() 함수를 조합하여 사용해야 한다. 이렇게 복잡해지는 이유는 도큐먼트 하나에 여러개의 뷰가 연결될 수 있기 때문이다.

    도큐먼트에는 이에 연결된 뷰가 연결 리스트 형태로 관리되고 있기 때문에 몇 번째 뷰를 얻을 것인지 선택하고 나서 위의 함수를 조합하여 사용하면 된다.

    다음은 도큐먼트와 연결된 모든 뷰 클래스를 차례로 얻어 뷰 클래스의 멤버함수인 UpdateWindow() 함수를 호출하는 예제이다.

    POSITION pos = GetFirstViewPosition();
    while( pos != NULL )
    {
        CView *pView = GetNextView( pos );
        pView->UpdateWindow();
    }

    물론 이와 같은 효과를 내기 위해서 도큐먼트 클래스의 멤버함수인 UpdateAllViews(NULL) 함수를 호출해도 된다. 여기서 쓰이는 인자인 NULL 은 모든 뷰를 업데이트하는 것이고, NULL 대신, 신호를 보내는 뷰의 포인터를 넣어주면 신호를 보내는 뷰는 빼고 나머지 뷰만 업데이트를 한다.

    도큐먼트에 뷰가 오직 하나만 연결되어 있는 경우에는 다음과 같이 간단하게 뷰 클래스의 인슽턴스 포인터를 얻어낼 수도 있다. m_viewList 는 CDocument 클래스의 멤버변수로서, 뷰를 관리하는 연결 리스트이다. 이것을 이용하여 GetHead() 함수를 호출하면 리스트에 들어있는 첫 번째 뷰가 얻어진다.

    void CTestDoc::OnRepaintViews()
    {
        CView *pView = m_viewList.GetHead();
        pView->UpdateWindows();
    }

    (c) 스플리트 윈도우에서의 각 뷰 클래스에 접근할 때

    동적 스플리트 윈도우라면 모든 페인에서 같은 뷰를 사용하므로 별 문제가 되지 않는데, 정적 스플리트 윈도우라면 각 페인마다 다른 뷰를 사용할 수 있으므로 각 페인별로 뷰의 인스턴스 포인터를 얻는 것이 문제가 되는 경우가 생길 수 있다.

    이렇때는 메인 프레임 클래스에서 정의한 CSplitterWnd 클래스의 변수인 m_wndSplitter 의 멤버함수 GetPane()을 사용하면 각 페인의 뷰에 접근할 수 있다.

    우선 메인 프레임에서 정의된 m_wndSplitter 변수를 public: 속성으로 바꾸고(외부에서 접근해야 하므로) 메인 클래스의 인스턴스 포인터를 얻은 다음, 다시 여기서 m_wndSplitter 변수에 접근하여 이 멤버변수의 멤버함수 GetPane()을 이용하면 된다. 다음은 GetPane()의 함수 원형이다. 리턴값은 대부분의 경우 CView에서 파생된 클래스의 인스턴스 포인터가 된다.

    CWnd* GetPane( int row, int col );

    임의의 클래스에서 다음과 같이 사용하면 페인에 연결된 뷰의 포인터를 얻을 수 있다.

       CTestView *pView = (CTestView *)((CMainFrame *)AfxGetMainWnd())->

                                                                    m_wndSplitter.GetPane(0,1);

2006/05/13 23:01 2006/05/13 23:01

글 걸기 주소 : 이 글에는 트랙백을 보낼 수 없습니다

덧글을 달아 주세요