创建的MFC应用程序名为:wd,那么:
一、wd.h解析
// wd.h : main header file for the WD application
//
#if !defined(AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_)
#define AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_
//////////////////////////////////////////////////////////////////
//以下语句的作用是:判断当前微软编译器的版本,如果版本大于1000,那么“#pragma once”这个语句就会被编译。
//////////////////////////////////////////////////////////////////
#if _MSC_VER > 1000 //Microsoft Compiler version 在_MSC_VER较小时,它对一些东西的支持与新版不同
#pragma once //这是一个比较常用的C/C++杂注,只要在头文件的最开始加入这条杂注,就能够保证头文件只被编译一次
#endif // _MSC_VER > 1000
#ifndef __AFXWIN_H__
#error include ‘stdafx.h‘ before including this file for PCH
#endif
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CWdApp:
// See wd.cpp for the implementation of this class
//
class CWdApp : public CWinApp
{
public:
CWdApp();
// Overrides 指示你可以对InitInstance函数进行重载
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CWdApp)
public:
virtual BOOL InitInstance(); //它的作用是初始化实例对象,它是一个虚函数,mfc已经定义了这个函数,但你可以重载它来完成自己的初始化实例功能,如果没有定义就会调用Mfc的默认函数。
//}}AFX_VIRTUAL
// Implementation 指示你可以去实现OnAppAbout函数
//{{AFX_MSG(CWdApp)
afx_msg void OnAppAbout(); // afx_msg本身只是一个注释宏,就是起注释作用的宏定义,指明当前函数是mfc框架中的消息响应函数;OnApptAbout()函数就是当选择 "帮助"里面的 "关于"菜单时,调用的函数一般是弹出一个对话框显示程序的一些信息
// 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()//DECLARE_MESSAGE_MAP()宏的作用是向类中添加消息映射必要的结构体和函数声明,只需要添加一次,放在什么位置并不重要,就如同类里其他普通函数的声明可以相互交换顺序一样。
//函数的修饰符也是可以自己决定的,遵循一般原则。比如你需要在类外部也可以调用该消息响应函数,就可以定义成public的
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_WD_H__89BE48D2_F377_4DF1_8C44_4D7372A61CE0__INCLUDED_)
二、wd.h对应的.cpp文件wd.cpp解析
// wd.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "wd.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "wdDoc.h"
#include "wdView.h"
///////////////////////////////////////////////////////////////////////////
//以下这段宏定义只是在程序开发和调试时有用,如果软件已经交付使用,则可以去掉
///////////////////////////////////////////////////////////////////////////
#ifdef _DEBUG //如果定义了_DEBUG,表示在调试状态下编译
#define new DEBUG_NEW //当在debug模式下时,我们分配内存时的new被替换成DEBUG_NEW,而这个DEBUG_NEW不仅要传入内存块的大小,还要传入源文件名和行号,这就有个好处,即当发生内存泄漏时,我们可以在调试模式下定位到该问题代码处。若删掉该句,就不能进行定位了。而在release版本下的new就是简单的new,并不会传入文件名和行号。
#undef THIS_FILE //表示清除当前定义的宏,使得THIS_FILE无定义
static char THIS_FILE[] = __FILE__; //将THIS_FILE定义为一个静态数组,THIS_FILE是一个char数组全局变量,字符串值为当前文件的全路径,这样在Debug版本中当程序出错时出错处理代码可用这个变量告诉你是哪个文件中的代码有问题。
//__FILE__ 是编译器能识别的事先定义的ANSI C 的6个宏之一,__FILE__ 包含当前程序文件名的字符串
#endif
/////////////////////////////////////////////////////////////////////////////
// CWdApp
//消息映射的定义
BEGIN_MESSAGE_MAP(CWdApp, CWinApp)
//{{AFX_MSG_MAP(CWdApp)
ON_COMMAND(ID_APP_ABOUT, OnAppAbout) //ON_COMMAND 是一个消息映射,这里是把 ON_COMMAND 消息中的 ID_APP_ABOUT 消息映射到函数 OnAppAbout,如果程序中接到这个消息,就会调用这个函数。
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks 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()
/////////////////////////////////////////////////////////////////////////////
// CWdApp construction
CWdApp::CWdApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
/////////////////////////////////////////////////////////////////////////////
// The one and only CWdApp object
////////////////////////////////////////////////////////////////////////////
//CSDN中对theApp的用法的总结:
//1.theApp是你工程的头,你可以通过AfxGetApp()获得整个进程的指针,然后通过它,可以获得该进程的HWND以及HINSTANCE,和菜单。。。等等。不一而足。可以通过msdn获得更多的信息
//2.theApp是个全局变量,几乎可以在程序的任何地方引用。如果你建立一个MDI或者SDI工程,那么,你可以看到一个类以*App结尾,这个theApp就是它的一个实例,在这个类中添加的public变量可以通过theApp引用。当然,由于WinApp是它的基类,theApp保存有许多有关程序运行期间的很多信息,如执行程序名,路径什么的。
//3.加个成员及方法,可以随时用AfxGetApp访问
//4.theApp是CWinApp类的派生类的对象,是一个全局变量。全局变量在WinMain()前被创建。
//5.theApp就是应用程序的实例,没有他你就什么都不能做啊!他初始了进程啊!
//6.你可以理解为 theApp像一般程序中的main函数一样。
/////////////////////////////////////////////////////////////////////////////
CWdApp theApp;
/////////////////////////////////////////////////////////////////////////////
// CWdApp initialization
BOOL CWdApp::InitInstance()
{
/////////////////////////////////////////////////////////////////////////
//要想在应用程序中使用ActiveX控件,必须使你的应用程序成为ActiveX控件包容器。
//ActiveX 控件包容器就是完全支持ActiveX控件,并能把控件组合进自己的窗口或对话框的父应用程序。
//利用MFC的AppWizard,你可以很方便地创建你的包容器程序。事实上,在用AppWizard创建新的应用程序时,
//你的应用程序就被缺省设置为控件包容器,即在第3步选中支持ActiveX Controls的复选框。如果你在创建过程中没有选择这项技术支持,
//以后也可以手动地加入这项支持。如果你手动添加这个函数,和APPWIZEARD添加效果是一样的
/////////////////////////////////////////////////////////////////////////
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
//////////////////////////////////////////////////////////////////////////
//如果原文件定义了_AFXDLL,说明原文件中有某些类,函数等,是以MFC DLL的形式提供的(也就是动态连接到MFC),
//如果原文件中没定义_AFXDLL,则这些类,函数等的实现代码是被直接插入原文件(也就是静态连接到MFC)
//Enable3dControls()和
Enable3dControlsStatic()函数的作用
//如果成功地载入了CTL3D32.DLL,则为TRUE;否则为FALSE。
//如果操作系统支持控件的三维外观,则这个函数将返回FALSE。
///////////////////////////////////////////////////////////////////////////
#ifdef _AFXDLL
Enable3dControls();
// Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic();
// Call this when linking to MFC statically
#endif
// Change the registry key under which our settings are stored.
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization.
SetRegistryKey(_T("Local AppWizard-Generated Applications"));//这个函数的功能是:设置MFC程序的注册表访问键,并把读写ini文件的成员函数映射到读写注册表。
///////////////////////////////////////////////////////////////////////
//This method is called from within the InitInstance method to enable and load the list of most recently used (MRU) files and last preview state. If nMaxMRU is zero, no MRU list will be maintained.
//最近文件列表可以让你很方便地打开你以前曾经打开过的文件,那么,如何为自己的应用程序加入最近文件列表功能呢?最简单的方法就是在你新建工程的时候选择包含最近文件列表功能,也就是在 MFC AppWizard 的第 4 步的时候使 “How many files would you like on your recent file list?” 的值不为 0 即可。
LoadStdProfileSettings(); // Load standard INI file options (including MRU)
// Register the application‘s document templates. Document templates
// serve as the connection between documents, frame windows and views.
////////////////////////////////////////////////////////////////////////////
//像MVC架构一样,Model-View-Controller(MVC),其中的Model就是MFC的Document,
//而Controller相当于MFC的Document Template。
//每当使用者欲打开一份文件,程序应该做出Document、View、Frame各一份。
//这三个成为一个运行单元,由所谓的Document Template掌管。
//MFC有一个CDocTemplate负责此事,他又有两个派生类,分别是CMultiDocTemplate和CSingleDocTemplate。
//如果你的程序能够处理两中数据类型,你必须制造两个Document Template,并使用AddDocTemplate函数将他们一一加入系统之中
//谁来管理Document Template呢?是CWinApp。也就是下面InitInstance中应有的相关行为:
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_WDTYPE,
RUNTIME_CLASS(CWdDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CWdView));
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
return FALSE;
m_pMainWnd = pMainFrame;//使用此数据成员存储指向您的线程的主窗口对象
////////////////////////////////////////////////////////////////////////
//MFC应用一般都会在它的应用对象中使用函数InitInstance创建这个类的一个本地实例。
//然后把该对象传给CWinApp::ParseCommandLine,ParseCommandLine又重复调用ParseParam填充CCommandLineInfo对象。
//最后,CCommandLineInfo对象被传给CWinApp::ProcessShellCommand来处理命令行参数和选项
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The main window has been initialized, so show and update it.
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
//定义“关于”窗口的相关内容
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
////申明枚举类型用enum开头,花括弧中把IDD_ABOUTBOX的值赋给IDD;本来如果不赋值的话,
//IDD值就默认为0(注意枚举元素看做常量,故有确定值),而编者想改变IDD的值为IDD_ABOUTBOX的值,故进行了赋值。
//const int IDD = IDD_ABOUTBOX
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
//DoDataExchange(CDataExchange* pDX) 是MFC CWnd的一个重要的函数。
//在此函数中可以利用一系列的DDX_xxxx(..)函数实现UI与data的数据交互,以及用DDV_xxx(...)来实现数据验证
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
//模态对话框的消息处理
//(1) 模态对话框弹出来后,首先会让父窗口失效,使其不能接受用户的输入(键盘鼠标消息)。
//1 EnableWindow(hwndParent, FALSE) ;
//(2) 父窗口消息循环被阻塞(会卡在DoModal处,等待返回),由模态对话框的消息循环来接管(因此整个程序不会卡住)。
//接管后,模态对话框的消息循环仍然会将属于父窗口及其子控件的窗口消息(不包括键盘鼠标相关的窗口消息)发送给它们各自的WindowProc窗口函数,进行响应处理。
//(3) 模态对话框销毁时(点击IDOK或IDCANCEL),父窗口消息循环重新激活,继续DoModal后的逻辑。
// 激活后,父窗口有可以重新接受用户的输入(键盘鼠标消息)。
//1 EnableWindow(hwndParent, TRUE) ;
//从上面的过程中,我们可以得到如下结论:
//对于窗口消息,模态对话框主窗口(及其子控件)与父窗口(及其子控件)都是用自身的WindowProc函数接收并处理,互不干扰。
//只是父窗口(及其子控件)无法接受到键盘鼠标消息相关的窗口消息。
//对于命令消息,由模态对话框主窗口的WindowProc接收。可以在模态对话框主窗口的OnCmdMsg中做命令绕行,使得其他的CCmdTarget对象也可以处理命令消息。
//对于控件通知,由其父窗口的WindowProc接收并处理,一般不进行命令绕行被其他的CCmdTarget对象处理。
void CWdApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg.DoModal();
}
/////////////////////////////////////////////////////////////////////////////
// CWdApp message handlers
还有好多文件,今天先解析这两个,接下来继续补上。