⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chap7_3.htm

📁 着重介绍基于C++的web编程技术
💻 HTM
📖 第 1 页 / 共 3 页
字号:
    <p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">其实,我们在前面介绍弹出式菜单时已经使用了</font><font FACE="Times New Roman" SIZE="3">ClientToScreen</font><font SIZE="3">函数。在那里,由于弹出式菜单使用的是屏幕坐标,因此当处理弹出式菜单快捷键</font><font FACE="Times New Roman" SIZE="3">shift+F10</font><font SIZE="3">时,如果要在窗口左上角</font><font FACE="Times New Roman" SIZE="3">(5,5)</font><font SIZE="3">处显示快捷菜单,就必须先调用</font><font FACE="Times New Roman" SIZE="3">ClientToScreen</font><font SIZE="3">函数将客户区坐标(</font><font FACE="Times New Roman" SIZE="3">5,5</font><font SIZE="3">)转化为屏幕坐标。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>CRect rect;</p>
    <p>GetClientRect(rect);</p>
    <p>ClientToScreen(rect);</p>
    <p>point = rect.TopLeft();</p>
    <p>point.Offset(5, 5);</p>
    <p></font><font SIZE="3">在视图滚动后,如果用户在视图中单击鼠标,那么会得到鼠标位置的设备(视图)坐标。在使用这个数据处理文档(比如画点或画线)时,需要把它转化为文档坐标。这是因为利用</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">绘图时,所有传递给</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">作图的坐标都是逻辑坐标。当调用</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">绘图函数绘图时,</font><font FACE="Times New Roman" SIZE="3">Windows</font><font SIZE="3">自动将逻辑坐标转换成设备坐标,然后再绘图。设备上下文类</font><font FACE="Times New Roman" SIZE="3">CDC</font><font SIZE="3">提供了两个成员函数</font><font FACE="Times New Roman" SIZE="3">LPToDP</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">DPToLP</font><font SIZE="3">完成逻辑坐标和设备坐标之间的转换工作。如其名字所示那样,</font><font FACE="Times New Roman" SIZE="3">LPToDP</font><font SIZE="3">将逻辑坐标转换为设备坐标,</font><font FACE="Times New Roman" SIZE="3">DPToLP</font><font SIZE="3">将设备坐标转换为逻辑坐标。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>void LPtoDP( LPPOINT lpPoints, int nCount = 1 ) const;</p>
    <p>void LPtoDP( LPRECT lpRect ) const;</p>
    <blockquote>
      <blockquote>
        <p>void LPtoDP( LPSIZE lpSize ) const;</p>
        <p>void DPtoLP( LPPOINT lpPoints, int nCount = 1 ) const;</p>
        <p>void DPtoLP( LPRECT lpRect ) const;</p>
        <p>void DPtoLP( LPSIZE lpSize ) const;</p>
        </font><p> </p>
      </blockquote>
    </blockquote>
    <font SIZE="3"><b><p></b><font color="#3973DE">7.3.2 滚动文档</font></p>
    </font><font FACE="Times New Roman" SIZE="3"><p></font><font SIZE="3">由于</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">绘图函数使用的是逻辑坐标,因此用户可以在一个假想的通常是比视图要大的“文档窗口”中绘图;</font><font FACE="Times New Roman" SIZE="3">Windows</font><font SIZE="3">自动在幕后完成坐标转换工作,并将落在视图范围内的那一部分“文档窗口”显示出来,其余的部分被裁剪。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">但是光这样还不能卷滚文档。要卷滚显示文档,还必须知道文档卷滚到了什么位置;一旦用户拖动滚动条时要告诉视图改变在文档中的相应位置。所有这些,由</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">来完成。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>MFC</font><font SIZE="3">提供了</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">类,简化了滚动需要处理的大量工作。除了管理文档中的滚动操作外,</font><font FACE="Times New Roman" SIZE="3">MFC</font><font SIZE="3">还通过调用</font><font FACE="Times New Roman" SIZE="3">Windows API</font><font SIZE="3">函数画出滚动条、箭头和滚动光标。它还负责处理:</p>
    <blockquote>
      <p>用户初始化滚动条范围</font><font FACE="Times New Roman" SIZE="3">(</font><font SIZE="3">通过滚动视图的</font><font FACE="Times New Roman" SIZE="3">SetScrollRange()</font><font SIZE="3">方法</font><font FACE="Times New Roman" SIZE="3">)</p>
      </font><font SIZE="3"><p>处理滚动条消息,并滚动文档到相应位置</p>
      <p>管理窗口和视图的尺寸大小</p>
      <p>调整滚动条上滑块(或称拇指框)的位置,使之与文档当前位置相匹配</font></p>
    </blockquote>
    <p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">程序员要做的工作是:</p>
    <blockquote>
      <p>从</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">类中派生出自己的视图类,以支持卷滚</p>
      <p>提供文档大小,确定滚动范围和设置初始位置</p>
      <p>协调文档位置和屏幕坐标</font></p>
    </blockquote>
    <p><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">要让应用程序支持卷滚,可以在用</font><font FACE="Times New Roman" SIZE="3">AppWizard</font><font SIZE="3">生成框架程序时就指定视图的基类为</font><font FACE="Times New Roman" SIZE="3">CSrollView</font><font SIZE="3">。可以在</font><font FACE="Times New Roman" SIZE="3">AppWizard</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">MFC AppWizard-Step 6 of 6</font><font SIZE="3">对话框中,在对话框上方应用程序所包含的类中选择</font><font FACE="Times New Roman" SIZE="3">CEditorView</font><font SIZE="3">,然后在</font><font FACE="Times New Roman" SIZE="3">Base Class</font><font SIZE="3">下拉列表框中选择应用程序视图类的基类为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">,如图</font><font FACE="Times New Roman" SIZE="3">7-11</font><font SIZE="3">所示:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p align="center"></font><img src="T7_13.gif" alt="T7_13.tif (317268 bytes)" WIDTH="504" HEIGHT="405"><font FACE="Times New Roman" SIZE="3"></p>
    <p align="center"></font><font SIZE="3">图</font><font FACE="Times New Roman" SIZE="3">7-13 
    </font><font SIZE="3">为应用程序的视图类指定基类</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">现在我们要手工修改</font><font FACE="Times New Roman" SIZE="3">CEditorView</font><font SIZE="3">,使它的基类为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>1. </font><font SIZE="3">修改视图类所对应的头文件,将所有用到</font><font FACE="Times New Roman" SIZE="3">CView</font><font SIZE="3">的地方改为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">。通常,首先修改视图类赖以派生的父类,形式如下:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>class CEditorView:public CScrollView</p>
    <p>2. </font><font SIZE="3">修改视图类实现的头文件,把所有用到</font><font FACE="Times New Roman" SIZE="3">CView</font><font SIZE="3">的地方改为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">。首先修改</font><font FACE="Times New Roman" SIZE="3">IMPLEMENT_DYNACREATE</font><font SIZE="3">一行:</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>IMPLEMENT_DYNACREATE(CEditorView,CScrollView)</p>
    <p></font><font SIZE="3">然后修改</font><font FACE="Times New Roman" SIZE="3">BEGIN_MESSAGE_MAP</font><font SIZE="3">宏</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>BEGIN_MESSAGE_MAP(CEditorView,CScrollView)</p>
    <p></font><font SIZE="3">然后将其他所有用到</font><font FACE="Times New Roman" SIZE="3">CView</font><font SIZE="3">的地方改为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">一个更简单的方法是:使用</font><font FACE="Times New Roman" SIZE="3">Edit-Replace</font><font SIZE="3">功能,进行全局替换。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">到现在为止,已经将编辑器视图类</font><font FACE="Times New Roman" SIZE="3">CEditorView</font><font SIZE="3">的基类由</font><font FACE="Times New Roman" SIZE="3">CView</font><font SIZE="3">转化为</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">现在,要设置文档大小,以便让</font><font FACE="Times New Roman" SIZE="3">CScrollView</font><font SIZE="3">知道该如何处理文档。视图必需知道文档的卷滚范围,这样才能确定何时卷滚到文档的头部和尾部,以及当拖动卷滚条的滑块时按适当比例调整文档当前显示位置。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">为此,我们首先在文档类</font><font FACE="Times New Roman" SIZE="3">CEditorDoc</font><font SIZE="3">的头文件</font><font FACE="Times New Roman" SIZE="3">editordoc.h</font><font SIZE="3">中增加一个</font><font FACE="Times New Roman" SIZE="3">CSize</font><font SIZE="3">类型的数据成员</font><font FACE="Times New Roman" SIZE="3">m_sizeDoc</font><font SIZE="3">用以表示文档的大小。</font><font FACE="Times New Roman" SIZE="3">CSize</font><font SIZE="3">对象包含</font><font FACE="Times New Roman" SIZE="3">cx</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">cy</font><font SIZE="3">两个数据成员,分别用于存放文档的</font><font FACE="Times New Roman" SIZE="3">x</font><font SIZE="3">方向坐标范围和</font><font FACE="Times New Roman" SIZE="3">y</font><font SIZE="3">方向坐标范围。另外,还要提供一个成员函数</font><font FACE="Times New Roman" SIZE="3">GetDocSize()</font><font SIZE="3">来访问该文档大小范围数据成员。修改后的</font><font FACE="Times New Roman" SIZE="3">editordoc.h</font><font SIZE="3">如清单</font><font FACE="Times New Roman" SIZE="3">7.11</font><font SIZE="3">。<b></p>
    <p>清单</font><font FACE="Times New Roman" SIZE="3">7.11 CEditorDoc</font><font SIZE="3">头文件</font></b><font FACE="Times New Roman" SIZE="3"></p>
    <p>class CEditorDoc : public CDocument</p>
    <p>{</p>
    <p>protected: // create from serialization only</p>
    <p>CEditorDoc();</p>
    <p>DECLARE_DYNCREATE(CEditorDoc)</p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>//</font><font SIZE="3">保存文档大小</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>CSize m_sizeDoc;</p>
    <p>// Attributes</p>
    <p>public:</p>
    <p>CSize GetDocSize(){return m_sizeDoc;}</p>
    <p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>// Operations</p>
    <p>public:</p>
    <p>CStringList lines;</p>
    <p>int nLineNum;</b></p>
    <p>......</p>
    <p>};</p>
    <p></font><font SIZE="3">既然增加了</font><font FACE="Times New Roman" SIZE="3">m_sizeDoc</font><font SIZE="3">这一数据成员,就需要在</font><font FACE="Times New Roman" SIZE="3">CEditorDoc</font><font SIZE="3">构造函数中进行初始化,给</font><font FACE="Times New Roman" SIZE="3">m_sizeDoc</font><font SIZE="3">设置一合理的数值,比如说</font><font FACE="Times New Roman" SIZE="3">x=700</font><font SIZE="3">,</font><font FACE="Times New Roman" SIZE="3">y=800</font><font SIZE="3">。构造函数如清单</font><font FACE="Times New Roman" SIZE="3">7.12</font><font SIZE="3">。<b></p>
    <p>清单</font><font FACE="Times New Roman" SIZE="3">7.12 CEditorDoc</font><font SIZE="3">的构造函数</font></b><font FACE="Times New Roman" SIZE="3"></p>
    <p>CEditorDoc::CEditorDoc()</p>
    <p>{</p>
    <p>// TODO: add one-time construction code here</p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>nLineNum=0;</p>
    <p>m_sizeDoc=CSize(700,800);</b></p>
    <p>}</p>
    <p></font><font SIZE="3">一个设计优秀的应用程序应当能够动态调整文档的卷滚范围。比如,在</font><font FACE="Times New Roman" SIZE="3">WORD</font><font SIZE="3">中新建一个文件时,在“页面模式”下将可卷滚范围设为一页大小。随着用户输入,逐渐增加文档的卷滚范围。但是这里为简明起见,将文档卷滚范围设为固定大小</font><font FACE="Times New Roman" SIZE="3">700X800</font><font SIZE="3">点像素大小。设置文档大小通过由视图类的</font><font FACE="Times New Roman" SIZE="3">CEditorView::OnInitialUpdate()</font><font SIZE="3">调用</font><font FACE="Times New Roman" SIZE="3">SetScrollSizes()</font><font SIZE="3">成员函数来完成。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>SetScrollSizes()</font><font SIZE="3">用于设置文档卷滚范围。一般在重载</font><font FACE="Times New Roman" SIZE="3">OnInitialUpdate()</font><font SIZE="3">成员函数或</font><font FACE="Times New Roman" SIZE="3">OnUpdate()</font><font SIZE="3">时调用该函数,用以调整文档卷滚特性。比如,在文档初始显示或文档大小作了调整之后。<b></p>
    <p>清单</font><font FACE="Times New Roman" SIZE="3">7.13 </font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">OnInitialUpdate()</font><font SIZE="3">中设置卷滚范围</font></b><font FACE="Times New Roman" SIZE="3"></p>
    <p>void CEditorView::OnInitialUpdate() </p>
    <p>{</p>
    <p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>// TODO: Add your specialized code here and/or call the base class</p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>CDC *pDC=GetDC();</p>
    <p>pFont=new CFont();</p>
    <p>if(!(pFont-&gt;CreateFont(0,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,</p>
    <p>ANSI_CHARSET,OUT_TT_PRECIS,CLIP_TT_ALWAYS,</p>
    <p>DEFAULT_QUALITY,DEFAULT_PITCH,&quot;Courier New&quot;)))</p>
    <p>{</p>
    <p>pFont-&gt;CreateStockObject(SYSTEM_FONT);</p>
    <p>}</p>
    <p>CFont* oldFont=pDC-&gt;SelectObject(pFont);</p>
    <p>TEXTMETRIC tm;</p>
    <p>pDC-&gt;GetTextMetrics(&amp;tm);</p>
    <p>lHeight=tm.tmHeight+tm.tmExternalLeading;</p>
    <p>cWidth=tm.tmAveCharWidth;</p>
    <p>SetScrollSizes(MM_TEXT,GetDocument()-&gt;GetDocSize());</b></p>
    <p>CScrollView::OnInitialUpdate();</p>
    <p>}</p>
    <p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>SetScrollSizes()</font><font SIZE="3">第一个参数为映射模式。</font><font FACE="Times New Roman" SIZE="3">SetScrollSizes()</font><font SIZE="3">可以使用除</font><font FACE="Times New Roman" SIZE="3">MM_ISOTROPIC</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">MM_ANISOTROPIC</font><font SIZE="3">之外的其他任何映射模式。</font><font FACE="Times New Roman" SIZE="3">SetScrollSizes()</font><font SIZE="3">第二个参数为文档大小,用一个</font><font FACE="Times New Roman" SIZE="3">CSize</font><font SIZE="3">类型的数值表示。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p></font><font SIZE="3">另外,我们还要检查两个包含绘图输出功能的函数:</font><font FACE="Times New Roman" SIZE="3">CEditorView::OnChar()</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">CEditorView::OnDraw()</font><font SIZE="3">函数。</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>void CEditorView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) </p>
    <p>{</p>
    <p></font><b><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
    <p>CEditorDoc* pDoc=GetDocument();</p>
    <p>CClientDC dc(this);</p>
    <p>CString line(&quot;&quot;);//</font><font SIZE="3">存放编辑器当前行字符串</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>POSITION pos=NULL;//</font><font SIZE="3">字符串链表位置指示</font><font FACE="Times New Roman" SIZE="3"></p>
    <p>if(nChar=='\r')</p>
    <p>{</p>
    <p>pDoc-&gt;nLineNum++;</p>
    <p>}</p>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -