LuvSea

[MFC 기초] 자동생성 클래스 분석 - CWinApp 본문

sTudy

[MFC 기초] 자동생성 클래스 분석 - CWinApp

사랑海 2009. 10. 13. 18:55
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

[출처] http://myhome.hanafos.com/~log0/mfc/mfc03.htm

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

/* CLyraApp 클래스는 CwinApp 클래스를  상속받았으므로 메세지 발생시 다음 줄의 함수를 실행하라는 의미. */
BEGIN_MESSAGE_MAP(CLyraApp, CwinApp)
   //{{AFX_MSG_MAP(CLyraApp)

/* ID_APP_ABOUT란 일종의 이름이라고  생각하자. 
    다시 말해 한개의 프로젝트에 같은 이름이 존재 해서는 않되며 유일해야만 한다. 
    즉 프로젝트에 사용되는 개체와  연결 고리인 것이다. About DEMO1란 팝업 메뉴를 선택하면 OnAppAbout 함수를 실행하라는 의미. */
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
       
/* 팝업 메뉴에서 File -> New를  선택하면 CwinApp 클래스의 OnFileNew 함수를 실행하라는 의미. */
ON_COMMAND(ID_FILE_NEW,  CwinApp::OnFileNew)

/* 팝업 메뉴에서 File->Open을 선택하면  CwinApp 클래스의 OnFileOpen 함수를 실행하라. */       
ON_COMMAND(ID_FILE_OPEN,  CwinApp::OnFileOpen)
       // Standard print setup command

/* 팝업 메뉴에서 File->PrintSetup을  선택하면 CwinApp 클래스의 OnFilePrintSetup 함수를 실행하라. */ 
ON_COMMAND(ID_FILE_PRINT_SETUP,  CwinApp::OnFilePrintSetup)
END_MESSAGE_MAP() 

BEGIN_MESSAGE_MAP(CLyraApp, CwinApp), END_MESSAGE_MAP() 
위 Source는 BEGIN_MESAGE_MAP 부분이다.
이상한 점은 세미콜론(;)이 없다는 것이다.
Visual C++은 윈도우 프로그래밍이다. 이말은 즉 모든 실행을 메세지로 처리한다는 뜻이다.

위에서 알수 있듯이 기본적으로 생성된 프로그램에는 보통 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안에 이 정보가 들어간다. 다음 내용은 이 정보를 실행시키는 것입니다.

// 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 대화상자를 벗어나 이 프로그램내의 다른 명령을 내릴수 없다는 뜻이다.
Comments