按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
它们。
493
…………………………………………………………Page 556……………………………………………………………
第篇 深入 MFC 程式設計
我们来看看CView 之中居最重要地位的OnDraw,面对Scribble Document 的数据结构,
将如何进行绘图动作。为了获得资料,OnDraw 一开始先以GetDocument 取得Document
对象指针;然后以while 循环一一取得各线条,再调用CStroke::DrawStroke 绘图。想象
中绘图函数应该放在View 类别之内(绘图不正是View 的责任吗),但是DrawStroke 却
否!原因是把线条的资料和绘图动作一并放在CStroke 中是最好的包装方式。
void CScribbleView::OnDraw(CDC* pDC)
{
CScribbleDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// The view delegates the drawing of individual strokes to
// CStroke::DrawStroke()。
CTypedPtrList& strokeList = pDoc…》m_strokeList;
POSITION pos = strokeList。GetHeadPosition ();
while (pos != NULL)
{
CStroke* pStroke = strokeList。GetNext (pos);
pStroke…》DrawStroke(pDC);
}
}
其中用到两个CObList 成员函数:
GetNext:取得下一个元素。
GetHeadPosition:传回串行之第一个元素的「位置」。传回来的「位置」是一
个类型为POSITION 的数值,这个数值可以被使用于CObList 的其它成员函数
中,例如GetAt 或SetAt 。你可以把「位置」想象是串行中用以标示某个节点
node )的指针。当然,它并不真正是指针。
(
494
…………………………………………………………Page 557……………………………………………………………
第8章 Document…View 深入探討
View 与使用者的交谈 (鼠标消息处理实例)
为了实现「以鼠代笔」的功能,CScribbleView 必须接受并处理三个消息:
BEGIN_MESSAGE_MAP(CScribbleView; CView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
。。。
END_MESSAGE_MAP()
三个消息处理例程的的内容总括来说就是追踪鼠标轨迹、在窗口上绘图、以及调用CStroke
成员函数以修正线条内容……包括产生一个新的线条空间以及不断把坐标点加上去。三
个函数的重要动作摘记于下。这些函数的骨干及其在Messape Map 中的映射项目,不劳
我们动手,有ClassWizard 代劳。下一个小节我会介绍其操作方法。
void CScribbleView::OnLButtonDown(UINT nFlags; CPoint point)
{
// 当鼠标左键按下,
// 利用CScribbleDoc::NewStroke 产生一个新的线条空间;
// 利用CArray::Add 把这个点加到线条上去;
// 调用SetCapture 取得鼠标捕捉权(mouse capture);
// 把这个点记录为「上一点」(m_ptPrev);
}
void CScribbleView::OnMouseMove(UINT; CPoint point)
{
// 当鼠标左键按住并开始移动,
// 利用CArray::Add 把新坐标点加到线条上;
// 在上一点(m_ptPrev)和这一点之间画直线;
// 把这个点记录为「上一点」(m_ptPrev);
}
void CScribbleView::OnLButtonUp(UINT; CPoint point)
{
// 当鼠标左键放开,
// 在上一点(m_ptPrev)和这一点之间画直线;
// 利用CArray::Add 把新的点加到线条上;
495
// 调用ReleaseCapture() 释放鼠标捕捉权(mouse capture)。
}
…………………………………………………………Page 558……………………………………………………………
第篇 深入 MFC 程式設計
ClassWizard 的辅佐
前述三个CScribbleView 成员函数(OnLButtonDown,OnLButtonUp,OnMouseMove)是
Message Map 的一部份,ClassWizard 可以很方便地帮助我们完成相关的Message Map 设
定工作。
首先,选按【View/ClassWizard 】激活ClassWizard,选择其【Message Map 】附页:
在图右上侧的【Class Name 】清单中选择CScribbleView,然后在图左侧的【Object IDs 】
清单中选择CScribbleView,再在图右侧的【Messages 】清单中选择WM_LBUTTONDOWN ,
然后选按图右的【Add Function 】钮,于是图下侧的【Member functions 】清单中出现一
笔新项目。
然后,选按【Edit Code 】钮,文字编辑器会跳出来,你获得了一个OnLButtonDown 函数
空壳,请在这里键入你的程序代码:
496
…………………………………………………………Page 559……………………………………………………………
第8章 Document…View 深入探討
另两个消息处理例程的实作作法雷同。
Message Map 因此有什么变化呢?ClassWizard 为我们自动加上了三笔映射项目:
BEGIN_MESSAGE_MAP(CScribbleView; CView)
//{{AFX_MSG_MAP(CScribbleView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}AFX_MSG_MAP
// Standard printing mands
ON_MAND(ID_FILE_PRINT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_DIRECT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_PREVIEW; CView::OnFilePrintPreview)
END_MESSAGE_MAP()
此外ScribbleView 的类别声明中也自动有了三个成员函数的声明:
class CScribbleView : public CView
{
。。。
// Generated message map functions
protected:
//{{AFX_MSG(CScribbleView)
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
。。。
};
497
…………………………………………………………Page 560……………………………………………………………
第篇 深入 MFC 程式設計
WizardBar 的辅佐
WizardBar 是Visual C++ 4。0 之后的新增工具,也就是文字编辑器上方那个有着【Object
IDs 】和【Messages 】清单的横杆。关于修改Message Map 这件事,WizardBar 可以取代
ClassWizard 这个大家伙。
首先,进入ScribbleViwe。cpp (因为我们确定要在这里加入三个鼠标消息处理例程),选
择WizardBar 上的【Object IDs 】为CScribbleView , 再选择【Messages 】为
_
WM LBUTTONDOWN ,出现以下画面:
回答Yes ,于是你获得一个OnLButtonDown 函数空壳,一如在ClassWizard 中所得。请
在函数空壳中输入你的程序代码。
Serialize :对象的文件读写
你可能对Serialization 这个名词感觉陌生,事实上它就是对象导向世界里的Persistence (永
续生存),只是后者比较抽象一些。对象必须能够永续生存,也就是它们必须能够在程
式结束时储存到文件中,并且在程序重新激活时再恢复回来。储存和恢复对象的过程在
MFC 之中就称为serialization。负责这件重要任务的,是MFC CObject 类别中一个名为
Serialize 的虚拟函数,文件的「读」「写」动作均透过它。
498
…………………………………………………………Page 561……………………………………………………………
第8章 Document…View 深入探討
如果文件内容是借着层层类别向下管理(一如本例),那么只要每一层把自己份内的工
作做好,层层交待下来就可以完成整份资料的文件动作。
Serialization 以外的文件读写动作
其实有时候我们希望在重重包装之中返璞归真一下,感受一些质朴的动作。在介绍
Serialization 的重重包装之前,这里给你一览文件实际读写动作的机会。
文件I/O 服务是任何操作系统的主要服务。Win32 提供了许多文件相关APIs :开档、
关文件、读文件、写文件、搜寻资料。。。。MFC 把这些操作都包装在CFile 之中。可想而知,它