본문 바로가기

Language/MFC

4대클래스 자동생성 소스 분석[CWinApp]


자동생성 클래스 분석 - CWinApp

AppWizard 단계를 거치고 나면 Lyra 프로젝트를 만들고 나면 자동적으로

CWinApp -> CLyraApp

CMDIFrameWnd -> CMainFrame

CDocument -> CLyraDoc

CView -> CLyraView인4개의 클래스가 만들어진다.

한가지 덧붙이면 WorkSpace 창에서 클래스 탭을 클릭하면 현재 생성된 클래스들을 볼수 있다.

클래스는 *.CPP, *.h 두 파일을 모두 보여 준다. 클래스 이름을 클릭하면 *.h 파일을 볼수 있고

해당 클래스의 함수를 클릭하면 *.cpp 파일이 보여지며 클래스를 수정해도 *.cpp, *.h 파일이

함께 자동 변경된다.

CLyraApp클래스

 

우선 CWinApp 클래스다. 애플리케이션 클래스로 CLyraApp란 클래스가 만들어지고 그것은

Lyra.cpp 파일에 기록된다. 이 CLyraApp 클래스는 CWinApp클래스를 상속받아서 사용한다.

즉 CWinApp 클래스의 기능을 물려받고 거기다가 개발자가 하고자하는 기능을 넣으면 된다.

CWinApp라는 것은 애플리케이션을 만들 때 필요한 클래스다.

 

 

CLyraApp파일을 한 번 열어보면.

 

#include "stdafx.h"

#include "Lyra.h"

 

#include "mainfrm.h"

#include "Lyradoc.h"

#include "Lyraview.h"

 

#indef _DEBUG

#UNDEF THIS_FILE

ststic char BASED_CODE THIS_FILE[] = _FILE_;

#endif

 

 

여기까지는 C++ 언어를 접해본 사용자라면 평이하게 넘어갈 것이다.

 

 

BEGIN_MESSAGE_MAP(CLyraApp, CwinApp)

//{{AFX_MSG_MAP(CLyraApp)

ON_COMAND(ID_APP_ABOUT, OnAppAbout)

// NOTE-the Classwizard will add and remove

mapping macros here.

// DO NOT EDIT what you see in these block of

generated code!

//}}AFX_MSG_MAP

// Standard file based document commands

ON_COMMAND(ID_FILE_NEW, CwinApp::OnFileNew)

ON_COMMAND(ID_FILE_OPEN, CwinApp::OnFileOpen)

// Standard print setup command

ON_COMMAND(ID_FILE_PRINT_SETUP, CwinApp::OnFilePrintSetup)

END_MESSAGE_MAP()

 

BEGIN_MESSAGE_MAP(CLyraApp, CwinApp),

END_MESSAGE_MAP()

 

BEGIN_MESAGE_MAP 부분이다. 이상한 점은 세미콜론(;)이 없다는 것이다. Visual C++은 윈도우

프로그래밍이다. 이말은 즉 모든 실행을 메세지로 처리한다는 뜻이다.

 

BEGIN_MESSAGE_MAP(CLyraApp, CwinApp)

//CLyraApp 클래스는 CwinApp 클래스를 상속받았으므로 메세지 발생시 다음 줄의 함수를 실행

하라는 의미.

 

ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

//ID_APP_ABOUT란 일종의 이름이라고 생각하자. 다시 말해 한개의 프로젝트에 같은 이름이 존재

해서는 않되며 유일해야만 한다. 즉 프로젝트에 사용되는 개체와 연결 고리인 것이다. About

DEMO1란 팝업 메뉴를 선택하면 OnAppAbout 함수를 실행하라는 의미.

 

ON_COMMAND(ID_FILE_NEW, CwinApp::OnFileNew)

//팝업 메뉴에서 File -> New를 선택하면 CwinApp 클래스의 OnFileNew 함수를 실행하라는 의미.

 

ON_COMMAND(ID_FILE_OPEN, CwinApp::OnFileOpen)

//팝업 메뉴에서 File->Open을 선택하면 CwinApp 클래스의 OnFileOpen 함수를 실행하라.

 

ON_COMMAND(ID_FILE_PRINT_SETUP, CwinApp::OnFilePrintSetup)

//팝업 메뉴에서 File->PrintSetup을 선택하면 CwinApp 클래스의 OnFilePrintSetup 함수를

실행하라.

 

END_MESSAGE_MAP()

 

쉽게 이해가 될 것이다.

위에서 알수 있듯이 기본적으로 생성된 프로그램에는 보통 File메뉴와 Edit메뉴, Window메뉴,

Help메뉴가 들어간다. 또한 위의 4개의 함수는 CWinApp에서 제공 되는 기본 함수이다. 몇 번의

클릭으로 여러분은 엄청난 일을 했다. 원하는 다른 함수를 동작시키려면 위의 메시지 매핑에

사용자가 직접 써 넣어야 한다.

 

다른 함수는 CLyraApp의 생성자입니다. 혹시 생성자를 모르는 사람을 위해 잠깐 설명하도록

하겠습니다. 이것은 이 클래스가 생행됨과 동시에 자동적으로 실행되는 함수 이다. 이 클래스

는 프로그램이 시작됨과 동시에 실행된다.

그런데 안에는 아무것도 없다. 즉 지금 현재는 생성시 아무것도 하지 않겠지만 후에 애플

리케이션 클래스가 생성될 때 어떤 일을 해야 한다는 이 함수 안에 기록하면 된다.

 

