




已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
让文档视结构程序支持卷滚但是,编辑器现在还不支持卷滚。当文本行超过窗口大小时,窗口并不自动向上滚动以显示输入的字符。当打开一个文件时,如果文件大小超过窗口大小,也无法通过卷滚视图来看文档的全部内容。现在我们要让编辑器增加卷滚功能。7.3.1逻辑坐标和设备坐标在引入文档卷滚功能之前,首先要介绍以下逻辑坐标和设备坐标这两个重要概念。在Windows中,文档坐标系称作逻辑坐标系,视图坐标系称为设备坐标系。它们之间的关系如下图所示:图7-11文档坐标和视图坐标逻辑坐标按照坐标设置方式(又成为映射模式)可分为8种,它们在坐标上的特性如下表所示:表7-1 各种映射模式下的坐标转换方式映射模式逻辑单位x递增方向y递增方向MM_TEXT像素向右向下MM_LOMETRIC0.1mm向右向上MM_HIMETRIC0.01mm向右向上MM_LOENGLISH0.01inch向右向上MM_HIENGLISH0.001inch向右向上MM_TWIPS1/1440inch向右向上MM_ISOTROPIC可调整 (x=y)可选择可选择MM_ANISOTROPIC可调整(x!=y)可选择可选择我们一般使用的映射模式是MM_TEXT,它也是缺省设置。在该模式下,坐标原点在工作区左上角,而x坐标值是向右递增,y坐标值是向下递增,单位值1代表一个像素。要设置映射模式,可以调用CDC:SetMapMode()函数。CClientDC dc;nPreMapMode=dc.SetMapMode(nMapMode);它将映射模式设置为nMapMode,并返回前一次的映射模式nPreMapMode,GetMapMode可取得当前的映射模式:CClientDC dc;nMapMode=dc.GetMapMode();MFC绘图函数都使用逻辑坐标作为位置参数。比如CString str(“Hello,world!”);dc.TextOut(10,10,str,str.GetLength();这里的(10,10)是逻辑坐标而不是像素点数(只是在缺省映射模式MM_TEXT下,正好与像素点相对应),在输出时GDI函数会将逻辑坐标(10,10)依据当前映射模式转化为“设备坐标”,然后将文字输出在屏幕上。设备坐标以像素点为单位,且x轴坐标值向右递增,y轴坐标值向下递增,但原点(0,0)位置却不限定在工作区的左上角。依据设备坐标的原点和用途,可以将Windows下使用的设备坐标系统分为三种:工作区坐标系统,窗口坐标系统和屏幕坐标系统。(1)工作区坐标系统:工作区坐标系统是最常见的坐标系统,它以窗口客户区左上角为原点(0,0),主要用于窗口客户区绘图输出以及处理窗口的一些消息。鼠标消息WM_LBUTTONDOWN、WM_MOUSEMOVE传给框架的消息参数以及CDC一些用于绘图的成员都是使用工作区坐标。(2)屏幕坐标系统:屏幕坐标系统是另一类常用的坐标系统,以屏幕左上角为原点(0,0)。以CreateDC(“DISPLAY” , .)或GetDC(NULL)取得设备上下文时,该上下文使用的坐标系就是屏幕坐标系。一些与窗口的工作区不相关的函数都是以屏幕坐标为单位,例如设置和取得光标位置的函数SetCursorPos()和GetCursorPos();由于光标可以在任何一个窗口之间移动,它不属于任何一个单一的窗口,因此使用屏幕坐标。弹出式菜单使用的也是屏幕坐标。另外,CreateWindow、MoveWindow、SetWindowPlacement()等函数用于设置窗口相对于屏幕的位置,使用的也是屏幕坐标系统。(3)窗口坐标系统:窗口坐标系统以窗口左上角为坐标原点,它包含了窗口控制菜单、标题栏等内容。一般情况下很少在窗口标题栏上绘图,因此这种坐标系统很少使用。三类设备坐标系统关系如下图所示:图7-12. 三类设备坐标MFC提供ClientToScreen()、ScreenToClient()两个函数用于完成工作区坐标和屏幕坐标之间的转换工作。void ScreenToClient( LPPOINT lpPoint ) const;void ScreenToClient( LPRECT lpRect ) const;void ClientToScreen( LPPOINT lpPoint ) const;void ClientToScreen( LPRECT lpRect ) const;其实,我们在前面介绍弹出式菜单时已经使用了ClientToScreen函数。在那里,由于弹出式菜单使用的是屏幕坐标,因此当处理弹出式菜单快捷键shift+F10时,如果要在窗口左上角(5,5)处显示快捷菜单,就必须先调用ClientToScreen函数将客户区坐标(5,5)转化为屏幕坐标。CRect rect;GetClientRect(rect);ClientToScreen(rect);point = rect.TopLeft();point.Offset(5, 5);在视图滚动后,如果用户在视图中单击鼠标,那么会得到鼠标位置的设备(视图)坐标。在使用这个数据处理文档(比如画点或画线)时,需要把它转化为文档坐标。这是因为利用MFC绘图时,所有传递给MFC作图的坐标都是逻辑坐标。当调用MFC绘图函数绘图时,Windows自动将逻辑坐标转换成设备坐标,然后再绘图。设备上下文类CDC提供了两个成员函数LPToDP和DPToLP完成逻辑坐标和设备坐标之间的转换工作。如其名字所示那样,LPToDP将逻辑坐标转换为设备坐标,DPToLP将设备坐标转换为逻辑坐标。void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;void LPtoDP( LPRECT lpRect ) const;void LPtoDP( LPSIZE lpSize ) const;void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;void DPtoLP( LPRECT lpRect ) const;void DPtoLP( LPSIZE lpSize ) const;7.3.2 滚动文档由于MFC绘图函数使用的是逻辑坐标,因此用户可以在一个假想的通常是比视图要大的“文档窗口”中绘图;Windows自动在幕后完成坐标转换工作,并将落在视图范围内的那一部分“文档窗口”显示出来,其余的部分被裁剪。但是光这样还不能卷滚文档。要卷滚显示文档,还必须知道文档卷滚到了什么位置;一旦用户拖动滚动条时要告诉视图改变在文档中的相应位置。所有这些,由MFC的CScrollView来完成。MFC提供了CScrollView类,简化了滚动需要处理的大量工作。除了管理文档中的滚动操作外,MFC还通过调用Windows API函数画出滚动条、箭头和滚动光标。它还负责处理:用户初始化滚动条范围(通过滚动视图的SetScrollRange()方法)处理滚动条消息,并滚动文档到相应位置管理窗口和视图的尺寸大小调整滚动条上滑块(或称拇指框)的位置,使之与文档当前位置相匹配程序员要做的工作是:从CScrollView类中派生出自己的视图类,以支持卷滚提供文档大小,确定滚动范围和设置初始位置协调文档位置和屏幕坐标要让应用程序支持卷滚,可以在用AppWizard生成框架程序时就指定视图的基类为CSrollView。可以在AppWizard的MFC AppWizard-Step 6 of 6对话框中,在对话框上方应用程序所包含的类中选择CEditorView,然后在Base Class下拉列表框中选择应用程序视图类的基类为CScrollView,如图7-11所示:图7-13 为应用程序的视图类指定基类现在我们要手工修改CEditorView,使它的基类为CScrollView。1. 修改视图类所对应的头文件,将所有用到CView的地方改为CScrollView。通常,首先修改视图类赖以派生的父类,形式如下:class CEditorView:public CScrollView2. 修改视图类实现的头文件,把所有用到CView的地方改为CScrollView。首先修改IMPLEMENT_DYNACREATE一行:IMPLEMENT_DYNACREATE(CEditorView,CScrollView)然后修改BEGIN_MESSAGE_MAP宏BEGIN_MESSAGE_MAP(CEditorView,CScrollView)然后将其他所有用到CView的地方改为CScrollView。一个更简单的方法是:使用Edit-Replace功能,进行全局替换。到现在为止,已经将编辑器视图类CEditorView的基类由CView转化为CScrollView。现在,要设置文档大小,以便让CScrollView知道该如何处理文档。视图必需知道文档的卷滚范围,这样才能确定何时卷滚到文档的头部和尾部,以及当拖动卷滚条的滑块时按适当比例调整文档当前显示位置。为此,我们首先在文档类CEditorDoc的头文件editordoc.h中增加一个CSize类型的数据成员m_sizeDoc用以表示文档的大小。CSize对象包含cx和cy两个数据成员,分别用于存放文档的x方向坐标范围和y方向坐标范围。另外,还要提供一个成员函数GetDocSize()来访问该文档大小范围数据成员。修改后的editordoc.h如清单7.11。清单7.11 CEditorDoc头文件class CEditorDoc : public CDocumentprotected: / create from serialization onlyCEditorDoc();DECLARE_DYNCREATE(CEditorDoc)/保存文档大小CSize m_sizeDoc;/ Attributespublic:CSize GetDocSize()return m_sizeDoc;/ Operationspublic:CStringList lines;int nLineNum;.;既然增加了m_sizeDoc这一数据成员,就需要在CEditorDoc构造函数中进行初始化,给m_sizeDoc设置一合理的数值,比如说x=700,y=800。构造函数如清单7.12。清单7.12 CEditorDoc的构造函数CEditorDoc:CEditorDoc()/ TODO: add one-time construction code herenLineNum=0;m_sizeDoc=CSize(700,800);一个设计优秀的应用程序应当能够动态调整文档的卷滚范围。比如,在WORD中新建一个文件时,在“页面模式”下将可卷滚范围设为一页大小。随着用户输入,逐渐增加文档的卷滚范围。但是这里为简明起见,将文档卷滚范围设为固定大小700X800点像素大小。设置文档大小通过由视图类的CEditorView:OnInitialUpdate()调用SetScrollSizes()成员函数来完成。SetScrollSizes()用于设置文档卷滚范围。一般在重载OnInitialUpdate()成员函数或OnUpdate()时调用该函数,用以调整文档卷滚特性。比如,在文档初始显示或文档大小作了调整之后。清单7.13 在OnInitialUpdate()中设置卷滚范围void CEditorView:OnInitialUpdate() / TODO: Add your specialized code here and/or call the base classCDC *pDC=GetDC();pFont=new CFont();if(!(pFont-CreateFont(0,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_TT_PRECIS,CLIP_TT_ALWAYS,DEFAULT_QUALITY,DEFAULT_PITCH,Courier New)pFont-CreateStockObject(SYSTEM_FONT);CFont* oldFont=pDC-SelectObject(pFont);TEXTMETRIC tm;pDC-GetTextMetrics(&tm);lHeight=tm.tmHeight+tm.tmExternalLeading;cWidth=tm.tmAveCharWidth;SetScrollSizes(MM_TEXT,GetDocument()-GetDocSize();CScrollView:OnInitialUpdate();SetScrollSizes()第一个参数为映射模式。SetScrollSizes()可以使用除MM_ISOTROPIC和MM_ANISOTROPIC之外的其他任何映射模式。SetScrollSizes()第二个参数为文档大小,用一个CSize类型的数值表示。另外,我们还要检查两个包含绘图输出功能的函数:CEditorView:OnChar()和CEditorView:OnDraw()函数。void CEditorView:OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) CEditorDoc* pDoc=GetDocument();CClientDC dc(this);CString line();/存放编辑器当前行字符串POSITION pos=NULL;/字符串链表位置指示if(nChar=r)pDoc-nLineNum+;else/按行号返回字符串链表中位置值pos=pDoc-lines.FindIndex(pDoc-nLineNum);if(!pos)/没有找到该行号对应的行,因此它是一个空行,/我们把它加到字符串链表中。line+=(char)nChar;pDoc-lines.AddTail(CString(line);else/there is a line,so add the incoming char to the end of/the lineline=pDoc-lines.GetAt(pos);line+=(char)nChar;pDoc-lines.SetAt(pos,line);TEXTMETRIC tm;dc.GetTextMetrics(&tm);dc.TextOut(0,(int)pDoc-nLineNum*tm.tmHeight,line,line.GetLength();pDoc-SetModifiedFlag();SetScrollSizes(MM_TEXT,GetDocument()-GetDocSize();CScrollView:OnChar(nChar,nRepCnt,nFlags);在程序运行开始的时侯,视图坐标原点和文档坐标原点是重合的。但是,当用户拖动滚动条时,视图原点就与文档原点不一致了,如图7-14。由于GDI是按照文档坐标(逻辑坐标)来输出图形的,这样自然就无法正确显示文档内容。图7-14 文档滚动前后文档坐标原点和视图坐标原点的变化这时,要想获得正确输出,就必须调整视图坐标,让视图坐标原点和文档坐标原点重合,如图7-15所示。图7-15 调整视图设备上下文原点后CScrollView视图类提供了一个CScrollView:OnPrepareDC()成员函数,完成视图设备上下文坐标原点的调整工作。现在修改OnChar(),加入OnPrepareDC()函数,见清单7.15。清单7.15 修改后的OnChar成员函数void CEditorView:OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) CEditorDoc* pDoc=GetDocument();CClientDC dc(this);OnPrepareDC(&dc);CFont* pOldFont=dc.SelectObject(pFont); CString line();/存放编辑器当前行字符串POSITION pos=NULL;/字符串链表位置指示if(nChar=r)pDoc-nLineNum+;else/按行号返回字符串链表中位置值pos=pDoc-lines.FindIndex(pD
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025湖北襄阳市中医医院(襄阳市中医药研究所)招聘急需专业技术人才55人模拟试卷及参考答案详解一套
- 2025喀什地区两级法院机关招聘聘用制书记员(43人)考前自测高频考点模拟试题带答案详解
- 2025贵州铜仁市妇幼保健院引进专业技术人才考前自测高频考点模拟试题附答案详解(模拟题)
- 2025年六安阳光电力维修工程有限责任公司招聘85人考前自测高频考点模拟试题及参考答案详解
- 2025河南郑州高新区双桥社区卫生服务中心招聘3人考前自测高频考点模拟试题及答案详解(历年真题)
- 2025河南洛阳市东方人民医院招聘39人考前自测高频考点模拟试题及答案详解(各地真题)
- 2025广东中山市西区集体资产经营有限公司招聘1人考前自测高频考点模拟试题及答案详解(网校专用)
- 2025贵州毕节医学高等专科学校第一批次“人才强市”暨高层次急需紧缺人才引进考前自测高频考点模拟试题带答案详解
- IL-6-IN-3-生命科学试剂-MCE
- Hydroxyfasudil-hydrochloride-Standard-生命科学试剂-MCE
- 2025年安全工程师《安全生产管理》考前模拟卷(一)
- 综合实践 记录我们的校园(教案)北师大版数学三年级上册
- 第4课 探究智慧农业应用领域 课件【教科版】《信息科技》八年级上册
- 《信息系统安全》课程教学大纲
- 2024年青海省行政执法资格考试备考题库及答案(题型)
- 无人机航拍课件
- 2025-2026学年第一学期校园“1530”安全教育记录表
- 压力性损伤的分期及护理
- 2025支付宝财经内容生态报告
- 35kv变电运维协议合同
- 中文大模型基准测评2025年上半年报告-SuperCLUE团队
评论
0/150
提交评论