欢迎大家光临【无师自通-教程网】您的到来是我们的荣幸。本站提供photoshop教程,ps教程,flash教程,cad教程,网页制作教程,excel教程,asp教程,vb教程,3d教程,c语言教程,html教程,coreldraw教程,dreamweaver教程,java教程,3dmax教程 等各种教程为主题的内容和服务,相信您会在这里找到您所需要的东东。无师自通伴您一生-谢谢您的光临!!
网站地图 设为首页
简繁切换 加入收藏
栏目待定 留言本站
您现在的位置: 无师自通-教程网 >> 程序设计 >> Visual C教程 >> VC.NET教程 >> 教程正文

  没有公告

教程: VisualC .NET编程讲座之三 更多...
教程: VisualC .NET编程讲座之三
第二讲 文档数据的读取和显示

  摘要

  本讲先来介绍程序各个类的关联机制,然后讨论文档的读过程及读操作,最后讨论文档数据的显示方法和技巧。

  程序中各用户类的关联

  在上一讲中,我们使用MFC应用程序向导创建一个单文档项目TextViewer。现在,我们打开该项目。可以看出,向导为TextViewer项目创建了以下几个类:

  应用程序类CTextViewerApp,应用程序必须的运行入口,在上一讲已经讨论过。

  主框架窗口类CMainFrame,用来负责窗口的标题栏、菜单、工具栏及状态栏等界面元素的操作。

  文档类CTextViewerDoc,用来负责文档数据的读取和保存

  视图类CTextViewerView类,用来显示文档显示,并可响应各种类型的输入(例如键盘输入)以及实现打印和打印预览等。

  还有一个对话框类CAboutDlg,用来显示该应用程序的版本信息,是一个"关于"对话框。

  需要说明的是,Visual C .NET将各个类的声明保存在头文件中,即以.h为扩展名,而将类的实现代码保存在以.cpp为扩展名的实现文件中。

  那么,在MFC中上述的主框架窗口类、文档类和视图类的关系是怎样呢?我们来看一下。

  将解决方案管理器切换到"类视图",展开CTextViewerApp类的所有节点,双击"InitInstance( void )",打开该函数代码。由于Visual C .NET的代码注释是中文的,因此我们这里仅给出如图1所示的代码。


图1 InitInstance函数中的部分代码

  代码中,CSingleDocTemplate是从CDocTemplate派生的单文档类,它协调了文档窗口、文档和视图的关系,并把三者联系起来。该类的构造函数需要指定四个参数,分别为表示菜单和加速键等的资源ID号以及三个由宏RUNTIME_CLASS指定的CRuntimeClass结构对象指针,它们分别是程序的文档类、框架窗口类和视图类的结构指针。

  CRuntimeClass结构反映一个运行时类的信息,通常用宏RUNTIME_CLASS来获取一个类的CRuntimeClass结构指针。Visual C 借助CRuntimeClass类结构能在应用程序运行过程中获得该类对象及其基类的相关信息,从而可以实现运行时类型检查(Run Time Type Inspection,RTTI)。

  AddDocTemplate用来将指定的单文档模板或多文档模板指针添加到程序所包含内部的文档模板指针列表中。


  文档的读过程

  在向导创建的应用程序中,程序的默认菜单有"文件"、"编辑"、"视图"和"帮助"。当运行程序后,打开"文件"菜单中的"打开"命令时,应用程序会自动打开相应的"打开"文件通用对话框。之所以有这功能,是因为向导创建的应用程序框架中,自动将"打开"菜单命令与CWinApp的OnFileOpen成员函数相关联。这种关联是通过"消息映射"来实现的,在CTextViewerApp类的实现文件TextViewer.cpp前面有这样的代码,如图2所示。


