朱皮特的博客 自由的飞翔

《MFC Windows程序设计》读书笔记第1章杂记

2009-02-14
朱皮特
 
阅读量:

第一章 杂记

MFC的好处就在于Microsoft已经为你写好了几万行代码,并对其进行了测试。

MFC简介

MFC提供了一组包含Windows API的基于面向对象的C++类库,有些类可以直接使用,有些类作为基类。MFC也是一个应用程序的框架结构,为应用程序处理许多杂务。

文档(CDocument)仅仅是程序数据的抽象表示。

CObject给那些继承它的类提供了3个重要特性:

  1. 串行化支持
  2. 运行时类信息支持
  3. 诊断和调试支持

AFX函数

MFC全局函数形式提供的API,以Afx开头,如: AfxGetAppAfxGetMainWnd

指定窗口风格:

  • CWnd的Create函数
  • PreCreateWindow修改参数

CPaintDC只在WM_PAINT消息处理程序中使用,是CDC的一个特殊例子。

消息映射

消息映射是一个将消息和成员函数相互关联的表。当框架窗口接收到了一个消息,MFC将搜索该窗口的消息映射,如果存在一个处理xx消息的处理程序,然后就调用它。

将消息映射添加到一个类中需要做的工作:

  1. 通过将DECLARE_MESSAGE_MAP语句添加到类声明中,声明消息映射。
  2. 通过放置标示消息的宏来执行消息映射,相应的类将在对BEGIN_MESSAGE_MAPEND_MESSAGE_MAP的调用之间处理消息。
  3. 添加成员函数来处理消息。

如:

afx_msg void OnPaint();
afx_msg LRESULT OnSetText(WPARAM wParam,LPARAM,lParam);

BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)
ON_WM_PAINT()
ON_MESSAGE(WM_SETTEXT,OnSetText)
END_MESSAGE_MAP

消息映射的工作方式

通过检查afxwin.h中的DECLARE_MESSAGE_MAP,BEGIN_MESSAGE_MAP,END_MESSAGE_MAP宏以及wincore.cpp中的CWnd::WindowProc代码,来找到消息映射是如何工作的。

DECLARE_MESSAGE_MAP宏在类声明中添加3个成员:一个名为_messageEntries的AFX_MSGMAP_ENTRY结构数组,其中包含将消息与消息处理程序关联的信息;一个名为messageMap的静态AFX_MSGMAP结构,其中包含一个指向基类的messageMap结构的指针,和一个指向_messageEntries结构的指针;一个名为GetMessageMap的虚函数,它返回messageMap的地址。

BEGIN_MESSAGE_MAP包含 GetMessageMap函数的实现,和初始化messageMap结构的代码,出现在BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间的宏都将填入到_messageEntries数组中。

END_MESSAGE_MAP使用一个NULL条目结束数组。 对于如下的语句:

//In the class delcaration
DECLARE_MESSAGE_MAP()

//In the class implementation
BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)
ON_WM_PAINT()
END_MESSAGE_MAP

编译器的预处理程序将会生成如下的语句:

//In the class delcaration
private:
   static const AFX_MSGMAP_ENTRY _messageEntries[];
protected:
static const AFX_MSGMAP messageMap;
virtual const AFX_MSGMAP *GetMessageMap() const;

//In the class implementation
const AFX_MSGMAP *CMainWindow::GetMessageMap() const
{return &CMainWindow::messageMap;}

const AFX_MSGMAP CMainWindow::messageMap = {
&CFrame::messageMap,
&CMainWindow::_messageEntries[0]
};

const AFX_MSGMAP_ENTRY CMainWindow:_messageEntries[] = {
{WM_PAINT,0,0,0,AfxSig_vv,
(AFX_PMSG)(AFX_PMSGW)(void(CWnd::*)(void))OnPaint},
{0,0,0,0,AfxSig_end,(AFX_PMSG)0}
};

要分派消息,框架调用CMainWindow从CWnd继承下来的WindowProc虚函数,WindowProc调用OnWndMsg,而OnWndMsg又调用GetMessageMap获取一个指向CmainWindow::messageMap的指针,兵搜索CMainWindow::_messageEntries数组来获取一个消息ID与当前正等待处理的消息ID相匹配的条目,若找到了则调用相关联的处理程序。否则,OnWndMsg从CMainWindow::messageMap获取指向CFrameWnd::messageMap的指针并作为基类重复上述过程。

字符集 _T宏,参见《Advanced Windows》(1997,Microsoft Press)–Jeffrey Richter关于Unicode的章节。

其他: Project菜单->General->MFC->Use MFC In A Shared Dll这样生成的应用程序大小会比较小些。


Comments

Content