1、文档/视类结构
MFC提供了一一个文档/视 (DocumentView)结构,其中文档就是指CDocument类,视就是指CView类。Microsoft 在设计基础类库时,考虑到要把数据本身与它的显示分离开,于是就采用文档类和视类结构来实现这一想法。 数据的存储和加载由文档类来完成,数据的显示和修改则由视类来完成,从而把数据管理和显示方法分离开来。文档/视结构是MFC程序的一个重点。
MFC除了主框架窗口外,还有一个窗口是视类窗口,对应的类是CView类,CView类也派生于CWnd类, 框架窗口是视类窗口的的父窗口。关系如下:
2、窗口类、窗口类对象与窗口
C++窗口类对象与窗口并不是一回事,它们之间一-的关系是C++窗口类对象内部定义了一个窗口句柄变量,保存了与这个C++窗口类对象相关的那个窗口的句柄。窗口销毁时,与之对应的C++窗口类对象销毁与否,要看其生命周期是否结束。但C++窗口类对象销毁时,与之相关的窗口也将销毁。
3、全局函数
以::开始的表示方法表明该函数是一个全局函数。
在定义自己的成员函数时,如果调用的API函数名与自己的函数名不同,那么该API函数名前可以加也可以不加::符号,编译器会自动识别API函数。但是如果当前定义的成员函数与内部调用的API函數名相同,那么后者前面必须加::符号,否则程序在编译或运行时就会出错。
5、m_hWnd
CWnd类定义了-一个HWND类型的成员变量m_hWnd,用于保存当前窗口的句柄,并且该成员变量具有public类型的访问权限。这样,窗口的所有操作就不再需要传递这个句柄了,因为它已经是成员变量,可以直接使用。根据类继承性原理,所有派生于CWnd类的子类都拥有这一成员变量, 用来保存当前子类窗口的句柄,因此在调用与子类窗口有关的操作时,也不再需要传递这个窗口句柄了。
6、消息映射机制
(1)消息响应函数原型
{{AFX_MSG(CDrawView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
}}AFX_MSG
afx_msg这是一个限定符,是一个宏,如果用该宏修饰一个函数则表明该函数是一个消息响应函数。
(2) ON_WM_LBUTTONDOWN消息映射宏
BEGIN_MESSAGE_MAP(CDrawView, CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
BEGIN MESSAGE MAP和END MESSAGE MAP()这两个宏之间定义了CDrawView类的消息映射表,其中有一个ON_ WM_ LBUTTONDOWN这消息映射宏,这个宏的作用就是把鼠标左键按下消息(WM LBUTTONDOWN)与一个消息响应函数关联起来(本例中就把WM LBUTTONDOWN消息与OnLButtonDown函数关联起来)。通过这种机制,一旦有消息产生,程序就会调用相应的消息响应函数来进行处理。
(3)消息响应函数的定义
其中一个响应函数的实现:
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
m_ptOrigin = point;
m_ptOld = point;
m_bDraw = TRUE;
CView::OnLButtonDown(nFlags, point);
}
一个MFC消息响应函数在程序中有三处相关信息:函数原型、函数实现,以及用来关联消息和消息响应函数的宏。头文件中在两个AFX MSG注释宏之间是消息响应函数原型的声明。源文件中有两处:一处是在两个 AFX_ MSG_ MAP注释宏之间的消息映射宏,通过这个宏把消息与消息响应函数关联起来;另--处是源文件中的消息响应函数的实现代码。
(4)消息映射机制:
消息循环中,当有消息产生时,操作系统会把这条消息放到应用程序的消息队列中,应用程序通过GetMessage函数从这个队列中取出一-条具体的消息,并通过DispatchMessage函数把消息交给操作系统,后者调用应用程序的窗口过程,即窗口过程函数WndProc进行处理。该函数利用switch-case结构来对消息进行判别并分类处理。然而,我们看到在MFC程序中,并不是按照这种途径进行处理的,只要遵照上述步骤,定义了与消息有关的三处信息后,就可以实现消息的响应处理。MFC中采用的这种消息处理机制称为MFC消息映射机制。
MFC消息映射机制的具体实现方法是:在每个能接收和处理消息的类中,定义~个消息和消息函数静态对照表,即消息映射表。在消息映射表中,消息与对应的消息处理函数指针是成对出现的。某个类能处理的所有消息及其对应的消息处理函的地址都列在这个类所对应的静态表中。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就可知道该类能否处理此消息。如果能处理该消息,则同样依照静态表能很容易找到并调用对应的消息处理函数。