5.“关于”对话框类(CAboutDlg)
该类封装了用于显示软件版本,版权等相关信息的“关于”对话框,通常不需要对它进行任何的编程。而只需要使用对话框资源编辑器对对话框模板进行简单的编辑即可。
3.源文件结构:
应用向导生成的应用程序具有很多原始的功能,例如:打开文件对话框等,而且还可以使用类向导向某个类添加成员函数或者成员变量,而且类向导可以将添加的成员安排在何时得位置。应用向导和类向导时怎么样实现这些自动功能呢?下面先浏览一下CCExcmpleView的头文件:
// CExcmpleView.h : interface of the CCExcmpleView class //
/////////////////////////////////////////////////////////////////////////////
#if !defined(AFX_CEXCMPLEVIEW_H__4FEB3544_9956_4E4C_93C9_35D40796D187__INCLUDED_) #define AFX_CEXCMPLEVIEW_H__4FEB3544_9956_4E4C_93C9_35D40796D187__INCLUDED_
#if _MSC_VER > 1000 #pragma once
#endif // _MSC_VER > 1000
class CCExcmpleView : public CView {
//Constructors
protected: // create from serialization only CCExcmpleView(); DECLARE_DYNCREATE(CCExcmpleView) // Attributes public: CCExcmpleDoc* GetDocument(); // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CCExcmpleView) public: virtual void OnDraw(CDC* pDC); // overridden to draw this view virtual BOOL PreCreateWindow(CREATESTRUCT& cs); protected: virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); //}}AFX_VIRTUAL // Implementation public: virtual ~CCExcmpleView(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif protected:
// Generated message map functions protected: //{{AFX_MSG(CCExcmpleView) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() };
#ifndef _DEBUG // debug version in CExcmpleView.cpp inline CCExcmpleDoc* CCExcmpleView::GetDocument() { return (CCExcmpleDoc*)m_pDocument; } #endif
///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif
// !defined(AFX_CEXCMPLEVIEW_H__4FEB3544_9956_4E4C_93C9_35D40796D187__INCLUDED_)
该代码的作用是声明CCExcmpleView类,但是这个声明包含在一个“#iif…#define…#endif”结构内,其目的时保证编译时此文件只被包含一次。下面介绍下头文件的组成部分。主要由注释块,访问类型以及分界符。 1.注释块:用“//”引导的绿色部分
Constructors块:构造块,用于声明该类的C++构造函数,以及所需的各种初始化函数。 Attributes块 : 共性或属性快,用于包含对象的共性或属性,
Operations块:操作块,用于包含成员函数,可以通过对象调用这些函数,以使该对象执行需要的任务或操作,
Overridables块:重载块,该块用于包含虚函数,当需要更改基类的行为时,可以在派生类中重载这些函数。
Implementation块;实现块,是MFC类声明中最重要的部分。实现块包括所有的实现信息,包括成员变量和成员函数。 2.访问类型。
Public ,protected,private 3.分界符:
从上面的代码可以看到如“//{{AFX_MSG(CCExcmpleView)”等的标识符,类向导使用几种特殊的分界符,用以区分向导生成的代码和用户输入的代码,这些格式化的分界符以注释的形式出现在代码中。如下所示: 分界符 通用定界符 AFX_MSG AFX_MSG_MAP AFX_VIRTUAL 对话框定界符 AFX_DATA AFX_DATA_INIT AFX_DATA_MAP 记录集定界符 AFX_FIELD AFX_FIELD_INIT AFX_FIELD_MAP OLE定界符 AFX_DISP AFX_DISP_MAP AFX_EVENT 在头文件中标志OLE自动化声明的起止 在实现文件中标志OLE自动化映射的起止 在头文件中标志OLE事件声明的起止 在头文件中标志用于数据库记录字段交换的成员变量声明的起止 在记录集类的构造函数中标志RFX的成员变量初始化的起止 在记录集类的DoFieldExchange函数中标志RFX函数调用的起止 在头文件中标志与消息映射相关的ClassWizard实体 在实现文件的类的消息映射中标志消息映射的起止 在头文件中标志虚函数重载声明的起止 在头文件中标志用于对话框数据交换(DDX)的成员变量声明的起止 在对话框类的构造函数中标志DDX的成员变量初始化的起止 在对话框类的DoDataExchange函数中标志DDX函数调用的起止 简要描述 AFX_EVENT_MAP 在实现文件中标志OLE事件的起止
“DECLARE_DYNCREATE(CCExcmpleView)”是MFC为支持该类的动态创建而提供的宏。
4.应用程序类:MFC程序的启动过程:终止过程
1.全局对象的产生:
全局对象在名为Global的文件夹中,此时只有一个theApp,从C++的学习中可以了解到,当操作系统将程序加载并激活时,全局对象将首先获得配置,因此其构造函数将首先被执行,也即时说它比WinMain更早,下来看这个构造函数到底做了什么。 CCExcmpleApp theApp; 从程序中看到,它自己的构造函数只是完成用户自定义的变量的初始化,而运行环境的初始化是在它的基类中完成的,它的基类时CWinApp,它的构造函数定义如下: CWinApp::CWinApp(LPCTSTR lpszAppName) {//参数时Windows使用的应用名称 if (lpszAppName != NULL) m_pszAppName = _tcsdup(lpszAppName); else m_pszAppName = NULL; // initialize CWinThread state初始化CWinThread state状态 AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE(); AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread; ASSERT(AfxGetThread() == NULL); pThreadState->m_pCurrentWinThread = this; ASSERT(AfxGetThread() == this); m_hThread = ::GetCurrentThread(); m_nThreadID = ::GetCurrentThreadId(); // initialize CWinApp state初始化CWinApp状态 ASSERT(afxCurrentWinApp == NULL);
// only one CWinApp object please存储theApp对象的指针 pModuleState->m_pCurrentWinApp = this; ASSERT(AfxGetApp() == this); // in non-running state until WinMain直到运行WinMain时,才是真正意义上的运行状态 m_hInstance = NULL; m_pszHelpFilePath = NULL;// 应用程序帮助文件的路径 m_pszProfileName = NULL; m_pszRegistryKey = NULL; m_pszExeName = NULL; m_pRecentFileList = NULL; m_pDocManager = NULL; m_atomApp = m_atomSystemTopic = NULL; m_lpCmdLine = NULL; m_pCmdInfo = NULL; // initialize wait cursor state m_nWaitCursorCount = 0; m_hcurWaitCursorRestore = NULL; // initialize current printer state m_hDevMode = NULL; m_hDevNames = NULL; m_nNumPreviewPages = 0; // not specified (defaults to 1) // initialize DAO state m_lpfnDaoTerm = NULL; // will be set if AfxDaoInit called
} // other initialization m_bHelpMode = FALSE; m_nSafetyPoolSize = 512; // default size
CWinApp的基类时CWinThread,CWinThread表示具有一个或多个线程的应用程序的主执行线程。
从上面代码可以看到,此函数主要时用来对线程和全局对象的初始化,同时保存theApp对象的指针,这样WinMain可以通过该指针调用它的成员函数,用以初始化和执行该应用.
2.应用程序入口-WinMain函数以及主框架创建
全局对象生成后,系统根据配置的CRT DLL(C-Runtime DLL,C运行时动态链接库)对WinMain函数进行调用,这些工作是由系统自动完成的,WinMain函数的定义如下: extern \_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // call shared/exported WinMain return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); }
_tWinMain中的_t是为了支持Unicode而定义的映射宏。
从代码里面看到,WinMain只是对另外一个函数AfxWinMain的简单调用,下面看AfxWinMain函数的实现过程。如下: int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { ASSERT(hPrevInstance == NULL); int nReturnCode = -1; CWinThread* pThread = AfxGetThread(); CWinApp* pApp = AfxGetApp(); // AFX internal initialization AFX内部初始化 dxq if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow)) goto InitFailure;