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