C语言实例教程(PDF格式)-第64部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
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())
{
arTextOut(0;yval;pDoc…》data_string'loop_index';
pDoc…》data_string'loop_index'。GetLength());
yval+=tm。tmHeight;
}
// TODO: add draw code for native data here
}
/////////////////////////////////////////////////////////////////////////////
// CMdiView printing
// CMdiView diagnostics
// 。。。
#ifdef _DEBUG
void CMdiView::AssertValid() const
{
CView::AssertValid();
}
// 。。。
// CMdiView message handlers
…………………………………………………………Page 508……………………………………………………………
void CMdiView::OnChar(UINT nChar; UINT nRepCnt; UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CMdiDoc *pDoc=GetDocument();
CClientDC dc(this);
OnPrepareDC(&dc);
if(nChar=='r'){
pDoc…》line_number++;
}
else{
pDoc…》data_string'pDoc…》line_number'+=nChar;
TEXTMETRIC tm;
dc。GetTextMetrics(&tm);
dc。TextOut(0;(int)pDoc…》line_number*tm。tmHeight;
pDoc…》data_string'pDoc…》line_number';