深入浅出MFC第2版(PDF格式)-第91部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
Tile ID_WINDOW_TILE_HORZ MDIFrameWnd::OnWindowCmd Yes
Arrange Icons ID_WINDOW_ARRANGE MDIFrameWnd::OnWindowCmd Yes
Help
About AppName ID_APP_ABOUT None
上表的最后一字段为No 者有五笔,表示虽然那些命令项有预设的处理例程,但你必须
在自己的Message Map 中设定映射项目,它们才会起作用。噢,AppWizard 此时又表现
出了它的善体人意,自动为我们做出了这些码:
BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp)
。。。
ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew)
ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen)
ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
BEGIN_MESSAGE_MAP(CScribbleView; CView)
。。。
ON_MAND(ID_FILE_PRINT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_PREVIEW; CView::OnFilePrintPreview)
END_MESSAGE_MAP()
448
…………………………………………………………Page 511……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
对话框
Scribble 可以激活许多对话框,前一节提了许多。唯一要程序员自己动手(我的意思是
出现在我们的程序代码中)的只有About 对话框。
为了拦截WM_MAND 的ID_APP_ABOUT 项目,首先我们必须设定其Message
Map :
BEGIN_MESSAGE_MAP(CScribbleApp; CWinApp)
ON_MAND(ID_APP_ABOUT; OnAppAbout)
ON_MAND(ID_FILE_NEW; CWinApp::OnFileNew)
ON_MAND(ID_FILE_OPEN; CWinApp::OnFileOpen)
ON_MAND(ID_FILE_PRINT_SETUP; CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()
当消息送来,就由OnAppAbout 处理:
void CScribbleApp::OnAppAbout()
{
CAboutDlg aboutDlg;
aboutDlg。DoModal();
}
其中CAboutDlg 是CDialog 的衍生类别:
class CAboutDlg : public CDialog
{
enum { IDD = IDD_ABOUTBOX }; // IDD_ABOUTBOX 是RC 文件中的对话框模板资源
。。。
DECLARE_MESSAGE_MAP()
};
比之于SDK 程序中的对话框,这真是方便太多了。传统SDK 程序要在RC 文件中定义
对话框模板(dialog template,也就是其外形),在C 程序中设计对话框函数。现在只
需从CDialog 衍生出一个类别,然后产生该类别之对象,并指定RC 文件中的对话框面
板资源,再调用对话框对象的DoModal 成员函数即可。
第10 章一整章将讨论所谓的对话框数据交换(DDX )与对话框数据确认(DDV)。
449
…………………………………………………………Page 512……………………………………………………………
第篇 湷觥 FC 程式設計
改用CEditView
Scribble step0 除了把一个应用程序的空壳做好,不能再贡献些什么。如果我们在
AppWizard 步骤六中把CScribbleView 的基础类别从CView 改为CEditView,那可就
有大妙用了:
CEditView 是一个已具备文字编辑能力的类别,它所使用的窗口是Windows 的标准控
制组件之一Edit ,其SerializeRaw 成员函数可以把Edit 控制组件中的raw text (而非
「对象」所持有的资料)写到文件中。当我们在AppWizard 步骤六选择了它,程序代码中
所有的CView 统统变成CEditView,而最重要的两个虚拟函数则变成:
void CScribbleDoc::Serialize(CArchive& ar)
{
// CEditView contains an edit control which handles all serialization
((CEditView*)m_viewList。GetHead())…》SerializeRaw(ar);
}
void CScribbleView::OnDraw(CDC* pDC)
{
450
…………………………………………………………Page 513……………………………………………………………
第7章 簡單而完整:MFC 骨幹程式
CScribbleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
就这样,我们不费吹灰之力获得了一个多窗口的文字编辑器:
并拥有读写档能力以及预视能力:
451
…………………………………………………………Page 514……………………………………………………………
第篇 湷觥 FC 程式設計
452
…………………………………………………………Page 515……………………………………………………………
4
深入MFC 程 序 设 计
深入湷觥FC
2nd Edition
453
…………………………………………………………Page 516……………………………………………………………
MFC
第篇 深入 程式設計
454
…………………………………………………………Page 517……………………………………………………………
第8章
Document…View 深入探讨
形而上者谓之道,形而下者谓之器。
对于 View 而言,很少有人能够先道而后器。
Document/
完全由AppWziard 代劳做出的Scribble step0,应用程序的整个架构(空壳)都已经建
构起来了,但是Document Document 和VView iew 还空着好几个最重要的函数(都是虚拟函数)等着
你设计其实体。这就像一部汽车外面的车体以及内部的油路电路都装配好了,但还等着
最重要的发动机(引擎)植入,才能够产生动力,开始「有所为」。
我已经在第7章概略介绍了Document/View 以及Document Template ,还有更多的秘密将
在本章揭露。
为什么需要Document…View (形而上)
MFC 之所以为Application Framework ,最重要的一个特征就是它能够将管理资料的程序
码和负责资料显示的程序代码分离开来,这种能力由MFC 的Document/View 提供。
Document/View 是MFC 的基石,了解它,对于有效运用MFC 有极关键的影响。甚至
OLE 复合文件(pound document )都是建筑在Document/View 的基础上呢!
几乎每一个软件都致力于资料的处理,毕竟信息以及资料的管理是计算机技术的主要用途。
把数据管理和显示方法分离开来,需要考虑下列几个议题:
455
…………………………………………………………Page 518……………………………………………………………
第篇 深入 MFC 程式設計
1。 程序的哪一部份拥有资料
2。 程序的哪一部份负责更新资料
3。 如何以多种方式显示资料
4。 如何让资料的更改有一致性
5。 如何储存资料(放到永久储存装置上)
6。 如何管理使用者接口。不同的数据类型可能需要不同的使用者接口,而一个程
序可能管理多种类型的资料。
其实Document / View 不是什么新主意,Xerox PARC 实验室是这种观念的滥觞。它是
Smalltalk 环境中的关键性部份,在那里它被称为Model…View…Controller (MVC )。其
中的Model 就是MFC 的Document ,而Controller 相当于MFC 的Document Template。
回想在没有Application Framework 帮助的时代(并不太久以前),你如何管理资料?只
要程序需要,你就必须想出各种表现资料的方法;你有责任把资料的各种表现方法和资
料本体调解出一种关系出来。100 位程序员,有100 种作法!如果你的程序只处理一种
数据类型,情况还不至于太糟。举个例,字处理软件可以使用巨大的字符串数组,把文
字统统含括进来,并以ASCII 型式显示之,顶多嘛,变换一下字形!
但如果你必须维护一种以上的数据类型,情况又当如何?想象得到,每一种数据类型可
能需要独特的处理方式,于是需要一套功能菜单;每一种数据类型显现在窗口中,应该
有独特的窗口标题以及缩小图标;当资料编辑完毕要存盘,应该有独特的扩展名;登录
在Registry 之中应该有独特的型号。再者,如果你以不同的窗口,不同的显现方式,秀
出一份资料,当资料在某一窗口中被编辑,你应该让每一窗口的资料显像与实际资料之
间常保一致。吧啦吧啦吧啦! K ,繁杂事务不胜枚举。
」
很快地,问题就浮显出来了。程序不仅要做数据管理,更要做「与数据类型相对应的UI
的管理。幸运的是,解决之道亦已浮现,那就是对象导向观念中的Model…View…Controller
(MVC ),也就是MFC 的Document / View 。
456
…………………………………………………………Page 519……………………………………………………………
第8章 Document…View 深入探討
Document
名称有点令人惧怕…Document 令我们想起文字处理软件或电子表格软件中所谓的「文件」。
但,这里的Document 其实就是资料。的确是,不必想得过份复杂。有人用data set 或data
source 来表示它的意义,都不错。
Document 在MFC 的CDocument 里头被具体化。CDocument 本身并无实务贡献,它
只是提供一个空壳。当你开发自己的程序,应该从CDocument 衍生出一个属于自己的
Document 类别,并且在类别中声明一些成员变量,用以承载(容纳)数据。然后再(至
少)改写专门负责文件读写动作的Serialize 函数。事实上,AppWizard 为我们把空壳都
准备好了,以下是Scribble step0 的部份内容:
class CScribbleDoc : public CDocument
{
DECLARE_DYNCREATE(CScribbleDoc)
。。。
virtual void Serialize(CArchive& ar);
DECLARE_MESSAGE_MAP()
};
void CScribbleDoc::Serialize(CArchive& ar)
{
if (ar。IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}