深入浅出MFC第2版(PDF格式)-第131部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
…………………………………………………………Page 712……………………………………………………………
第篇 深入 MFC 程式設計
数值(hex) 说明(共173 bytes )
8001 表示接下来的对象仍旧使用旧的类别
00000015 00000054 外围四方形的左上角坐标(膨胀一个笔宽)
0000003D 0000007C 外围四方形的右下角坐标(膨胀一个笔宽)
0014 第四条线条的宽度
0002 第四条线条的点数
00000029 00000068 第四条线条的第一个点坐标
00000029 00000068 第四条线条的第二个点坐标
图11…6b 文件档 ( 图11…6a ) 的分析
大窗口中的小窗口:Splitter
MDI 程序的标准功能是允许你为同一份Document 开启一个以上的Views 。这种情况类
似我们以多个观景窗观看同一份资料。我们可以开启任意多个Views ,各有滚动条,那么
我们就可以在屏幕上同时观察一份资料的不同区域。这许多个View 窗口各自独立运
作,因此它们的观看区可能互相重叠。
如果这些隶属同一Document 的Views 能够结合在一个大窗口之内,又各自有独立的行
为(譬如说有自己的滚动条),似乎可以带给使用者更好的感觉和更方便的使用,不是吗?
分裂窗口的功能
把View 做成所谓的「分裂窗口(splitter )」是一种不错的想法。这种窗口可以分裂出
数个窗口,如图11…7,每一个窗口可以映射到Document 的任何位置,窗口与窗口之间
彼此独立运作。
650
…………………………………………………………Page 713……………………………………………………………
第 11 章 View 功能之加強與重繪效率之提昇
splitter box
在Splitter Box 上以鼠标左键快按两下,就可以将窗口分裂开来。Splitter Box 有
水平和垂直两种。分裂窗口的窗口个数,由程序而定,本例是2x2。不同的窗口可
以观察同一份Document 的不同区域。本例虽然很巧妙地安排出一张完整的图出
来,其实四个窗口各自看到原图的某一部份。
图11…7 分裂窗口 (splitter window)
在Splitter Box 上以鼠标左键快按两下,就可以将窗口分裂开来。Splitter Box 有水平和
垂直两种。分裂窗口的窗口个数,由程序而定,本例是2x2 。不同的窗口可以观察同一
份Document 的不同区域。本例虽然很巧妙地安排出一张完整的图出来,其实四个窗口
各自看到原图的某一部份。
分裂窗口的程序概念
回忆第8章所说的Document/View 架构,每次打开一个Document ,需有两个窗口通力
合作才能完成显示任务,一是CMDIChildWnd 窗口,负责窗口的外框架与一般行为,一
是CView 窗口,负责资料的显示。但是当分裂窗口引入,这种结构被打破。现在必须有
三个窗口通力合作完成显示任务(图11…8):
1。 Document Frame 窗口:负责一般性窗口行为。其类别衍生自CMDIChildWnd。
2。 Splitter 窗口:负责管理各窗口。通常直接使用CSplitterWnd 类别。
3。 View 窗口:负责资料的显示。其类别衍生自CView。
651
…………………………………………………………Page 714……………………………………………………………
第篇 深入 MFC 程式設計
splitter 窗口,
采用CSplitterWnd.
View 窗口,
通常采用CView.
Document Frame 窗口,
采用CMDIChildWnd.
图11…8 欲使用分裂窗口, 必须三个对象合作才能完成显示任务, 一是
Document Frame 窗口, 负责一般性窗口行为; 二是
CSplitterWnd 窗口,管理窗口内部空间 ( 各个窗口);三是CView
窗口, 负责显示资料。
给SDK 程序员
你有以SDK 撰写MDI 程序的经验吗?MDI 程序有三层窗口架构:
MDI Frame 在SDK 程序中,MDI Frame 窗口的消息预设处理
函数是DefFrameProc ,而不是DefWindowProc 。
MDI Frame窗口发出MDI 消息(如WM_MDICASCADE 、
_
WM MDITILE ),命令MDI Client 窗口管理其子窗口
(管理动作包括窗口产生、位置排列等等) 。
MDI Client MDI Client 是Windows 预设好的窗口类别,名为
〃MDIClient〃 。你也可以把它视为一种控制组件。
在SDK 程序中,MDI Child 窗口的消息预设处理函数
是DefMDIChildProc() ,而不是DefWindowProc() 。
MDI Child1 MDI Child2 MDI Child3
652
…………………………………………………………Page 715……………………………………………………………
第 11 章 View 功能之加強與重繪效率之提昇
程序员想要控制MDI Child 窗口的大小、位置、排列状态,必须藉助另一个已经由
Windows 系统定义好的窗口, 此窗口称为MDI Client 窗口, 其类别名称为
〃MDICLIENT〃。
Frame 窗口、Client 窗口和Child 窗口构成MDI 的三层架构。Frame 窗口产生之后,
通常在WM_CREATE 时机就以CreateWindow(〃MDICLIENT 〃;。。。); 的方式建立Client 视
窗,此后几乎所有对Child 窗口的管理工作,诸如产生新的Child 窗口、重新排列窗口、
重新排列图标、在菜单上列出已开启窗口。。。等等,都由Client 代劳,只要Frame 窗口向
Client 窗口下命令(送MDI 消息如WM_MDICREATE 或WM_MDITILE 就去)即可。
你可以把CSplitterWnd 对象视为MDI Client ,观念上比较容易打通。
分裂窗口之实作
让我先把Scribble 目前使用的类别之中凡与本节主题有关的,做个整理。
Visual C++ 4。0 以前的版本,AppWizard 为Scribble 产生的类别是这样子的:
用途 类别名称 基础类别(MFC 类别)
main frame CMainFrame CMDIFrameWnd
document frame 直接使用MFC 类别CMDIChildWnd CMDIChildWnd
view CScribbleView CView
document CScribbleDoc CDocument
而其CMultiDocTemplate 对象是这样子的:
pDocTemplate = new CMultiDocTemplate(
IDR_SCRIBTYPE;
RUNTIME_CLASS(CScribbleDoc);
RUNTIME_CLASS(CMDIChildWnd);
RUNTIME_CLASS(CScribbleView));
为了加上分裂窗口,我们必须利用ClassWizard 新增一个类别(在Scribble 程序中名为
653
…………………………………………………………Page 716……………………………………………………………
第篇 深入 MFC 程式設計
CScribbleFrame),衍生自CMDIChildWnd,并让它拥有一个CSplitterWnd 对象,名为
m_wndSplitter 。然后为CSrcibbleFrame 改写OnCreateClient 虚拟函数,在其中调用
m_wndSplitter。Create 以产生分裂窗口、设定窗口个数、设定窗口的最初尺寸等初始状态。
最后,当然,我们不能够再直接以CMDIChildWnd 负责document frame 窗口,而必须以
CScribbleFrame 取代之。也就是说,得改变CMultiDocTemplate 构造式的第三个参数:
pDocTemplate = new CMultiDocTemplate(
IDR_SCRIBTYPE;
RUNTIME_CLASS(CScribbleDoc);
RUNTIME_CLASS(CScribbleFrame);
RUNTIME_CLASS(CScribbleView));
俱往矣!Visual C++ 4。0 之后的AppWizard 为Scribble 产生的类别是这个样子:
用途 类别名称 基础类别
main frame CMainFrame CMDIFrame Wnd
document frame CChildFrame CMDIChild Wnd
view CScribble View CView
document CScribbleDoc CDocument
而其CMultiDocTemplate 对象是这样子的:
pDocTemplate = new CMultiDocTemplate(
IDR_SCRIBTYPE;
RUNTIME_CLASS(CScribbleDoc);
RUNTIME_CLASS(CChildFrame);
RUNTIME_CLASS(CScribbleView));
这就方便多了, CChildFrame 相当于以前( MFC 4。0 之前) 你得自力完成的
CScribbleFrame。现在,我们可以从「为此类别新添成员变量」开始作为。
654
…………………………………………………………Page 717……………………………………………………………
第 11 章 View 功能之加強與重繪效率之提昇
以下是加上分裂窗口的步骤:
在ClassView (注意,不是ClassWizard )中选择CChildFrame。按下右键,选
择突冒式菜单中的【Add Variable 】
出现【Add Member Variable 】对话框。填充如下,然后选按【OK 】。
现在你可以从ClassView 画面中实时看到CChildFrame 的新变量。
打开ChildFrm。cpp,在WizardBar 的【Messages 】清单中选择OnCreateClient。
以Yes 回答WizardBar 的询问,产生处理例程。
在函数空壳中键入以下内容:
return m_wndSplitter。Create(this; 2; 2; CSize(10; 10); pContext);
655
…………………………………………………………Page 718…………………………