SDI 형태
1.     MainFrame 얻기
-          CMainFrame *pFrame = (CmainFrame *) AfxGetMainWnd();

2.     App 포인터 얻기
-          CTestApp *pApp = (CtestApp *) AfxGetApp();

3.     Document 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
            CTestDoc *pDoc = (CTestDoc *)pFrame->GetActiveDocument();
-          CTestDoc *pDoc = ((CMainFrame *)AfxGetMainWnd())->GetActiveDocument();

4.     View 포인터 얻기

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

MDI 형태
1.     ChildFrame 포인터 얻기
-          CMainFrame *pFrame = (CMainFrame *)AfxGetMainWnd();
           CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
-          CChildFrame *pChild = ((CMainFrame *)AfxGetMainWnd())->GetActiveFrame();

2.     Document 포인터 얻기
-           CMainFrame *pFrame = (CMainFrame)AfxGetMainWnd();
            CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
            CMdiTestDoc *pDoc = (CMdiTestDoc *)pChild->GetActiveDocument();
-          CMdiTestDoc *pDoc = (((CMainFrame *)AfxGetMainWnd())->GetActiveFrame())->GetActiveDocument();

3.     View 포인터 얻기
-          CCainFrame *pFrame = (CMainFrame)AfxGetMainWnd();
            CChildFrame *pChild = (CChildFrame *)pFrame->GetActiveFrame();
            CMdiTestView *pView = (CMdiTestDoc *)pChild->GetActiveView();
-          CMdiTestView *pView = (((CMainFrame *)AfxGetMainWnd())->GetActiveFrame())->GetActiveView();

--------SDI----------------

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

CWinApp* AfxGetApp()

함수를 사용합니다.

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

CWnd* AfxGetMainWnd()

함수를 사용합니다.

 이들 두 함수는 MFC의 전역함수로써 프로그램을 작성하는 도중 어디에서나 사용할 수 있습니다. MFC에서는 Afx~로 시작하는 함수들은 모두 전역함수를 의미합니다.

 물론 타입 캐스팅을 해야 하구요. 사용법은 다음과 같습니다.

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

이렇게 써준 다음에는 pApp와 pFr은 각각 애플리케이션 클래스와 메인 프레임 클래스의 인스턴스 포인터를 가리키게 됩니다.

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

    CFrameWnd* GetParentFrame() const

함수를 사용할 수 있습니다. 물론 뷰 클래스뿐만이 아니라 일반적인 윈도우를 둘러싸는 틀로써 프레임 윈도우가 사용될 수 있기 때문에 GetParentFrame() 함수는 CWnd() 클래스의 멤버함수로 되어있습니다.

 이 함수와 AfxGetMainWnd() 함수는 SDI에서는 같은 기능을 하지만, MDI에서는 메인 프레임 윈도우와 뷰를 둘러싸고 있는 프레임 윈도우가 다르기 때문에 그 각각을 구하는 역할을 합니다.

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

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

      이때는 말할 필요도 없이 GetDocument() 함수를 쓰면 됩니다. 뷰에 이미 정의되어 있는 함수죠. 하지만 사용자가 임의로 뷰를 추가한 경우에는 이 GetDocument() 함수가 포함되어 있지 않습니다. 이럴 경우 기존에 있는 뷰에서 GetDocument() 함수 부분을 복사해다가 넣으면 됩니다. 이 부분은 Debug 모드와 Release 모드 두 가지의 함수가 있으므로 모두 복사해 넣아야 합니다.

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

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

    위와 같이 두 줄에 걸쳐 써도 되고 다음처럼 한 줄로 줄여써도 됩니다.

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

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

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

     뷰 클래스의 포인터를 얻어야 하는 경우는 대부분 다이얼로그에서 뷰에 접근하거나, 스플릿을 사용한 경우 다른 뷰 클래스에서 접근하는 경우가 대부분일 겁니다. 뭐 어떻든 상관없이 다음과 같이 하면 어디서든 뷰에 접근할 수 있습니다.

    CTestView *pView = (CTestView *) ((CMainWnd *)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);

-------- MDI ---------------

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

    CWinApp* AfxGetApp()

함수를 사용합니다. 이것은 SDI에서와 동일합니다. App 클래스는 MDI든 SDI든 프로그램 내에서는 하나뿐이니까요. 다음처럼 사용하면 pApp는 애플리케이션 클래스의 인스턴스 포인터를 가리키게 됩니다.

    CTestApp *pApp = (CTestApp *)AfxGetApp();

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

    CWnd* AfxGetMainWnd()

함수를 사용합니다. 사용법은 SDI에서와 동일합니다.

    CMainFrame *pFr = (CMainFrame *)AfxGetMainWnd();

이렇게 써준 다음에는 pFr은 메인 프레임 클래스의 인스턴스 포인터를 가리키게 됩니다.

3. CMDIChildWnd의 파생클래스인 자식 프레임 윈도우의 포인터를 얻을 때

    (a) 활성화된 자식 프레임 윈도우의 포인터를 얻을 때

      virtual CFrameWnd* GetActiveFrame( );

    함수를 사용합니다. MSDN에 실려있는 이 함수의 리턴값에 대한 설명을 보면, 애플리케이션이 SDI이거나 MDI 프레임 윈도우에 활성화된 도큐먼트가 없을 때, 리턴값은 묵시적인 this 포인터가 된다고 하네요.

    사용법은 다음과 같습니다.

    CMDIChildWnd* pChild = (CMDIChildWnd *)AfxGetMainWnd()->GetActiveFrame();

4. 뷰 / 도큐먼트 클래스의 포인터를 얻을 때

 SDI 에서 구한 것과 마찬가지 방법을 사용한다. SDI에서는 메인 프레임의 포인터를 얻어 GetActiveView() 또는 GetActiveDocument() 함수를 사용했지만, MDI에서는 차일드 프레임의 포인터를 얻어 거기서 GetActiveView() / GetActiveDocument() 함수를 사용하면 된다. 사용법은 거의 동일하다.

 MDI에서도 SDI와 마찬가지로 도큐먼트나 뷰가 여러 개가 연결될 수 있으므로 그점만 주의해 주면 된다.

 사용법은 다음과 같다.

    CMDIChildWnd* pChild = (CMDIChildWnd *)AfxGetMainWnd()->GetActiveFrame();

    // 뷰 클래스의 포인터 얻기
    CTestView *pView = (CTestView *)pChild->GetActiveView();  

    // 도큐먼트 클래스의 포인터 얻기
    CTestDoc *pDoc = (CTestDoc *)pChild->GetActiveDocument();


'1.소프트웨어 이야기 > 01.MFC(Visual Studio)' 카테고리의 다른 글

[펌] DialogBar 구현  (0) 2008.08.07
클래스간 포인터 얻기  (0) 2007.12.06
MFC Socket 사용시 유의점  (0) 2007.12.06
함수 포인터의 단점은 다음과 같습니다.

1) 디버깅이 어렵다.
(콜백함수나 이벤트 핸들링의 경우가 아니고) 함수 포인터를 사용하여 수동으로 호출하는 함수가 몇십개나 된다고 가정해 봅시다.
분 기하기전에 브레이크 포인트를 걸고 어떤 함수로 분기하고자하는지 알고자 할때는 너무 어렵죠. 예를 들어 변수 a라면 값을 바로 알아 낼 수 있지만, 함수 포인터 p라면 그 값이 어떤 함수를 가리키는지 알 수가 없죠. 이럴때는 분기 가능한 모든 함수에 브레이크 포인터를 거는 수밖에 없습니다.

2) 속도가 느리다.
ANSI C 라이브러리에서 함수 포인터를 사용하는 대표적인 함수인 qsort의 경우를 생각해 봅시다. 대소 비교를 위해서 fcmp라는 함수 포인터를 사용하는 데, 이건 qsort 내부에서 대소 비교가 필요할 때마다 매번 호출됩니다.
실제 정렬하는 시간보다 함수 호출을 위한 비용이 훨씬 크게 되어버립니다.

그래서 ANSI C++ STL에서 이런 문제점을 해결하기 위해 만든 것이 함수 포인터를 대신하는 함수 객체(function object)입니다.
함수 객체란 멤버 함수로 함수 하나만 들어 있는 매우 간단한 클래스입니다.
클래스이기 때문에 당연히 인라이닝할 수 있지요.
그래서, STL의 sort가 C의 qsort보다 무려 67000배나 빠릅니다!

콜백함수나 이벤트 핸들링과 같이 반드시 필요한 경우나,
함수 포인터를 써야만 코드가 매우 간결해지는 경우외에는 가능한 한 사용하지 않는 것이 좋습니다.

출처 : 볼랜드포럼
#include<stdio.h>
#include<conio.h>

//------------------------------------------------------------------
int* (*Func1())();
int* (*Func1_1())();
int* (*Func1_2())();
int* (*Func1_3())();
int* Func2();
int* Func2_1();
int* Func2_2();

#define N 8
int *(*(*a[N])())() = {Func1,Func1_1,Func1_2,Func1_3,NULL,};
/*
위는 배열 a를 선언/정의한 것이며 해석해보면 아래와 같습니다.
형을 해석할 때는 가장 안쪽 괄호부터 합니다.
*a[N] : 원소수가 N개인 포인터 배열 a
       , 이 배열의 각원소인 포인터가 무엇을 가리키느냐는 다음 괄호를 해석.
*() : 포인터를 반환(return)하는 함수
      ,위의 배열 각 원소가 바로 이 함수형으로 정의된 함수를 가리킴
      ,그리고 이 함수가 포인터를 반환한다고 했는데 그 포인터가 어떤 것인지는 다음을 해석
int *() : int*를 반환하는 함수
       ,위의 함수가 반환하는 포인터는 이 함수형으로 정의된 함수를 가리킴.

참고로, 이런 복잡한 형은 거의 사용하지 않습니다.
이해가 잘 안되면 그냥 넘어가시기를 권합니다.
프로그램 경력이 늘면 차츰 쉽게 이해가 됩니다.
다만, 아래 1,2는 알고 계시는게 좋습니다.
1. 포인터 배열과 배열을 가리키는 포인터의 구별
int *arr[16]; 포인터 배열 arr(원소수가 16개이고 각 원소는 포인터(int*))
int (*arr)[16]; 배열(원소수가 16개이고 각원소는 int형)을 가리키는 포인터 변수 arr

2. 포인터를 반환하는 함수와 함수를 가리키는 포인터의 구별
int* Func(float); float형 매개변수 하나를 취하고 포인터를(int*)를 반환하는 함수 Func
int (*Func)(float); 함수(float형 매개변수 하나를 취하고 int를 return)를 가리키는 포인터 Func

3. 어떤 함수가 있을 때 이를 가리키는 포인터 선언/정의 방법
int* Func(float); 함수가 있다고 하면
우선 함수이름 부분을 괄호로 묶습니다: int* (Func)(float);
다음으로 함수이름 바로 앞에 *를 붙입니다: int* (*Func)(float);
마지막으로 이름을 중복되지 않은 원하는 것으로 지정합니다: int* (*pFunc)(float);

4. 특정형으로의 형변환 방법
int* (*Func)(float)로 형변환 하려면
우선 변수의 이름을 지웁니다: int* (*)(float)
전체를 괄호로 묶습니다: (int* (*)(float))

5. typedef
int* (*Func)(float);
위와 같은 형을 만들려면 앞에 typedef를 붙인다음: typedef int* (*Func)(float);
형의 이름을 원하는 것으로 정해주면 됩니다:  typedef int* (*FuncPointerType)(float);
*/

//출처 - 볼랜드포럼

+ Recent posts