友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
C语言实例教程(PDF格式)-第43部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 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';
pDoc…》data_string'pDoc…》line_number'。GetLength());
}
pDoc…》UpdateAllViews(this;0l;NULL);
pDoc…》SetModifiedFlag();
CView::OnChar(nChar; nRepCnt; nFlags);
}
void CMdiView::OnUpdate(CView* pSender; LPARAM lHint; CObject* pHint)
{
// TODO: Add your specialized code here and/or call the base class
Invalidate();
}
…………………………………………………………Page 509……………………………………………………………
void CMdiView::OnInitialUpdate()
{
CView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
}
// Mdi。h : main header file for the MDI application
#if !defined(AFX_MDI_H__6A6E4EF9_1FC8_11D2_BC8B_E95B8191F13C__INCLUDED_)
// 。。。
/////////////////////////////////////////////////////////////////////////////
// CMdiApp:
// See Mdi。cpp for the implementation of this class
//
class CMdiApp : public CWinApp
{
public:
CMdiApp();
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CMdiApp)
public:
virtual BOOL InitInstance();
//}}AFX_VIRTUAL
// 。。。
DECLARE_MESSAGE_MAP()
};
// 。。。
…………………………………………………………Page 510……………………………………………………………
#endif // !defined(AFX_MDI_H__6A6E4EF9_1FC8_11D2_BC8B_E95B8191F13C__INCLUDED_)
// Mdi。cpp : Defines the class behaviors for the application。
#include 〃stdafx。h〃
#include 〃Mdi。h〃
#include 〃MdiSplitFrm。h〃
#include 〃MainFrm。h〃
// 。。。
// CMdiApp
// 。。。
// CMdiApp construction
// 。。。
// The one and only CMdiApp object
CMdiApp theApp;
// CMdiApp initialization
// 。。。
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(
IDR_MDITYPE;
RUNTIME_CLASS(CMdiDoc);
RUNTIME_CLASS(CMdiSplitFrm); // custom MDI splitter frame
RUNTIME_CLASS(CMdiView));
AddDocTemplate(pDocTemplate);
// 。。。
return TRUE;
}
…………………………………………………………Page 511……………………………………………………………
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
// 。。。
};
// 。。。
/////////////////////////////////////////////////////////////////////////////
// CMdiApp mands
//尽管类CSplitter是我们这节的重点,但由于在该类中我们并没有添加什么新的东西,而
//有关该类的基础知识我们在讲解中已经作了解释,此处不再列出。
第七节 添加对多文档类型的支持
在本章前面的部分,我们已经比较详细地对多文档类型支持的一些问
题。在本节中,我们只计划再简单地作一回顾,在本节的最后部分,
我们则简单地谈谈程序对打印的支持手段。
在程序中加入多文档的支持,从技术上来说,只是需要将窗口的直接
基类从单文档界面的CFrameWnd换成多文档程序的CMDIFrameWnd就可
以了。但是,由于多文档程序的特殊性,也出现了一些需要不同处理
的问题。对每个文档来说,它们所关联的视类 (或其派生类)总是仅
仅对应于唯一的文档,因此,对各个文档的数据的管理实际上与单文
档程序没有什么区别,但是,由于多个文档的出现,对它们的管理就
成为主要的问题。
我们不妨先将问题简化。每一个文档可以有多个视,但每个视只能对
应于一个确定的文档。因此,多文档程序需要解决的问题仅仅是多个
文档的数据管理方法的问题 (对视图的管理我们在前面一节中已经作
出了比较详细的解释)。对多文档程序来说,最初的文档模板只支持
主窗口,但每次打开一个新文档时都调用CDocument的函数
OnNewDocument,建立一个有CMDIChildWnd派生的新的MDI子窗口,这
些窗口中保存着各种已打开的文档,所有的细节都由MFC库处理。例
如,当用户单击File菜单下的New菜单项时,将生成另外一个文档并
打开其窗口。但是,每个文档中初始时都是一片空白,因此还需加上
…………………………………………………………Page 512……………………………………………………………
能对不同的窗口事件作出反应的代码。每个MDI子窗口都支持由类
CView派生的普通类型的视窗,这就意味着可以同以前一样不受约束
地使用各类消息。而对各类消息的单独处理,读者不妨参考对应各章
的讲解。
作为文档/视结构的一个组成部分,在本章我们并没有对打印和打印
预览这一部分内容进行讲述。由于篇幅的有限,在本书中我们将不单
独讲述如何添加和完善应用程序的打印支持。这里仅指出一点:在我
们建立非基于对话框的程序时,如果我们选择了打印支持,那么,系
统已经为我们完成了绝大部分的工作。但如果我们没有在最初的设计
中选择打印支持,那么,我们就需要考虑对它自己实现了。MFC提供
了标准打印对话框CPrintDialog来简化打印操作。读者如果有这方面
的需要,请参考系统的帮助文件。
…………………………………………………………Page 513……………………………………………………………
第九章 图形设备接口
事实上,图形设备接口 (Graphics Device Interface,GDI)是指这样
的一个可执行程序,它处理来自Windows应用程序的图形函数调用,
然后把这些调用传递给合适的设备驱动程序,由设备驱动程序来执行
与硬件相关的函数并产生最后的输出结果。GDI可以看作是一个应用
程序与输出设备之间的中介,一方面,GDI向应用程序提�
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!