按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
0007 后面接着的「类别名称」有7 个字符。
43 43 69 72 63 6C 65 〃CCircle〃 (类别名称)的ASCII 码。
00000055 第一个圆形的中心点X 坐标
00000066 第一个圆形的中心点Y 坐标
00000077 第一个圆形的半径
8001 这是(wOldClassTag | nClassIndex) 的组合结果,表示接
下来的对象使用索引为 的旧类别。
1
0002 第二条线条的宽度
0002 第二条线条的点数组大小(点数)
542
…………………………………………………………Page 605……………………………………………………………
第8章 Document…View 深入探討
数值(hex) 说明
00000066;00000031 第二条线条的第一个点坐标
00000066;00000031 第二条线条的第二个点坐标
8003 这是(wOldClassTag | nClassIndex) 的组合结果,表示接
下来的对象使用索引为3 的旧类别。
00000011 第二个四方形的左
00000022 第二个四方形的上
00000033 第二个四方形的右
00000044 第二个四方形的下
8005 这是(wOldClassTag | nClassIndex) 的组合结果,表示接
下来的对象使用索引为 的旧类别。
5
00000055 第二个圆形的中心点X 坐标
00000066 第二个圆形的中心点Y 坐标
00000077 第二个圆形的半径
图8…10b TEST。SCB 文件内容剖析。别忘了Intel 采用〃little…endian〃 位
组排列方式,每一字组的前后字节系颠倒放置。本图已将之摆正。
Document 与View 交流为Step4 做准备
虽然Scribble Step1 已经可以正常工作,有些地方仍值得改进。
在一个子窗口上作画,然后选按【Window/New Window 】,会蹦出一个新的子窗口,内
有第一个子窗口的图形,同时,第一个子窗口的标题加上:1 字样,第二个子窗口的标
题则有:2 字样。这是Document/View 架构带给我们的礼物,换句话说,想以多个窗口
观察同一份资料,程序员不必负担什么任务。但是,如果此后使用者在其中一个子窗口
上作画而不缩放窗口尺寸的话(也就是没有产生WM_PAINT),另一个子窗口内看不到
新的绘图内容:
543
…………………………………………………………Page 606……………………………………………………………
第篇 深入 MFC 程式設計
这不是好现象!一体的两面怎么可以不一致呢?!
那么,让「作用中的View 窗口」以消息通知隶属同一份Document 的其它「兄弟窗口」,
是不是就可以解决这个问题?是的,而且Framework 已经把这样的机制埋伏下去了。
CView 之中的三个虚拟函数:
CView::OnInitialUpdate 负责View 的初始化。
CView::OnUpdate 当Framework 调用此函数,表示Document 的内容已有变化。
CView::OnDraw Framework 将在WM_PAINT 发生后,调用此函数。此函数应
负责更新View 窗口的内容。
这些函数往往成为程序员改写的目标。Scribble 第一版就是因为只改写了其中的OnDraw
函数,所以才有「多个View 窗口不能同步更新」的缺失。想要改善这项缺失,我们必
须改写OnUpdate。
让所有的View 窗口「同步」更新资料的关键在于两个函数:
CDocument::UpdateAllViews 如果这个函数执行起来,它会巡访所有隶属同一
Document 的各个Views ,找到一个就通知一个,而所谓「通知」就是调用View
的OnUpdate 函数。
544
…………………………………………………………Page 607……………………………………………………………
第8章 Document…View 深入探討
CView::OnUpdate 这是一个虚拟函数,我们可以改写它,在其中设计绘图动作,
也许全部重绘(这比较笨一点),也许想办法只绘必要的一小部份(这样速度
比较快,但设计上比较复杂些)。
因此,当一个Document 的资料改变时,我们应该设法调用其UpdateAllViews,通知所
有的Views 。什么时候Scribble 的资料会改变?答案是鼠标左键按下时! 所以你可能猜
测到,我打算在CView::OnLButtonDown 内调用CDocument::UpdateAllViews。这个猜测
的立论点是对的而结果是错的,Scribble Step4 的作法是在CView::OnButtonUp 内部调用
它。
CView::OnUpdate 被调用,代表着View 被告知:「嘿,Document 的内容已经改变了,
请你准备修改你的显示画面」。如果你想节省力气,利用Invalidate(TRUE) 把窗口整个
设为重绘区(无效区)并产生WM_PAINT,再让CView::OnDraw 去伤脑筋算了。但是
全部重绘的效率低落,程序看起来很笨拙,Step4 将有比较精致的作法。
Document
。
View:1 View:2 View:3
o1 使用者在View:1 做动作(View 扮演使用者接口的第一线)。
o2 View:1 调用GetDocument ,取得Document 指针,更改资料内容。
o3 View:1 调用Document 的UpdateAllViews
o4 View:2 和View:3 的OnUpdate 一一被调用起来,这是更新画面的时机。
图8…11 假设一份Document 联结了三个Views
注意:在MFC 手册或其它书籍中,你可能会看到像「View1 以消息通知Document 」
或「Document 以消息通知View2、View3 」的说法。这里所谓的「消息」是对象导向学
术界的术语,不要和Windows 的消息混淆了。事实上整个过程中并没有任何一个Windows
消息参与其中。
545
…