훈, IT 공부/C,C++,MFC

[MFC] 각클래스 객체 포인터 얻어오기

IT훈이 2018. 4. 28.
반응형

 MFC 정리가 필요해서 끄적끄적 작성하고 코드로 쳐보고 해보았습니다. 추가해야하는 부분은 점차 수정해나가겠습니다.


MFC 로 프로젝트 생성하였다는 가정하에 정리합니다. 프로젝트명 Test


CTestApp(CWinApp 상속) - 프로그램의 생성을 담당하는 영역, 프로그램 초기화관련

CMainFrame(CFrameWnd상속)- 겉 프레임을 윈도우 담당하는 클래스 

CTestDoc(CDocument상속) - 문서의 저장 열기 등등, 문서 담당하는 클래스 

CTestView(CView상속) - 화면을 담당하는 클래스

CTestDlg(CDialog상속) - 도움말 대화상자 클래스


CTestApp 포인터 얻어오기


CTestApp은 CWinApp를 상속받는다.


어느곳에서나 CTestApp의 포인터를 얻고자 한다면 AfxGetApp() 전역함수를 사용한다.


CTestApp *pApp = AfxGetApp();


하지만 위와같이 사용하면 에러가 발생한다.


error C2440: 'initializing' : connot convert from 'class CWinApp *' to 'class CTestApp *'


에러를 보면, CWinApp*를 CTestApp *로 변환할 수 없다는 것이다. AfxGetApp()의 함수 원형이


CWinApp* AfxGetApp()


이기 때문이다. 문제해결을 위해서는 형변환을 해주어야한다.


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


이제는 컴파일 에러없이 잘 될 것이다. 그리고 발생하는 에러중에

 

error C2065: 'CTestApp' : undeclared identifier


이 에러는 CTestApp 클래스의 선언 부분이 포함(include)되지 않았다는 것이다. 이럴 때는 CTestApp 클래스의 선언을 포함시켜야한다.


#include "Test.h"


이제 pApp는 생성된 CTestApp의 객체 포인터이기 때문에, CTestApp 객체에 접근이 가능하다. CTestApp에 int nIndex 변수가 있었다고 가정하자


pApp->nIndex = 10; 


이런방식으로 접근이 가능하다. 단 public 접근자에만 접근이 가능하다.



 CMainFrame 포인터얻어오기


CMainFrame 는 CFrameWnd를 상속받는다.


AfxGetMainWnd() 


CWinThread::m_pMainWnd 를 직접 참조하지 않고 포인터로 참조하는 방식이다.


CMainFame *pFrame = AfxGetMainWnd();


두 가지 에러와 만나게 된다.

첫 번째, CMainFrame에 대해서 컴파일러가 모르겠다는 에러이다.


error C2065: 'CMainFrame' : undeclared identifier


이 에러를 수정하기 위해서는 CMainFrame 클래스가 선언되어있는 헤더파일을 포함시키면 된다. 포함 시키는 위치도 순서에 맞추는 것이 좋다. Test.h와 TestDoc.h 사이가 좋다.


#include "stdafx.h"

#include "Test.h"


#include "MainFrm.h"


#include "TestDoc.h"

#include "TestView.h"


이 에러를 해결하고 나면, CTestApp에서 발생했던 에러가 발생한다.


error C2440: 'initializing' : cannot convert from 'class CWnd *' to 'class CMainFrame *'


에러를 보면, Cwnd* 를 CMainFrame* 으로 변환할 수 없다는 것이다. AfxGetMainWnd()원형이


CWnd* AfxGetMainWnd(); 


이기 때문이다. 이 문제를 해결하기 위해서는 형변환을 해주어야한다.


CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd();


이제는 컴파일 에러 없이 잘 될 것이다. 

CMainFrame()객체는  CFrameWnd을 상속받았고 CFrameWnd 객체는 CWnd을 상속받았기 때문에 pFrame포인터를 통해서 CFrameWnd클래스와 CWnd클래스의 맴버를 모두 호출가능하다. 만약 윈도우의 타이틀을 바꾸고 싶다면


pFrame->SetWindowText(_T("이름바꿔버리기"));


처럼 사용하면 된다.



CMainFrame*는 또 다른 이유로 자주 사용하게 되는데, 그 이유는 도큐먼트(CTestDoc)와 뷰(CTestView)클레스에 접근하기 위해서이다. CMainFrame 클래스는 뷰에 접근하는 GetActiveView() 함수와 문서에 접근하는 GetActiveDocument() 함수를 제공한다. 


우리가 어느 특정 클래스를 만들어서 사용하고, 이 클래스가 뷰에 접근해야한다면 다음과 같은 문장을 사용해야한다.


CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd();

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


또한 도큐먼트 클래스에 접근하기 위해서는 아래와 같이 작성한다.


CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd();

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


물론 이 때는 헤더파일을 포함시켜야 한다. 


#include "MainFrm.h"

#include "CTestDoc.h"

#include "CTestView.h"


만약 대화 상자에서 도큐먼트 클래스에 접근하려면 어떻게 할 것인가?? 방법은 위와 같다.


다음은 뷰에서 도큐먼트에 접근하는 것과 도큐먼트에서 뷰에 접근하는 것에 대해 알아보자


CTestDoc *pDoc = (CTestDoc*)GetDocument();


를 호출하면 된다. 물론 View클래스에는 GetDocument()함수가 존재해야한다. 일반적으로 이 함수는 MFC로 프로젝트 생성시 기본으로 있다. 하지만 만약 직접 만든 새로운 클래스라면 GetDocument() 함수를 직접 만들어 주어야한다. 직접 만들기가 귀찮다면 ,다음과 같이 사용해도 된다. 


CTestDoc* pDocument = (CTestDoc*)m_pDocument;

m_pDocument는 CTestView 클래스의 맴버이며, 다음과 같이 선언되어 있다.

CDocument *m_pDocument;


그리고, 도큐먼트에 뷰 클래스를 참조 하려면 아래와 같이 해야한다.


POSITION pos = GetFirstViewPosition();

CTestView* pView = (CTestView*)GetNextView(pos);


도큐먼트는 뷰 클래스를 내부적으로 링크드리스트를 사용해서 관리하고 있다. 그러므로 GetFirstViewPosition() 함수를 통해 POSITION을 얻어온 다음, GetNextView()함수를 통해 뷰의 포인터를 얻어오면 된다. 만양 창 분할에 의해 뷰가 여러개 존재한다면, 다음과 같이 얻어올 수 있다. 만약 컴파일 에러가 발생하면, 

#include "TestView.h" 처럼 해서 헤더 파일을 포함하는 것도 잊지 말자.


POSITION pos = GetFirstViewPosition();

CTestView1 *pView1 = (CTestView1*)GetNextView(pos);

CTestView2 *pView2 = (CTestView2*)GetNextView(pos);

CTestView3 *pView3 = (CTestView3*)GetNextView(pos);

CTestView4 *pView4 = (CTestView4*)GetNextView(pos);

.....



그렇다면 CTestApp 클래스에서 뷰(CTestView) 클래스는 어떻게 얻어올 수 있을까? 쉽게 응용할 수 있지만 머리가 꽉 막힐 수도 있다. 이곳에서 혹시 에러가 나면 헤더 파일을 잘 추가해야 할 것이다. 


CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

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


뷰(CTestView) 클래스에서 CMainFrame에 접근할 수 있는데 AfxGetMainWnd()함수 외에도 


CMainFrame* pFrame = (CMainFrame*)GetParentFrame();


이렇게 사용 가능하다.



http://kaen2891.tistory.com/5

참조

반응형

댓글