按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
用于幕后协调而不显现),图中以虚框表示。
由CSplitterWnd::CreateView 产
生的view 窗口,以CBarView
由CSplitterWnd::CreateView 产生的 为基础。
view 窗口,以CTextView 为基础。
由CSplitterWnd::CreateView 产生
的view 窗口,以CGraphView 为
基础。
图13…4 静态分裂窗口的类别运用 (以Graph 为例)
同源子窗口
虽然我说静态分裂窗口的窗口可视为完全独立的view 窗口,但毕竟它们不是!它们还
框在一个大窗口中。如果你不喜欢分裂窗口(谁知道呢,当初我也不太喜欢),我们来
试点新鲜的。
点子是从【Window/New Window 】开始。这个菜单项目令Framework 为我们做出目前作
用中的view 窗口的另一份拷贝。如果我们能够知道Framework 是如何动作,是不是可
以引导它使用另一个view 类别,以不同的方式表现同一份资料?
这就又有偷窥源代码的需要了。MFC 并没有提供正常的管道让我们这么做,我们需要
MFC 源代码。
725
…………………………………………………………Page 788……………………………………………………………
第篇 深入 MFC 程式設計
CMDIFrameWnd::OnWindowNew
如果你想在程序中设计断点,一步一步找出【Window/New Window 】的动作,就像我
在第12 章对付OnFilePrint 和OnFilePrintPreview 一样,那么你会发现没有着力点,因
为AppWizard 并不会做出像这样的消息映射表格:
BEGIN_MESSAGE_MAP(CScribbleView; CScrollView)
。。。
ON_MAND(ID_FILE_PRINT; CView::OnFilePrint)
ON_MAND(ID_FILE_PRINT_PREVIEW; CView::OnFilePrintPreview)
END_MESSAGE_MAP()
你根本不知道【Window/New Window 】这个命令流到哪里去了。第7章的「标准菜单File
/ Edit / View / Window / Help 」一节,也曾说过这个命令项是属于「与Framework 预有关
联型」的。
那么我如何察其流程?1/3 用猜的,1/3 靠字符串搜寻工具GREP (第8章介绍过),1/3 靠
勤读书。然后我发现,【New Window 】命令流到CMDIFrameWnd::OnWindowNew 去了。
图13…5 是其源代码(MFC 4。0 的版本)。
#0001 void CMDIFrameWnd::OnWindowNew()
#0002 {
#0003 CMDIChildWnd* pActiveChild = MDIGetActive();
#0004 CDocument* pDocument;
#0005 if (pActiveChild == NULL ||
#0006 (pDocument = pActiveChild…》GetActiveDocument()) == NULL)
#0007 {
#0008 TRACE0(〃Warning: No active document for WindowNew mand。n〃);
#0009 AfxMessageBox(AFX_IDP_MAND_FAILURE);
#0010 return; // mand failed
#0011 }
#0012
#0013 // otherwise we have a new frame !
#0014 CDocTemplate* pTemplate = pDocument…》GetDocTemplate();
#0015 ASSERT_VALID(pTemplate);
#0016 CFrameWnd* pFrame = pTemplate…》CreateNewFrame(pDocument; pActiveChild);
#0017 if (pFrame == NULL)
#0018 {
#0019 TRACE0(〃Warning: failed to create new frame。n〃);
726
…………………………………………………………Page 789……………………………………………………………
第 13 章 多重文件與多重顯示
#0020 return; // mand failed
#0021 }
#0022
#0023 pTemplate…》InitialUpdateFrame(pFrame; pDocument);
#0024 }
图13…5 CMDIFrameWnd::OnWindowNew 源代码 ( in WINMDI。CPP)
我们的焦点放在CMDIFrameWnd::OnWindowNew 函数的第14 行,该处取得我们在
InitInstance 函数中做好的Document Template,而你知道,Document Template 中记录有
View 类别。好,如果我们能够另准备一个崭新的View 类别,有着不同的OnDraw 显
示方式,并再准备好另一份Document Template,记录该新的View 类别,然后改变图
13…5 的第14 行,让它使用这新的Document Template,大功成矣。
当然,我们绝不是要去改MFC 源代码,而是要改写虚拟函数OnWindowNew,使为我
们所用。这很简单,我只要把【Window / New Window 】命令项改变名称,例如改为【Window
/ New Hex Window 】,然后为它撰写命令处理函数,函数内容完全仿照图13…5,但把第
14 行改设定为新的Document Template 即可。
Text 范例程序
Text 程序提供【Window / New Text Window 】和【Window / New Hex Window 】两个新的
菜单命令项目,都可以产生出view 窗口,一个以ASCII 型式显示资料,一个以Hex 型
式显示资料,资料来自同一份Document 。
以下Text 程序的是制作过程:
■进入AppWizard ,制造一个Text 项目,采用各种预设的选项。获得的主要类
别如下:
727
…………………………………………………………Page 790……………………………………………………………
第篇 深入 MFC 程式設計
类别 基础类别 文件
CTextApp CWinApp TEXT。CPP TEXT。H
CMainFrame CMDIFrameWnd MAINFRM。CPP MAINFRM。H
CChildFrame CMDIChildWnd CHILDFRM。CPP CHILDFRM。H
CTextDoc CDocument TEXTDOC。CPP TEXTDOC。H
CTextView CView TEXTVIEW。CPP TEXTVIEW。H
进入整合环境中的Resource View 窗口,选择IDR_TEXTTYPE 菜单,在
【Window 】菜单中加入两个新命令项:
命令项目名称 识别码(ID ) 提示字符串
New Text Window ID_ WINDO W_ TEXT New a Text Window with Active Document
New Hex Window ID_ WINDO W_HEX New a Hex Window with Active Document
再在Resource View 窗口中选择IDR_MAINFRAME 工具栏,增加两个按钮,安
排在Help 按钮之后:
这两个按钮分别对应于新添加的两个菜单命令项目。
进入ClassWizard,为两个UI 对象制作 Message Map 。这两个命令消息并不
会影响Document 内容(不像上一节的GRAPH 例那样),我们在CMainFrame
中处理这两个命令消息颇为恰当。
UI 对象 消息 消息处理函数
ID_WINDOW_TEXT MAND OnWindowText
ID_WINDOW_HEX MAND OnWindowHex
728
…………………………………………………………Page 791……………………………………………………………
第 13 章 多重文件與多重顯示
利用ClassWizard 产生一个新类别,准备做为同源子窗口的第二个View 类别:
类别名称 基础类别 文件
CHexView CView HEXVIEW。CPP HEXVIEW。H
修改程序代码,分别为两个view 类别都做出对应的Docment Template:
// in TEXT。H
class CTextApp : public CWinApp
{
public:
CMultiDocTemplate* m_pTemplateTxt;
CMultiDocTemplate* m_pTemplateHex;
。。。
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
。。。
};
// in TEXT。CPP
。。。
#include 〃TextView。h〃
#include 〃HexView。h〃
。。。
BOOL CTextApp::InitInst