《C语言实例教程(PDF格式)》第106章


RUNTIME_CLASS(CMdiView));
AddDocTemplate(pDocTemplate);
// 。。。
return TRUE;

每次打开一个新文档时都调用CDocument的函数OnNewDocument。该函 
数被定义如下:
class CMdiDoc : public CDocument

// 。。。
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMdiDoc)
public:
virtual BOOL OnNewDocument();
virtual void Serialize(CArchive& ar);
//}}AFX_VIRTUAL
// 。。。

当调用此函数时可以得到一个新的MDI子窗口,它由CDMIChildWnd派 
生出来。这些子窗口保存着各种已打开的文档,所有的细节都是由 
…………………………………………………………Page 499……………………………………………………………
MFC库处理。而每个MDI子窗口都支持由类CView派生出的普通类型的 
视窗。 这意味着可以同以前一样不受约束地使用WM_CHAR和 
WM_MOUSEMOVE这类消息。
l 注意:
l 如果读者对这一部分的理解不太清楚,建议再看看6。5视类一节 
中有关视类层次结构的介绍。
在8。4生成视一节中的最后,我们曾经提到过,可以用调用函数 
UpdateAllViews来维护所需要的众多视窗的同时协调工作。当任意一 
个视窗修改了文档之后就可调用该函数,这样可确保除了第一个调用 
该函数进行修改的视窗外所有视窗均调用函数OnUpdate。在前面的那 
个例子中,我们就如上所述的调用了该类。
函数UpdateAllViews 的原型为:
void UpdateAllViews( CView* pSender; LPARAM lHint = 0L; CObject* pHint = NULL );
其中LONG型参数lHint通常所包含的信息与视窗对文档所做的修改有 
关;pHint总是指向一个对象,该对象有助于处理更新。为简单起 
见,只需将这些值赋为NULL。
但另一方面,我们还需要将函数OnUpdate加到视窗类中,以处理由其 
它视窗引发的更新,因此需要处理函数CView::OnUpdate:
virtual void OnUpdate( CView* pSender; LPARAM lHint; CObject* pHint );
其中参数pSender为一指向修改了文档的指针 (当所有文档均需要更 
新时可以设置该参数为NULL),参数lHint内存放着有关这些修改的 
信息,函数最后一个参数pHint则为一存放该修改信息的内容的指 
针。
这样,当任意一个视窗修改了文档时,它就调用pDoc
》UpdateAllViews,该函数又调用与该文档相关联的其它所有视窗中 
的OnUpdate来更新所有显示。由此,在系统中的所有视窗就可以一起 
协调工作了。当在任意一个视窗中键入任何内容时,在其它视窗中也 
可以见到这些内容被显示出来。
…………………………………………………………Page 500……………………………………………………………
图8。24 类CSplitterWnd的层次
在程序中处理多文档,但同时,我们也可以通过分离窗口支持一个文 
档的多个视。分离窗口是这样一种窗口,它们在一个视窗中被分成几 
个相关联的部分,虽然它们在视窗中是分离的,但它们同样协同工 
作,任一窗口中所做的修改同样地反应到其它窗口中。
MFC中支持分离窗口的类是CSplitterWnd,该类的层次结构如图 
8。24。
因为CSplitterWnd类由CWnd类派生而来,它就可以使用它被授权使用 
的那一些CWnd类的成员函数。
class CMdiSplitFrm : public CMDIChildWnd

DECLARE_DYNCREATE(CMdiSplitFrm)
protected:
CMdiSplitFrm(); // protected constructor used by dynamic creation
// add and remove member functions here。
// 。。。
//}}AFX_DISPATCH
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()

l 注意:
l 在这里,涉及到一个创建新类的问题。如 图,打开ClassWizard, 
选择Add Class。。然后,我们键入想要生成类CMdiSplitFrm。并在 
Base class的下拉列表中选择splitter作为该类的基类。如 图 
8。25所示。
…………………………………………………………Page 501……………………………………………………………
图8。25 利用Class Wizard加入一个新类
我们在下面的程序中使用了上面介绍的一些概念,我们的程序也可以 
良好的运行,但仍有许多工作要做。我们的程序使用前面提到的方法 
生成了一个支持窗口分割的MDI,但是,在参考我们的程序建立起你 
自己的应用程序之后,我们想,你一定会发现,我们的程序离一个好 
用的编辑器仍有很长的距离。不过,通过我们的逐步完善,我们完全 
可以将它做得更好。
下面我们给出一个程序运行的画面 (如图8。26)。同时,我们也给出 
一部分关键的源代码,在需要自己添加的部分,我们会以具有底纹的 
文本标出,希望读者注意这些地方。
图8。26 分割窗口的一个运行画面
// MdiDoc。h : interface of the CMdiDoc class
…………………………………………………………Page 502……………………………………………………………
#if !defined(AFX_MDIDOC_H__6A6E4F01_1FC8_11D2_BC8B_E95B8191F13C__INCLUDED_)
// 。。。
class CMdiDoc : public CDocument

protected: // create from serialization only
CMdiDoc();
DECLARE_DYNCREATE(CMdiDoc)
CSize m_sizeDoc;
// Attributes
public:
CString data_string'100';
long line_number;
// Operations
public:
CSize GetDocSize(){return m_sizeDoc;}
// Overrides
// 。。。
protected:
protected:
//{{AFX_MSG(CMdiDoc)
// 。。。
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
// 。。。
#endif // !defined(AFX_MDIDOC_H__6A6E4F01_1FC8_11D2_BC8B_E95B8191F13C__INCLUDED_)
…………………………………………………………Page 503……………………………………………………………
// MdiDoc。cpp : implementation of the CMdiDoc class
#include 〃stdafx。h〃
// CMdiDoc
// 。。。
IMPLEMENT_DYNCREATE(CMdiDoc; CDocument)
BEGIN_MESSAGE_MAP(CMdiDoc; CDocument)
//{{AFX_MSG_MAP(CMdiDoc)
// 。。。
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
// CMdiDoc construction/destruction
CMdiDoc::CMdiDoc()

// TODO: add one…time construction code here
line_number=0;
m_sizeDoc=CSize(800;1000);

// 。。。
BOOL CMdiDoc::OnNewDocument()

if (!CDocument::OnNewDocument())
return FALSE;
// 。。。
return TRUE;

…………………………………………………………Page 504……………………………………………………………
// CMdiDoc serialization
void CMdiDoc::Serialize(CArchive& ar)

if (ar。IsStoring())

ar
小说推荐
返回首页返回目录