图2 应用程序类的消息映射

  "消息映射"是MFC中的一个亮点。在Windows操作环境中,无论是系统产生的动作或是用户运行应用程序产生的动作,都称为事件(Events)产生的消息(Message)。例如,用户选择菜单时所产生的消息称为"命令"消息,而鼠标改变窗口状态时所产生的消息是"窗口"消息。只要是消息,都可以通过MFC的"消息机制"来映射。映射的目的是将消息和某个函数相关联,这样一旦该消息产生就会执行相关联的函数。

  图2代码中,BEGIN_MESSAGE_MAP和END_MESSAGE_MAP是MFC开始和结束消息映射宏,ON_COMMAND是专门用来映射像菜单的一些命令消息宏,它有两个参数,第一个参数用来指定命令标识,MFC中每个菜单项都有一个标识值,"打开"菜单的标识ID为ID_FILE_OPEN,第二个参数是用来指定关联的函数。(消息映射以后还会讲到)

  当用户在通用"打开"文件对话框中指定一个文件后,应用程序将调用文档对象的 CDocument::OnOpenDocument虚成员函数。该函数将打开文件,并调用DeleteContents清除文档对象的内容,然后创建一个CArchive(归档类)对象用于数据的读取,接着又自动调用Serialize函数。之后便调用视图对象的CView::OnInitialUpdate虚成员函数。

  在这个过程中,我们可能有很多地方不理解。但我们仔细想一想就会明白许多。假如视图中已有文档数据显示,为了能快速显示和修改这些数据,显然这些数据要存储在专门的内存空间中,CArchive类对象就起到了这个作用。当打开另一个文档时,以前在内存中存储的数据要清除,这就是DeleteContents作用,而且还要使视图能及时更新显示,所以要调用OnInitialUpdate函数。

  上述的Serialize函数是一个很特别的函数,它既可以从中读取文档数据,也可以保存文档数据,称为"序列化"函数。它被添加用户的文档类中,用来根据CArchive内部的一个标志来决定文档数据的流向(读或写),如图3所示。


图3 Serialize函数代码


  文档数据的读操作

  对于上述过程,我们所做的仅仅是在文档类的Serialize函数中添加文档数据读取(加载)和存储的代码。需要说明的是,Serialize函数的参数ar是一个CArchive类的引用对象。CArchive类提供了"<<"和">>"运算符,分别可以向文档对象写入数据或从文档对象中读取数据。它们的含义与C 中的"<<"和">>"运算符相同,只不过CArchive支持更多的数据类型,如:CObject、CString等。除此之外CArchive类还提供ReadString和WriteString成员函数来读写文档中的一行文本。下面的过程用来将文档的文本内容读出并保存到一个字符串集合类对象中。

  (1) 将解决方案管理器窗口切换到"类视图",展开所有的类,右击类名"CTextViewerDoc",从弹出的快捷菜单中选择"添加"->"添加变量",弹出"添加成员变量向导"对话框,在"变量类型"框中输入CStringArray,在"变量名"框中输入m_strContent,如图4所示。单击"完成"按钮。

  CStringArray是"字符串集合类",它封装了CString数组对象的全部操作。类似的还有对BYTE、UINT、WORD和DWORD等类型的数组操作的集合类CByteArray、CUIntArray、CWordArray和CDWordArray。这些集合类都有相似的操作,如Add(添加)、RemoveAll(删除全部元素)、GetAt(获取指定数组下标的元素)等。


图4 添加成员变量

  (2) 在CTextViewerDoc::Serialize函数中添加读取文档文本内容代码,如图5所示。


图5 添加的读取文档文本内容代码

  代码中,ReadString是读取打开的文档的一行文本,当成功读出时,函数返回TRUE,当文本达到文档结尾时,函数返回FALSE。这样,通过while循环可以将文档的文本内容全部读取并保存到m_strContent中。

  (3) 由于另一个文档打开时,需要将m_strContent中的内容清除,所以我们需要跟踪DeleteContents函数。在CTextViewerDoc类的属性窗口,单击"重写"按钮,在列表框中找到DeleteContents函数项,单击右边的空格后再单击右侧的下拉按钮,出现一个下拉列表,如图6所示。


图6 添加DeleteContents函数的重写

  (4) 单击"<添加>DeleteContents",该函数的重写就添加好了。这样,框架在自动执行该函数时就会将自己添加在这个函数中的代码也会被执行。

  (5) 在DeleteContents中添加如图7所示的加框代码。


图7 在DeleteContents函数中添加的代码

  这就是文档文本内容的整个读取过程。需要说明的是,也可以将"m_strContent.RemoveAll();"语句直接添加在图5中的while循环语句之前,从而可以省略(5)和(6)的步骤。


  文档数据的显示方法和技巧

  用户的视图类是负责显示文档数据的,目前常用的显示方法有三个:一是使用CEditView机制来显示,二是在视图的客户区中使用编辑控件,三是直接调用CDC类的文本输出函数绘制所有的文本内容。下面就来介绍。

  1. 使用CEditView机制

  在MFC文档应用程序中,其内部有一个视图指针列表变量m_viewList,由于CEditView支持文档的序列化,因此我们可以使用下列语句来进行:

((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);

  具体过程如下:

  (1) 在InitInstance函数中,改写框架窗口类、文档类和视图类的关联,如图8所示的加框部分。


图8 在文档模板中改变关联的视图类

  CEditView视图类提供了简单的文本编辑功能,如打印、查找并替换、剪贴板的剪切、复制和粘贴等。

  (2) 在CTextViewerDoc::Serialize函数中添加序列化代码,如图9所示的加框部分。


图9 添加的序列化代码

  (3) 运行程序,打开一个文档,看看是不是可以显示出文档的内容?(显示的内容可能会出现乱码,这是Visual C .NET中的一个BUG)

  评述:这种方法简单有效,并且能够实现文本的编辑功能,缺点是程序中的CTextViewerView类变得没有用了,并且很难进行更深层次的视图控制。


  2. 使用编辑控件

  "编辑控件"是一个可以让用户从键盘输入和编辑文本的控件,通过它可以输入各种文本、数字或者口令,也可使用它来编辑和修改简单的文本内容。MFC类CEdit封装了编辑控件的全部操作。

  使用编辑控件实现文档数据的显示的思路是,先在视图中创建一个与视图客户区大小相同的编辑控件,然后把文档的文本内容转送到编辑控件中。这里的视图客户区是指除了窗口标题栏、菜单栏、工具栏、状态栏以及边框之外的部分。简单地说,就是默认的背景色为白色的区域。

  实现的步骤如下:

  (1) 为CTextViewerView类添加成员变量CEdit* m_ctrlEdit。这是一个指针变量,用"添加成员变量向导"添加时,要在"变量类型"框加输入"CEdit*"(双引号不输入,注意其中的星号),而在"变量名"中输入m_ctrlEdit。

  (2) 为CTextViewerView类添加OnInitialUpdate函数的重写,并添加如图10所示的代码(加框部分)。


图10 在OnInitialUpdate中添加的代码

  new和delete分别用来为类对象分配和释放内存空间。为了避免m_ctrlEdit内存空间重复分配,我们在new操作前,要先将m_ctrlEdit内存空间释放。

  当框架将文档与视图关联,且视图将要显示时调用OnInitialUpdate函数,因此我们将视图的一些初始化代码添加到这里。

  (3) 在CTextViewerView析构函数中添加m_ctrlEdit内存空间释放的语句: if ( m_ctrlEdit ) delete m_ctrlEdit;

  (4) 由于视图大小改变后,编辑控件的大小也应随之改变,因此我们需要跟踪窗口的WM_SIZE消息,只要窗口大小发生改变后,都会发送这个消息。单击CTextViewerView类属性窗口中的"消息"按钮,添加WM_SIZE消息映射。如图11所示。


图11 添加WM_SIZE的消息映射

  (5) 在消息映射函数CTextViewerView::OnSize中添加如图12所示的代码。


图12 在OnSize中添加的代码

  (6) 运行程序,打开当前文件夹下的ReadMe.txt文件,结果如图13所示。


图13 使用编辑控件的文档数据显示结果

  评述:这种方法虽然也比较简单,且具有文本的编辑功能,但文本显示的格式还很单调,例如它的行间距和字间距无法调整,更主要的是视图的绘制功能无法起作用。


  3. 直接控制文本的输出

  图形和文本的绘制需要用到MFC的CDC类,它是一个设备环境类。所谓设备环境,就好比我们写字用的纸那样,显示时指的是屏幕,打印时指的是打印机。实际上,MFC的CDC类还为一些特殊的设备环境提供相应的派生类。例如,CClientDC是一个窗口客户区的设备环境类。

  CDC为我们提供了四个输出文本的函数:TextOut、ExtTextOut、TabbedText

[1] [2] 下一页

教程录入:admin    责任编辑:admin 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
     
     
     
     

    access基础知识
    免责声明!本站资料大部分来自于互联网,其版权归原作者或其他合法者所有.如内容涉及或侵犯了您的权益,请通知本人,我将尽快处理!.欢迎您的光临。
    辽ICP备07003958号
    无师自通,伴你一生-教程网