CLyraApp::CLyraApp()

{

// TODO add construction code here,

// place all significant initialization in InitInstance

}

 

 

위의 함수는 CLyraApp의 생성자다.

CLyraApp 클래스가 실행됨과 동시에 자동적으로 실행되는 함수이며 프로그램이 시작과 동시에

실행된다. 생성자와 같이 CLyraApp 클래스의 실행과 함께 CWinApp::InitInstance() 함수가

작동한다.

그리고 상속받은 것을 무시하려면 헤더에 다음과 같이 등록한다.

virtual BOOL InitInstance();

 

아래의 예는 AppWizard 4단계에서 사용자 인터페이스 옵션 항목에서 3D Controls를 Enable했다

는 가정에서 이다.

 

 

BOOL CLyraApp::InitInstance()

{

#ifdef _AFXDLL

Enable3dControls(); // Call this when using MFC in a shared DLL

#else // Call this when linking to MFC statically

Enable3dControlsStatic();

#endif

 

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

//위의 값은 윈도우 레지스트리에 저장된다. 레지스트리 편집기로 확인해 보도록 하세요.

//위의 값을 자기의 이름이나 뭐 아무거나 넣어 보세요.

 

LoadStdProfileSettings(); //Load standard INI file options (including MRU)

//위 또한 AppWizard 4단계에서 사용자 인터페이스 옵션 항목에서 MRU File List 항목에서 개

수를 넣었을 것이다. 뭐냐하면 최근 열어본 파일을 리스트화 해서 사용하기 편하게 팝업 메뉴에

추가해 놓은 것이다.

 }

 

 

CSingleDocTemplate* pDocTemplate;

pDocTemplate = new CSingleDocTemplate(

IDR_MAINFRAME,

RUNTIME_CLASS(CLyraDoc),

RUNTIME_CLASS(CMainFrame), // main SDI frame window

RUNTIME_CLASS(CLyraView));

AddDocTemplate(pDocTemplate);

// Parse command line for standard shell commands, DDE, file open

 

이 프로젝트를 SDI로 선택했었다. 그렇다면 MDI 처럼 사용될 데이터를 저장할 공간이 있어야 하는

것은 아니다. 단 SDI에 필요한 하나의 공간을 설정해 주는 클래스가 CSingleDocTemplate입니다.

pDocTemplate라는 가상적인 CSingleDocTemplate 형의 변수를 선언하고 이것이 생성될 때는

CLyraDoc 클래스인 Document와 CMainFrame 형태인 틀과 CDemo1View인 화면이 링크되면서

RC(리소스) 파일의 String Table 안에 설정된 IDR_MAINFRAME형으로 연결됩니다.

 

다음은 도스창에서 프로그램을 실행시켰을 경우나 또는 DDE나 파일 설정 등으로 실행했을 때

넘겨주는 인자를 받는 내용이다.

 

CCommandLineInfo cmdInfo;

ParseCommandLine(cmdInfo);

 

위의 내용은 CCommandLineInfo라는 클래스 변수 cmdInfo를 만들고 현재 프로그램이 실행되면서

어떤 인자가 들어왔나 조사하기 위한 ParseCommandLine 라는 함수를 실행하는 것이다. 또한

AddDocTemplate 함수를 이용하여 여러개의 Doc와 View와 Frame이 연결된 템플리트를 만들어

등록하였을 경우에도 cmdInfo안에 이 정보가 들어갑니다. 다음 내용은 이 정보를 실행시키는

 

// Dispatch commands specified on the command line

 

if (!ProcessShellCommand(cmdinfo))

return FALSE;

 

 

ProcessShellCommand 함수가 실행되면서 OnFileNew()라는 함수가 실행됩니다. 이 함수가 실행

되면 프레임과 도큐먼트 그리고 View가 만들어진다.

 

 

// The main window has been initialized, so show and update it.

pMainFrame->ShowWindow(SW_SHOW);

pMainFrame->UpdateWindow();

 

 

아래의 코드는 About 팝업 메뉴를 클릭했을 때의 실행코드 다.

기본 클래스의 설명 범주에 벗어나지만 간략히 설명하고 CLyraapp 클래스의 설명을 마치도록 하겠다.

CAboutDlg도 하나의 클래스이며 CDialog 클래스를 상속받았다.

 

 

// CAboutDlg dialog used for App About

 

class CAboutDlg : public CDialog

{

public:

 

CAboutDlg();

 

// Dialog Data

 

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX };

//}}AFX_DATA

 

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

//}}AFX_VIRTUAL

 

// Implementation

protected:

 

//{{AFX_MSG(CAboutDlg)

// No message handlers

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

  };

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

 

//{{AFX_DATA_INIT(CAboutDlg)

//}}AFX_DATA_INIT

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

 

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CAboutDlg)

//}}AFX_DATA_MAP

}

 

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

 

//{{AFX_MSG_MAP(CAboutDlg)

// No message handlers

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

// App command to run the dialog

void CLyrasApp::OnAppAbout()

{

 

CAboutDlg aboutDlg;

aboutDlg.DoModal();

}

 

 

바로 위의 OnAppAbout() 함수에 의해 대화상자가 사용자에게 보여진다.

aboutDlg.DoModal();의 의미는 프로그램에서 About 대화상자를 열었을 경우 이 대화상자를 종료

하기 전까지는 About 대화상자를 벗어나 이 프로그램내의 다른 명령을 내릴수 없다는 뜻이다.