VC++大文档的分页显示

 

VC++大文档的分页显示

关键字:大文档  分页显示  RichEdit
1.问题提出
通常的大文件处理有三种方法,内存映射处理、分段读写处理、多线程读写处理。本文就较大的文本文档的分页处理提供了一个范例。分页显示在网上找不到解决方法,连CodeProject也没有相关文章介绍,笔者在网上得到一点线索经过研究,终于完成了此功能,当然还存在写不足,我将这些不足留在本文最后,希望有经验的读者能给我提供一些指导。

2.问题难点
(1)如何分页  
MFC没有提供现成的View类支持分页操作,网上有人说高版本的RichEdit控件支持自动分页,但是我至今还没找到。
(2)如何读取大文档数据 
大文档的读写很是麻烦,对于每一页如果读取太少则分页过多造成资源浪费;如果分页每一页显示过多则每一页会出现滚动条,达不到WORD WPS PDF等主流产品的阅读效果,用户体验不佳。动态计算每个页面容量是个大问题,通常的计算方法总会有偏差,很难保证无误。
(3)如何管理分页
提供分页支持就必须管理每一页的显示、更新、滚动浏览等其他 用户操作。
3.问题解决
(1)如何添加支持分页的视类
要支持分页滚动,就必须派生自己的类来支持,本例从CScrollView派生自定义的 CPagingDemoView类。
(2)如何管理分页
采用链表数据结构,根据动态分页生成的每一页加入链表来管理,链表定义之前须由 CObject派生自己的模板类 CRichCtrObj,该类实际上即为每一页显示提供支持。链表定义如下:
typedef CTypedPtrList<CObList, CRichCtrObj*>  CRichCtrList;
(3)如何定构每一页
分页显示的每一页必须支持动态创建、显示页码、页眉、边框等其他操作。因此需由显示控件派生自定义的显示控件,本例从 CRichEditCtrl派生自定义的CRichEditCtrlEx,支持这些操作。更为重要的分页后的内存管理工作,动态分配的每一页必须具备良好的内存管理,否则将会造成内存耗尽。
以上三个类的设计如下图所示:
VC++大文档的分页显示_第1张图片
(4)如何读取数据
对于大文档来说,读取数据必须开启新的线程来做,否则用户界面由于等待数据处理时间过长则造成无响应的后果,用户体验不佳。在读取数据的同时,动态生成每一页,并填充数据。因为在主线程中创建的界面控件在新建线程中无法修改(实验证明),因此需通过发送消息的方法来完成。要完成这些功能需要定义一些消息如下:
#define APP_CREATELABEL  WM_USER+1       // CRichEditCtrlEx对象创建页码
#define APP_STREAMDATA  WM_USER+2       // CPagingDemoView开启读取数据线程
#define APP_CREATECTRL  WM_USER+3      // CPagingDemoView创建每一页的CRichEditCtrlEx对象
#define APP_WRITEDATA   WM_USER+4        //CPagingDemoView每一页 CRichEditCtrlEx对象读取数据
读取数据的流程如下图所示:

(5)如何滚动文档
滚动统一由窗口处理,则每一页 CRichEditCtrlEx对象的滚动消息将路由给窗口处理。路由过程如下代码所示:
void CRichEditCtrlEx::OnMouseHWheel(UINT nFlags, short zDelta, CPoint pt)
{
    int nDist = abs(zDelta)/WHEEL_DELTA+1;
   while ( nDist-- )
   { 
      //窗口管理滚动
      GetParent()->GetParent()->PostMessage(WM_VSCROLL, zDelta > 0 ? SB_LINEUP : SB_LINEDOWN);
   }
    CRichEditCtrl::OnMouseHWheel(nFlags, zDelta, pt);
}
4.分页显示运行效果
  分页效果图1: VC++大文档的分页显示_第2张图片
分页效果图2:

5.尚未解决的问题
(1)界面线程和后台数据线程设计还不够合理,打开文档显示过程稍慢。
(2)页面滚动量超过32767时滚动出现异常,虽然网上有一些文字介绍这种问题,但还没解决。
(3)分页后的打印和打印预览尚未完善。

你可能感兴趣的:(VC++大文档的分页显示)