文档视图结构高级形式_第1页
文档视图结构高级形式_第2页
文档视图结构高级形式_第3页
文档视图结构高级形式_第4页
文档视图结构高级形式_第5页
已阅读5页,还剩124页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

文档视图结构高级形式

在具有结构的应用程序中,文档数据的初始化、更新、保存等一般由对象完成;视图类对象则提供表示文档数据的人机界面。与视图类对各自任务完成的这种相对独立性与MFC应用程序框架带给它们的,造就了视图组合形式的多样性,这给应用程序带来了丰富的特性。本SDI、MDI组合的多种形式。8.1文档视图结构组合的多种形式8.1.1MDI与SDI程序的区别比较MDI与SDI应用程序的文档视图结构,MDI应用程序有以下几个特点:·可以同时打开多个文档,每个文档有各自的子框架窗口;·主窗口的菜单可以随着当前激活的文档类型发生变化;·子框架窗口可以进行布局方式(层叠、平铺)等各项操作;·子框架窗口可以在MDI主窗口区域内定位、改变大小、最大化和最小化等放置操作,当最大化子框架窗口时,它将占满

MDI主窗口的全部客户区;·MDI不仅可以同时打开多个文档,还可以为每个文档同时建立多个视图。如果在主框架窗口的Window子菜单中选择New

菜单项功能,就为激活的视图窗口复制一个视图窗口。其中,文档的子框架窗口在MDI主框架窗口客户区中的定位、改变大小、最大化、最小化和Window->New功能都已经成为MDI应用程序的标准功能,均在主框架窗口类的基类中已经实现,因此,用户一般无需再增加新的操作。每个MDI应用程序的主框架窗口是CMDIFrameWnd类或其派生类的实例。CMDIFrameWnd的基类是CFrameWnd,它除了拥有CFrameWnd框架窗口类的全部特性外,还具有下列与MDI

相关的特性:

主框架窗口文档窗口客户窗口·主框架窗口并不直接与一个文档和视图相关联。但它拥有一个子帧窗口(又称为MDI客户窗口),当主框架窗口的控制栏

(包括工具栏、状态栏以及其他控制栏甚至菜单)显示或隐藏时,该子帧窗口将重新定位,这一点与SDI框架窗口不同。·MDI主框架的客户窗口是MDI子框架窗口的直接父窗口,它负责管理主框架窗口的客户区以及创建子框架窗口。每个

MDI主框架窗口都有且只有一个MDI客户窗口。

MDI子框架窗口是CMDIChildWnd派生类的实例,CMDIChildWnd的基类也是CFrameWnd,作为视图的框架窗口,相当于SDI的主框架窗口。·每打开一个文档,框架就自动为文档创建一个子框架窗口,

MDI应用程序负责动态地创建和删除这些子框架窗口;·在任何时刻,最多只有一个子框架窗口是激活的,MDI主框架窗口始终与当前激活子框架窗口相关联,命令消息在传给

MDI主框架窗口之前首先传送给当前激活的子框架窗口。·在没有任何激活的子窗口时,主框架窗口使用与主框架窗口关联的菜单,当有激活子窗口时,主框架窗口的菜单会自动被与子框架窗口相关联的菜单所替代。·主框架窗口的基类为子框架窗口的层叠或平铺排列和新建子框架窗口等一些标准窗口管理操作提供了菜单命令的响应操作,因此一般不需要重新定义这类消息的响应函数。MDI小结:1.文档视图模板的基本概念

·文档模板对象是由子框架窗口类、视图窗口类和文档类的运行时信息,以及相应的资源ID

组合而成的;

·一个应用程序中可以有多个同类或不同类文档模板对象;

·一个子框架窗口中可以包含一个或多个视图窗口;

·一个视图对象必须与一个且只与一个文档对象关联;

·一个文档对象可以与多个不同的视图对象关联;2.文档视图模板实例中各个对象的检索关系

·在应用程序类对象中可以检索特定的文档模板对象;

·在文档模板对象中可以检索特定的文档对象;

·在主框架窗口对象中可以检索所有显示的子框架窗口对象;

·在文档对象中可以检索所关联的所有视图对象;8.1.2文档视图的多种组合形式在SDI和MDI两种应用程序结构中,文档和视图的组合形式可以有多种。这取决于以什么形式、方式把文档展示出来。其中切分窗口和切换视图是以多种视图形式展示文档内容的常用方式。应用程序中的切分窗口具有以下特点:·切分窗口一般是定义在SDI的主框架窗口或MDI的子框架窗口中,它占据了框架窗口的客户区区域;·切分窗口将框架窗口客户区划分为若干窗格,每个窗格定义为一个视图框架,这些窗格中的视图可以是同一视图类的实例,也可以是不同视图类的实例;·窗格的划分个数和布局由窗口切分种类和窗格的初始化代码确定,并可以通过鼠标拖动切分隔离条动态调整;·切分窗口是由MFC的CSplitterWnd类对象实现的。切分窗口的创建是在框架窗口创建之后,视图窗口创建之前完成的;·切分窗口不是应用程序框架的基本类,一般不参加命令消息传递过程(即一般不安排消息映射和消息处理),而切分窗口各窗格中的视图类却是命令消息传递过程中的一部分;·切分窗口中窗格的一次划分是有限定的,静态切分窗口的窗格不超过16X16,而动态切分窗口的窗格不超过2X2。切换视图就是在不使用切分窗口的情况下,在框架窗口的客户区轮换显示一个文档的多个视图,从而在同一位置以不同形式显示文档内容。

综合两种同一文档多视图的显示方式,常见的文档视图的组合形式有:·SDI动态切分窗口应用程序;·MDI动态切分窗口应用程序;·SDI静态切分窗口应用程序;·MDI静态切分窗口应用程序;·无切分窗口的SDI多视图切换应用程序;·无切分窗口的MDI多视图切换应用程序本章将通过不同的实例分别叙述各类文档视图的组合形式。8.2实例1:动态切分窗口的SDI应用程序1生成新项目⑴使用AppWizard生成一个名为“Prog1”的SDI应用程序项目。在生成过程中除了进行窗口切分设置(如⑵所述),其他各步都可选择默认设置。⑵使用VisualC++6.0可在step4of6中单击Advanced按钮,显示Advanced

Option对话框。在WindowStyle属性页中,选中

Usesplitwindow复选框,其他设置保持原有默认选择,这将导致AppWizard在主框架窗口类的定义中添加一个CSplitterWnd

类对象,并增加创建切分窗口的相应代码。

使用VisualC++.NET,在项目创建过程中实现上述操作的方法如下:2查看与切分窗口相关的代码⑴在CMainFrame类定义中自动增加了CSplitterWnd对象成员,并重新定义了基类的虚函数OnCreateClient:classCMainFrame:publicCFrameWnd{…protected:CSplitterWndm_wndSplitter;…public:virtualBOOLOnCreateClient(LPCREATESTRUCTlpcs, CCreateContext*pContext);…};⑵在虚函数OnCreateClient中实现主框架窗口的切分该函数在主框架窗口创建之后,创建视图窗口之前被调用,一般在该函数中创建切分窗口和视图窗口。代码如下:

BOOLCMainFrame::OnCreateClient(LPCREATESTRUCT/*lpcs*/, CCreateContext*pContext){returnm_wndSplitter.Create(this, 2,2, //TODO:adjustthenumberofrows,columns CSize(10,10),//TODO:adjusttheminimumpanesize pContext);}

切分窗口的创建函数原型如下:

BOOLCreate(CWnd*pParentWnd, //切分窗口的父窗口指针。

intnMaxRows,intnMaxCols, //切分窗口的切分行和列。

SIZEsizeMin, //窗格显示的最小尺寸。

CCreateContext*pContext, //创建切分窗口的场境参数。

DWORDdwStyle=WS_CHILD|WS_VISIBLE| WS_HSCROLL|WS_VSCROLL|SPLS_DYNAMIC_SPLIT, //切分窗口的风格。

UINTnID=AFX_IDW_PANE_FIRST); //切分窗口的ID。该函数的功能是创建一个动态的切分窗口。CMainFrame::OnCreateClient函数被调用的位置如下框图所示:创建CMainFrame窗口CMainFrame::OnCreateCMainFrame::OnCreateClientm_wndSplitter.CreateCMainFrame::ReCalcLayout⑶在子菜单“查看”(View)中增加了菜单项“分隔”,用于发出切分命令,其标识值为ID_WINDOW_SPLIT。MFC定义了一系列默认命令,用于调用相应类的标准窗口操作。详细参见

MSDN的相关部分内容。3修改视图类的成员函数OnDraw

在视图中显示文本串“VisualC++Programming”。

voidCProg1View::OnDraw(CDC*pDC){ CProg1Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere CRectrc; GetClientRect(&rc); pDC->SetTextColor(RGB(255,0,0)); pDC->TextOut(5,(rc.bottom-rc.top)/2,"VisualC++Programming");}4

编译运行“Prog1”8.3实例2:动态切分窗口的MDI应用程序1生成新项目⑴使用AppWizard生成一个名为“Prog2”的MDI应用程序项目。在生成过程中除了在step4of6中进行窗口切分设置(如⑵所述),其他各步都选择默认设置。⑵设置子框架窗口的切分属性,方法同前。使得子框架窗口类中添加CSplitterWnd类对象,并添加相应的创建切分子框架窗口的代码。2查看与窗口切分相关的代码⑴在CChildFrame中添加了CSplitterWnd对象成员,并重新定义了基类的虚函数OnCreateClient:

classCChildFrame:publicCMDIChildWnd{DECLARE_DYNCREATE(CChildFrame) …protected:CSplitterWndm_wndSplitter;…public:virtualBOOLOnCreateClient(LPCREATESTRUCTlpcs, CCreateContext*pContext); …};⑵在虚函数OnCreateClient中实现子框架窗口的切分该函数在子框架窗口创建之后,创建视图窗口之前被调用,一般在该函数中创建切分窗口和视图窗口。代码如下:

BOOLCChildFrame::OnCreateClient(LPCREATESTRUCT/*lpcs*/, CCreateContext*pContext){returnm_wndSplitter.Create(this, 2,2,//TODO:adjustthenumberofrows,columns CSize(10,10),//TODO:adjusttheminimumpanesize pContext);}⑶在子框架窗口菜单的“窗口”(Window)子菜单中添加了菜单项“分隔”,用于发出切分命令,其标识为ID_WINDOW_SPLIT。3修改视图类成员函数OnDraw

在视图中显示文本串“VisualC++Programming”。

voidCProg2View::OnDraw(CDC*pDC){ CProg2Doc*pDoc=GetDocument(); ASSERT_VALID(pDoc); //TODO:adddrawcodefornativedatahere CRectrc; GetClientRect(&rc); pDC->SetTextColor(RGB(255,0,0)); pDC->TextOut(5,(rc.bottom-rc.top)/2,"VisualC++Programming“);}4编译运行“Prog2”小结:

·在框架窗口类中增加一个窗口切分类CSplitterWnd的对象成员;

·重新定义框架窗口类(SDI的主框架窗口,MDI的子框架窗口)的成员函数OnCreatClient;

·在OnCreatClient的定义中调用CSplitterWnd::Create完成对框架窗口类对象的客户窗口的动态切分(至多2×2),并与文档视图模板实例的视图对象关联。8.4静态切分窗口的多视图SDI应用程序从前面的实例不难看出,动态切分虽然将框架窗口的客户区切分成多个窗格,但每个窗格中只能共用同一视图,这就不能充分体现文档视图提供的多视图特性。这是动态切分窗口的一个特点。下面开始使用切分窗口的另一种形式——静态切分窗口,它的特点是每个窗格中的视图类可以不同。1生成新项目⑴使用AppWizard生成一个名为“Prog3”的SDI应用程序项目。⑵设置主框架窗口的切分属性,方法同前。使得子框架窗口类中添加CSplitterWnd类对象,并添加相应的创建切分主框架窗口的代码。⑶修改视图类的基类为CScrollView,并将缺省的类名修改为

CDigitView,类定义文件名和实现文件名分别修改为DigitView.h

和DigitView.cpp。2增加文档类数据成员和相应的数据类操作在文档类CProg3Doc中增加一个数组模板类对象数据成员:CArray<int,int>m_nArray,用于存放一组数据。这组数据将在文档所关联的不同视图中以不同的形式被显示。⑴为了使用数组模板类,必须在StdAfx.h中加入相应的系统头文件:

#endif//_AFX_NO_AFXCMN_SUPPORT#include<afxtempl.h>⑵在CProg3Doc类定义中添加数组模板类数据成员m_nArray的定义:

classCProg3Doc:publicCDocument{protected://createfromserializationonlyCProg3Doc();DECLARE_DYNCREATE(CProg3Doc)//Attributespublic:CArray<int,int>m_nArray;…};⑶修改CProg3Doc构造函数,加入对m_nArray的初始化代码:

CProg3Doc::CProg3Doc(){//TODO:addone-timeconstructioncodeherem_nArray.SetSize(10,0); //sizeandincreaseofarraym_nArray[0]=3;m_nArray[1]=4;m_nArray[2]=8;m_nArray[3]=20;m_nArray[4]=12;m_nArray[5]=17;m_nArray[6]=11;m_nArray[7]=7;m_nArray[8]=9;m_nArray[9]=6;}⑷修改CDigitView::OnDraw,显示m_nArray所保存数据:

voidCDigitView::OnDraw(CDC*pDC){CProg3Doc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahereTEXTMETRICtm;pDC->GetTextMetrics(&tm);inty=0;CStringstr;for(inti=0;i<pDoc->m_nArray.GetSize();i++){ str.Format("%2d:%d",i+1,pDoc->m_nArray[i]); pDC->TextOut(10,y,str); y+=tm.tmHeight+tm.tmExternalLeading;}}3增加一个视图类为了实现用直方图(棒图)显示文档数据的目的,需要给文档类CProg3Doc添加一个视图类CBarView。⑴添加一个新类CBarView,选择它的基类为CView。⑵为CBarView类添加获取文档对象指针的函数GetDocument,在CBarView的定义文件中添加:

classCBarView:publicCView{…public:CProg3Doc*GetDocument();…};

在CBarView实现文件添加:

#include“Prog3Doc.h”和GetDocument的定义代码:

CProg3Doc*CBarView::GetDocument(){ASSERT(m_pDocument-> IsKindOf(RUNTIME_CLASS(CProg3Doc)));return(CProg3Doc*)m_pDocument;}

其中m_pDocument是CArchive类的一个CDocument类型的数据成员,当使用菜单命令File->Open或File->New创建文档类对象时,m_pDocument指向新创建的文档类对象。⑶修改CBarView::OnDraw,实现用直方图显示m_nArray数据:

voidCBarView::OnDraw(CDC*pDC){CProg3Doc*pDoc=GetDocument();//TODO:adddrawcodehereCRectrc; //createaclientareaintcBar,cBarSpace; //barwidthandspacebetweentwobarsintx,y; //calculatepositionofbardrawingintcxGraph=100,cyGraph=20; //logicalwidth,heightGetClientRect(&rc);CBrushbr1(RGB(255,0,0)); //createabrushCPenpen(PS_SOLID,1,RGB(255,0,0)); //createapenCBrush*poldBr=pDC->SelectObject(&br1);CPen*poldPen=pDC->SelectObject(&pen);cBar=cxGraph*3/4/10;cBarSpace=cBar/3;pDC->SetMapMode(MM_ANISOTROPIC);pDC->SetWindowOrg(0,0);pDC->SetViewportOrg(10,rc.bottom-10);pDC->SetWindowExt(cxGraph,cyGraph);pDC->SetViewportExt(rc.right-20,-rc.bottom+20);

inti;for(x=cBarSpace,y=0,i=0;i<pDoc->m_nArray.GetSize(); i++,x+=cBar+cBarSpace) pDC->Rectangle(x,y,x+cBar,y+pDoc->m_nArray[i]);pDC->SelectObject(poldBr);pDC->SelectObject(poldPen);}

代码中关于坐标映射和直方图的绘制可以用下图表示:4修改框架窗口类⑴在CMainFrame类实现文件中加入:

#include"DigitView.h"#include"BarView.h“

在CDigitView类定义文件中加入:

#include"Prog3Doc.h"rc.right-20rc.bottom+20(10,rc.bottom-10)+X+YMM_ANISOTROPICCxGraph=100CyGraph=20cBarcBarSpac+X+Y(0,0)⑵修改CMainFrame::OnCreateClient函数

BOOLCMainFrame::OnCreateClient(LPCREATESTRUCT/*lpcs*/, CCreateContext*pContext){m_wndSplitter.CreateStatic(this,1,2);m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CDigitView), CSize(200,0),pContext);m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CBarView), CSize(0,0),pContext);returnTRUE;}

其中切分窗口类的两个成员函数的原型:

BOOLCreateStatic(CWnd*pParentWnd, //切分窗口的父窗口指针

intnRows,intnCols, //切分窗口的行和列

DWORDdwStyle=WS_CHILD|WS_VISIBLE, //切分窗口风格

UINTnID=AFX_IDW_PANE_FIRST //切分窗口的ID );

virtualBOOLCreateView(introw,intcol, //指定窗格的行和列

CRuntimeClass*pViewClass, //指定窗格中要创建的指定视图类

SIZEsizeInit, //视图显示的初始尺寸

CCreateContext*pContext //创建视图的场境

);CMainFrame::OnCreateClient函数的调用位置如下:5编译运行“Prog3”

发现问题:当CDigitView的窗格变小到不能显示全部数据的时候,虽然可以滚动视窗,但不能在垂直方向看到全部数据。创建CMainFrame窗口CMainFrame::OnCreateCMainFrame::OnCreateClientm_wndSplitter.CreateStaticm_wndSplitter.CreateViewCMainFrame::ReCalcLayout6修改CDigitView::OnInitialUpdate:将原来的代码:

sizeTotal.cx=sizeTotal.cy=100;SetScrollSizes(MM_TEXT,sizeTotal);

修改为如下代码:

CClientDCdc(this);TEXTMETRICtm;dc.GetTextMetrics(&tm);sizeTotal.cx=tm.tmMaxCharWidth*8;sizeTotal.cy=(tm.tmHeight+tm.tmExternalLeading)*10;SetScrollSizes(MM_TEXT,sizeTotal);

使视窗中所显示文本的字体的几何尺寸成为视窗滚动操作的依据,从而解决了上述问题。8.5静态切分窗口的多视图MDI应用程序1生成新项目⑴使用AppWizard生成一个名为“Prog4”的MDI应用程序项目。⑵设置子框架窗口的切分属性,方法同前。使得子框架窗口类中添加CSplitterWnd类对象,并添加相应的创建切分子框架窗口的代码。⑶修改视图类的基类为CScrollView,并将缺省的类名修改为

CDigitView,类定义文件名和实现文件名分别修改为DigitView.h

和DigitView.cpp。2添加文档类数据成员和相应的数据类操作在文档类CProg3Doc中增加一个数组模板类对象数据成员:CArray<int,int>m_nArray,用于存放一组数据。这组数据将在文档所关联的不同视图中以不同的形式被显示。⑴为了使用数组模板类,必须在StdAfx.h中加入相应的系统头文件:

#endif//_AFX_NO_AFXCMN_SUPPORT#include<afxtempl.h>⑵在CProg3Doc类定义中加入数组模板类数据成员m_nArray的定义:

classCProg4Doc:publicCDocument{…//Attributespublic:CArray<int,int>m_nArray;…};⑶修改CProg4Doc类构造函数,对m_nArray初始化:

CProg4Doc::CProg4Doc(){//TODO:addone-timeconstructioncodeherem_nArray.SetSize(10,0); //sizeandincreaseofarraym_nArray[0]=3;m_nArray[1]=4;m_nArray[2]=8;m_nArray[3]=20;m_nArray[4]=12;m_nArray[5]=17;m_nArray[6]=11;m_nArray[7]=7;m_nArray[8]=9;m_nArray[9]=6;}3修改CDigitView::OnDraw:

voidCDigitView::OnDraw(CDC*pDC){CProg4Doc*pDoc=GetDocument();ASSERT_VALID(pDoc);//TODO:adddrawcodefornativedatahereTEXTMETRICtm;pDC->GetTextMetrics(&tm);inty=0;CStringstr;for(inti=0;i<pDoc->m_nArray.GetSize();i++){ str.Format("%2d:%d",i+1,pDoc->m_nArray[i]); pDC->TextOut(10,y,str); y+=tm.tmHeight+tm.tmExternalLeading;}}4增加CBarView类由于CBarView类的定义和实现与实例3中的完全一致,所以可以采用借码法增加CBarView类,步骤如下:⑴把实例3

中的源文件BarView.h和BarView.cpp复制到本项目源文件目录中。⑵选择菜单Project->Addtoproject->Files…命令,在弹出的添加文件对话框中选择上述两个文件加入本项目,即可完成在项目中添加CBarView的工作。⑶最后将这两个文件中所有的“Prog3”字串替换为“Prog4”,这样就使CBarView成为与CProg4Doc相关联的视图类了。5增加一个绘制折线的视图类CPolyView:除了用数字和直方图形式显示m_nArray中的数据外,再增加一种用折线显示数据变化情况的视图,这也是常用的显示数据变化的方式。为此,需要在项目中增加一个绘制折线的视图类CPolyView。⑴使用ClassWizard定义CPolyView,选择该类基类为CView。⑵在CPolyView中添加获取文档指针的成员函数GetDocument,添加方法和所添加的代码与CBarView::GetDocument相似。⑶修改CPolyView::OnDraw函数:

voidCPolyView::OnDraw(CDC*pDC){CProg4Doc*pDoc=GetDocument();//TODO:adddrawcodehereCRectrc; //createaclientareaintcLine,cLineSpace; //linelengthandspacebetweentwolinesintx,y; //calculatepositionofbardrawingintcxGraph=100,cyGraph=20;//widthandheightforlogicalgraphGetClientRect(&rc);CBrushbr1(RGB(0,255,0)); //createabrushCPenpen(PS_SOLID,1,RGB(0,255,0)); //createapenCBrush*poldBr=pDC->SelectObject(&br1);CPen*poldPen=pDC->SelectObject(&pen);cLine=cxGraph*3/4/10;cLineSpace=cLine/3;pDC->SetMapMode(MM_ANISOTROPIC);pDC->SetWindowOrg(0,0);pDC->SetViewportOrg(10,rc.bottom-10);pDC->SetWindowExt(cxGraph,cyGraph);pDC->SetViewportExt(rc.right-20,-rc.bottom+20);inti;x=cLineSpace;y=0;pDC->MoveTo(x,y);for(x=cLineSpace,y=0,i=0;i<pDoc->m_nArray.GetSize(); i++,x+=cLine+cLineSpace) pDC->LineTo(x+cLine,y+pDoc->m_nArray[i]);CPenpen1(PS_DOT,0,RGB(0,0,255));pDC->SelectObject(&pen1);for(x=cLineSpace,y=0,i=0;i<pDoc->m_nArray.GetSize(); i++,x+=cLine+cLineSpace){ pDC->MoveTo(x+cLine/2,y); pDC->LineTo(x+cLine/2,-rc.top+20);}pDC->SelectObject(poldBr);pDC->SelectObject(poldPen);}6修改子框架窗口类CChildFrame:⑴在CChildFrame类定义中添加一个CSplitterWnd类对象成员

m_wndSplitter1,用于将切分窗口实例m_wndSplitter的一个窗格进行一次新的切分。

classCChildFrame:publicCMDIChildWnd{…DECLARE_DYNCREATE(CChildFrame)public:CChildFrame();protected:CSplitterWndm_wndSplitter;CSplitterWndm_wndSplitter1;…};⑵由于在创建静态切分窗口的代码中需要定义各窗格中的视图类对象,所以需要在CChildFrame的实现文件中加入:

#include"stdafx.h"#include"Prog4.h"#include"DigitView.h"#include"BarView.h"#include"PolyView.h"#include"ChildFrm.h"⑶修改CChildFrame::OnCreateClient函数:

BOOLCChildFrame::OnCreateClient(LPCREATESTRUCT/*lpcs*/, CCreateContext*pContext){m_wndSplitter.CreateStatic(this,1,2);m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CDigitView), CSize(200,0),pContext);m_wndSplitter1.CreateStatic(&m_wndSplitter,2,1, WS_CHILD|WS_VISIBLE,m_wndSplitter.IdFromRowCol(0,1));m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CBarView), CSize(0,100),pContext);m_wndSplitter1.CreateView(1,0,RUNTIME_CLASS(CPolyView), CSize(0,0),pContext);SetActiveView((CDigitView*)m_wndSplitter.GetPane(0,0));returnTRUE;}函数OnCreateClient对子框架窗口的切分过程如下:①首先m_wndSplitter.CreateStatic(this,1,2)在子框架窗口中创建切分窗口m_wndSplitter,把子框架窗口的客户区切分为两个窗格(1行2列)。窗格(0,0)窗格(0,1)m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CDigitView), CSize(200,0),pContext)视图CDigitView等待继续切分m_wndSplitter②然后在m_wndSplitter的窗格(0,1)中,调用CreateStatic创建切分窗口m_wndSplitter1,将m_wndsplitter的窗格(0,1)再次切分为2行1列。m_wndSplitter窗格(0,0)视图CDigitViewm_wndSplitter窗格(0,1)等待继续切分m_wndSplitter1.CreateStatic(&m_wndSplitter,2,1,WS_CHILD|WS_VISIBLE, m_wndSplitter.IdFromRowCol(0,1))m_wndSplitter1窗格(0,0)m_wndSplitter1窗格(1,0)m_wndSplitter1.CreateView(0,0,RUNTIME_CLASS(CBarView),CSize(0,100),pContext)CBarView视图m_wndSplitter1.CreateView(1,0,RUNTIME_CLASS(CPolyView),CSize(0,0),pContext)CPolyView视图7修改CDigitView::OnInitialUpdate函数:使得当视图窗口的尺寸小到不能看到所显示的全部数据时,可以通过使用滚动条浏览全部数据。voidCDigitView::OnInitialUpdate(){CScrollView::OnInitialUpdate();CSizesizeTotal;//TODO:calculatethetotalsizeofthisviewCClientDCdc(this);TEXTMETRICtm;dc.GetTextMetrics(&tm);sizeTotal.cx=tm.tmMaxCharWidth*8;sizeTotal.cy=(tm.tmHeight+tm.tmExternalLeading)*10;SetScrollSizes(MM_TEXT,sizeTotal);}8

编译运行“Prog4”小结:

·在框架窗口类中按切分格式需要增加n个CSplitterWnd的对象成员;

·重新定义框架窗口类(SDI的主框架窗口,MDI的子框架窗口)的成员函数OnCreatClient;

·按照对窗格切分的需要在OnCreatClient的定义中恰当地调用

CSplitterWnd::CreateStatic完成对框架窗口类对象的客户窗口和切分窗格的再切分(每次至多16×16);

·将每个窗格与不同的视图对象关联,而这些视图对象必须与同一个文档对象相关联。8.6实例5:无切分窗口的多视图SDI应用程序本例的目的是创建一个无切分窗口的多视图切换的SDI应用程序。内容是:将一个在文本编辑视图中产生的文本保存在与该编辑视图相关联的文档类对象的字符数组中。同时为该文档定义另一视图,在此视图中将文档中所保存的文本以带有下划线的粗斜体显示出来。文档所绑定的两个视图可以切换显示。1生成新项目⑴使用AppWizard生成一个名为“Prog5”的SDI应用程序项目。⑵将文档模板字串(DocumentTemplateString)修改为:

Prog5\n\nProg5\nProg5文件(*.txt)\n.txt\nProg5.Document\nProg5Document,使得保存文档内容的磁盘文件的默认扩展名为

txt;⑶将视图类的缺省类名CProg5View修改为CNormalView,并将

CNormalView的基类改为CEditView,同时将相应的类声明文件名和实现文件名分别修改为NormalView.h和NormalView.cpp。2修改文档类CProg5Doc:⑴在定义文件中加入视图类头文件:

#include"NormalView.h"⑵在CProg5Doc的定义中加入保存文本的数据成员:

…public: CStringm_szTextBuf; //savecontentsoftext…⑶修改CProg5Doc类构造函数:

CProg5Doc::CProg5Doc(){ m_szTextBuf=_T(“”); //settextbufferempty}⑷修改CProg5Doc::OnNewDocument和CProg5Doc::Serialize:

BOOLCProg5Doc::OnNewDocument(){if(!CDocument::OnNewDocument()) returnFALSE;((CEditView*)m_viewList.GetHead())->SetWindowText(NULL); //TODO:addreinitializationcodehere//(SDIdocumentswillreusethisdocument) m_szTextBuf=_T(“”); //settextbufferempty

returnTRUE;}

voidCProg5Doc::Serialize(CArchive&ar){//CEditViewcontainsaneditcontrolwhichhandlesallserialization((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);if(ar.IsLoading()){ POSITIONpos=GetFirstViewPosition(); CNormalView*pView=(CNormalView*)GetNextView(pos); ASSERT_VALID(pView); m_szTextBuf=pView->LockBuffer(); //copytextformeditviewtobuffer. pView->UnlockBuffer();}}3修改CNormalView视图类⑴在CNormalView类定义文件中加入文档类头文件:

#include"Prog5Doc.h"⑵为消息EN_CHAGE添加反射消息映射和处理函数,以便实时保存编辑视图窗口中发生了变化的文本。

ON_CONTROL_REFLECT(EN_CHANGE,OnChange) voidCNormalView::OnChange(){…CProg5Doc*pDoc=GetDocument();ASSERT_VALID(pDoc); pDoc->m_szTextBuf=LockBuffer(); UnlockBuffer();pDoc->SetModifiedFlag();}4增加一个视图类CItalicsView用于斜体加下划线显示文本⑴定义一个新类CItalicsView,选择其基类为CView。⑵在CItalicsView类中添加获取文档指针的函数GetDocument:在CItalicsView的类定义文件中加入:

#include"Prog5Doc.h"…classCItalicsView:publicCView{…

public:CItalicsView();//protectedconstructorusedbydynamiccreationCProg5Doc*GetDocument();…};

在CItalicsView的实现文件中添加GetDocument的定义代码:

CProg5Doc*

CItalicsView::GetDocument()

//non-debugversionisinline{ASSERT(m_pDocument-> IsKindOf(RUNTIME_CLASS(CProg5Doc)));return(CProg5Doc*)m_pDocument;}⑶修改CItalicsView::OnDraw函数:

voidCItalicsView::OnDraw(CDC*pDC){CProg5Doc*pDoc=GetDocument(); LOGFONTlf;memset(&lf,0,sizeof(LOGFONT));lf.lfItalic=TRUE;lf.lfUnderline=TRUE;lf.lfWeight=FW_BOLD;CFontfont;font.CreatePointFontIndirect(&lf);

CFont*poldFont=pDC->SelectObject(&font);TEXTMETRICtm;pDC->GetTextMetrics(&tm);inty=0,count=pDoc->m_szTextBuf.GetLength(),start=0;while(start<count){ intend=pDoc->m_szTextBuf.Find('\n',start); if(end!=-1) { pDC->TextOut(0,y, pDoc->m_szTextBuf.Mid(start,end-start-1)); start=end+1; } elseif(start<count) { pDC->TextOut(0,y, pDoc->m_szTextBuf.Mid(start,count-start)); start=count; } y+=tm.tmHeight+tm.tmExternalLeading;}pDC->SelectObject(poldFont);}⑷为命令消息ID_、ID_、ID_和

ID_定义用户界面更新函数,以便在切换到

CItalicsView视图时,禁用上述命令。

voidCItalicsView::OnUpdate(CCmdUI*pCmdUI){pCmdUI->Enable(FALSE); }voidCItalicsView::OnUpdate(CCmdUI*pCmdUI){pCmdUI->Enable(FALSE); }voidCItalicsView::OnUpdate(CCmdUI*pCmdUI){pCmdUI->Enable(FALSE); }voidCItalicsView::OnUpdate(CCmdUI*pCmdUI){pCmdUI->Enable(FALSE); }5修改菜单在“查看”子菜单中加入用于切换视图命令的菜单项:菜单项标题菜单项标识提示文本普通视图(&N)斜体视图(&I)ID_VIEW_NORMALID_VIEW_ITALICS普通字体文本视图倾斜字体文本视图6在CMainFrame类中增加两个视图类指针成员⑴在CMainFrame类中声明两个视图指针成员:

…#include"NormalView.h"#include"ItalicsView.h"classCMainFrame:publicCFrameWnd{…//Implementationpublic:CNormalView*m_pNormalView;CItalicsView*m_pItalicsView;…};⑵初始化视图指针:

CMainFrame::CMainFrame(){m_pNormalView=0;m_pItalicsView=0;}7为菜单命令ID_VIEW_ITALICS添加响应函数

voidCMainFrame::OnViewItalics(){

CProg5Doc*pDoc=(CProg5Doc*)GetActiveDocument();

if(m_pItalicsView==0)

{

m_pNormalView=(CNormalView*)GetActiveView();

m_pItalicsView=newCItalicsView();

m_pItalicsView->Create(NULL,NULL,AFX_WS_DEFAULT_VIEW,

rectDefault,this,AFX_IDW_PANE_FIRST+1);

}

intnSwitchChildID=m_pItalicsView->GetDlgCtrlID();

m_pItalicsView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

m_pNormalView->SetDlgCtrlID(nSwitchChildID);

m_pItalicsView->ShowWindow(SW_SHOW);

m_pNormalView->ShowWindow(SW_HIDE);

pDoc->AddView(m_pItalicsView);

pDoc->RemoveView(m_pNormalView);

SetActiveView(m_pItalicsView);

RecalcLayout();

}8为菜单命令ID_VIEW_NORMAL添加响应函数

voidCMainFrame::OnViewNormal(){

CProg5Doc*pDoc=(CProg5Doc*)GetActiveDocument();

ASSERT(m_pNormalView!=0);

ASSERT(m_pItalicsView!=0);

intnSwitchChildID=m_pNormalView->GetDlgCtrlID();

m_pNormalView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

m_pItalicsView->SetDlgCtrlID(nSwitchChildID);

m_pNormalView->ShowWindow(SW_SHOW);

m_pItalicsView->ShowWindow(SW_HIDE);

pDoc->AddView(m_pNormalView);

pDoc->RemoveView(m_pItalicsView);

SetActiveView(m_pNormalView);

RecalcLayout();

}9为命令消息ID_VIEW_NORMAL和ID_VIEW_ITALICS添加用户界面更新函数

voidCMainFrame::OnUpdateViewItalics(CCmdUI*pCmdUI){ pCmdUI->Enable(GetActiveView()->IsKindOf( RUNTIME_CLASS(CNormalView))&&((CProg5Doc*) GetActiveDocument())->m_szTextBuf.GetLength()!=0);}voidCMainFrame::OnUpdateViewNormal(CCmdUI*pCmdUI){ pCmdUI->Enable(GetActiveView()->IsKindOf( RUNTIME_CLASS(CItalicsView)));}10编译运行“Prog5”小结:·根据需要为单文档视图模板中的文档类定义与之关联的不同视图类;·在单文档视图模板的框架窗口类中为不同的视图类对象添加指针;·在操作界面(例如菜单)中添加能发送在框架窗口中分别显示不同视图的命令消息的功能(例如菜单条目);·在单文档视图模板的框架窗口类中添加消息响应函数分别用于不同视图对象的创建、与文档对象关联、切换显示(显示指定视图,隐蔽其他视图)。8.7实例6:无切分窗口的多视图MDI应用程序本例的目的是创建一个无切分窗口的多视图MDI应用程序。内容是:将一个在文本编辑视图中产生的文本保存在与该编辑视图相关联的文档类对象的字符数组中。同时为该文档定义另外一个斜体显示视图,在此视图中将文档中所保存的文本以带有下划线的粗斜体显示出来。对于一个文档,对应的编辑视图只能有一个,而斜体显示视图可以有一个以上。在编辑视图窗口中编辑的文本被同步地显示在所有与该文档相关联的所有视图中。1生成新项目⑴使用AppWizard生成一个名为“Prog6”的MDI应用程序项目。⑵将文档模板字串(DocumentTemplateString)修改为:

Prog5\n\nProg5\nProg5文件(*.txt)\n.txt\nProg5.Document\nProg5Document,使得保存文档内容的磁盘文件的默认扩展名为

txt;⑶将视图类的缺省类名CProg6View修改为CNormalView,并将

CNormalView的基类改为CEditView,同时将相应的类声明文件名和实现文件名分别修改为NormalView.h和NormalView.cpp。2修改文档类CProg6Doc:⑴在定义文件中加入视图类头文件:

#include"NormalView.h"⑵在CProg6Doc的定义中加入保存文本的数据成员:

…public: CStringm_szTextBuf; //savecontentsoftext…⑶修改CProg6Doc类构造函数:

CProg6Doc::CProg6Doc(){m_szTextBuf=_T(“”); //settextbufferempty}⑷修改CProg6Doc::OnNewDocument和CProg6Doc::Serialize:

BOOLCProg6Doc::OnNewDocument(){if(!CDocument::OnNewDocument()) returnFALSE;((CEditView*)m_viewList.GetHead())->SetWindowText(NULL); //TODO:addreinitializationcodehere//(SDIdocumentswillreusethisdocument)m_szTextBuf=_T(“”); //settextbufferempty returnTRUE;}voidCPro

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论