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

📄 chap7_2.htm

📁 VC++编程实例。非常详细
💻 HTM
📖 第 1 页 / 共 5 页
字号:
        <p><font >ASSERT_VALID(pDoc);</font></p>
        <p><font >// TODO: add draw code for native data
        here</font></p>
        <p><font >CFont *oldFont;</font></p>
        <p><font >//选择新字体</font></p>
        <p><font >oldFont=pDC-&gt;SelectObject(pFont);</font></p>
        <p><font >//纵向yval坐标为0</font></p>
        <p><font >int yval=0;</font></p>
        <p><font >POSITION pos;</font></p>
        <p><font >CString line;</font></p>
        <p><font >//取得文本行链表的头指针</font></p>
        <p><font >if(!(pos=pDoc-&gt;lines.GetHeadPosition()))</font></p>
        <p><font >{</font></p>
        <p><font >return;</font></p>
        <p><font >}</font></p>
        <p><font >//循环输出各文本行</font></p>
        <p><font >while(pos!=NULL)</font></p>
        <p><font >{</font></p>
        <p><font >line=pDoc-&gt;lines.GetNext(pos);</font></p>
        <p><font >pDC-&gt;TextOut(0,</font></p>
        <p><font >yval,</font></p>
        <p><font >line,</font></p>
        <p><font >line.GetLength());</font></p>
        <p><font >//更新y坐标值,让它加上文本行所用字体的高度</font></p>
        <p><font >yval+=lHeight;</font></p>
        <p><font >}</font></p>
        <p><font >//恢复原来DC所用的字体</font></p>
        <p><font >pDC-&gt;SelectObject(pFont);</font></p>
        <p><font >}</font></p>
          <p><font >  框架调用视图的CView::OnDraw(CDC* pDC)方法完成屏幕显示、打印、打印预览功能,对于不同的输出功能它会传递不同的DC指针给OnDraw()函数。</font></p>
          <p><font >  在OnDraw()函数中,首先调用GetDocument()函数,取得指向当前视图所对应的文档的指针。通过这个指针,来访问文档中的数据。以后在视图中修改文档中的数据,也是通过GetDocument()来取得文档指针,再通过该文档指针修改文档中的数据。</font></p>
          <p><font >  在绘图时,可以通过传给OnDraw函数的一个设备上下文DC的指针pDC进行GDI调用。开始绘图之前,往往需要选择GDI资源(或GDI对象,包括画笔、刷子、字体等),将它选入到设备上下文中。在文本编辑器中,我们选择一种字体pFont到设备上下文中,以后在窗口客户区的文本输出就都会使用该字体绘制。在绘制过程中,绘图代码是设备无关的,也就是说它并不需要知道目前使用的是什么设备(屏幕、打印机或其他绘图设备)。</font></p>
          <p><font >  读者以前如果用Borland C++或SDK编写过Windows程序的话,都会知道:当窗口或窗口的一部分变成无效的话(比如其他窗口从本窗口上拖过、窗口调整大小等),操作系统就会向窗口发送一条WM_PAINT消息。窗口接收到该消息之后,调用Borland 
            C++的EvPaint()或Visual C++的OnPaint()完成窗口绘制工作。这里OnDraw()函数也同样完成窗口绘图输出,这两者有什么关系呢?</font></p>
        <p><font >我们先看一下OnPaint()函数:</font></p>
        <p><font >void CMyWindow::OnPaint()</font></p>
        <p><font >{</font></p>
        <p><font >CPaintDC dc(this); //用于窗口绘制的设备上下文</font></p>
        <p><font >CString str(“Hello,world!”);</font></p>
        <p><font >...</font></p>
        <p><font >//绘图输出代码</font></p>
        <p><font >dc.TextOut(10,10,str,str.GetLength());</font></p>
        <p><font >}</font></p>
          <p><font >  在OnPaint()函数中,首先创建一个CPaintDC类的对象dc。CPaintDC必需也只能用在WM_PAINT消息处理中。在CPaintDC类对象dc的构造函数中,调用了在SDK下需要显式调用的BeginPaint函数,取得处理WM_PAINT消息时所需的设备上下文。然后OnPaint()函数使用该设备上下文完成各种输出。在OnPaint()函数退出时,dc对象被删除。在dc对象的析构函数中,包含了对EndPaint函数的调用。EndPaint一方面释放设备上下文,另一方面还从应用消息队列中删除WM_PAINT消息。如果在处理WM_PAINT时不使用CPaintDC,则WM_PAINT不被消除,会产生不断重画的现象。</font></p>
          <p><font >  视图是一个子窗口,它自然也从窗口类继承了OnPaint()成员函数,用以响应WM_PAINT消息。类似于上面的例子,视图OnPaint处理函数首先创建一个与显示器相匹配的CPaintDC类的设备上下文对象dc,但是OnPaint不再直接完成窗口输出,而是将设备上下文传给OnDraw()成员函数,由OnDraw()函数去完成窗口输出。当打印输出时,框架会调用视图的DoPreparePrinting创建一个与打印机相匹配的设备上下文并将该DC传递给OnDraw()函数,由OnDraw函数完成打印输出。这样,OnDraw()函数就把用于屏幕显示和打印机输出的工作统一起来,真正体现了设备无关的思想。如果想知道当前OnDraw函数是在用于屏幕显示还是打印输出,可以调用CView::IsPrinting()函数。当处于打印状态时,IsPrinting()返回TRUE;在用于屏幕显示时,返回FALSE。</font></p>
        <p><font color="#3973DE" >文档修改时通知视图的更新</font></p>
          <p><font >  当文档以某种方式变化时,必须通知视图作相应的更新即重绘,以反应文档的变化。这种情况通常发生在用户通过视图修改文档时。此时,视图将调用文档的UpdateAllViews成员函数通知同一文档的所有视图对自己进行更新。UpdateAllViews将调用每个视图的OnUpdate成员函数,使视图的客户区无效。</font></p>
        <p><font color="#3973DE">5 视图的消息处理</font></p>
          <p><font >  视图作为一个子窗口,当然可以处理消息。但是应用程序运行时,除了视图外,还有应用程序对象、主框架窗口、文档等,它们都是可以处理消息的。那么消息传递过程是什么样的呢?</font></p>
        <p><font >MFC的命令消息按以下方式传递:</font></p>
        <p align="center"><img src="T7_9.gif"
        alt="T7_9.tif (83342 bytes)" width="473" height="130"></p>
        <p align="center"><font >图7-9
        文档视结构中的消息传递</font></p>
        <p><font color="#3973DE" >键盘消息处理</font></p>
          <p><font >  前面的视图绘制就是完成窗口消息WM_PAINT的处理。编辑器要接收用户的键盘输入,就必须处理键盘消息;另外,在用户输入字符时,还必须马上就把用户输入的内容在屏幕上显示出来。</font></p>
        <p><font >用ClassWizard生成处理WM_CHAR消息的函数OnChar(),然后打开该函数进行编辑。修改后的OnChar函数如清单7.9:</font></p>
        <p><font >清单7.9 CEditorView的OnChar()成员函数</font></p>
        <p><font >void CEditorView::OnChar(UINT nChar,
        UINT nRepCnt, UINT nFlags)</font></p>
        <p><font >{</font></p>
        <p><font >CEditorDoc* pDoc=GetDocument();</font></p>
        <p><font >CClientDC dc(this);</font></p>
        <p><font >CFont *oldFont;</font></p>
        <p><font >//选择新字体</font></p>
        <p><font >oldFont=dc.SelectObject(pFont);</font></p>
        <p><font >CString line(&quot;&quot;);//存放编辑器当前行字符串</font></p>
        <p><font >POSITION pos=NULL;//字符串链表位置指示</font></p>
        <p><font >if(nChar=='\r')</font></p>
        <p><font >{</font></p>
        <p><font >pDoc-&gt;nLineNum++;</font></p>
        <p><font >}</font></p>
        <p><font >else</font></p>
        <p><font >{</font></p>
        <p><font >//按行号返回字符串链表中位置值</font></p>
        <p><font >pos=pDoc-&gt;lines.FindIndex(pDoc-&gt;nLineNum);</font></p>
        <p><font >if(!pos)</font></p>
        <p><font >{</font></p>
        <p><font >//没有找到该行号对应的行,因此它是一个空行,</font></p>
        <p><font >//我们把它加到字符串链表中。</font></p>
        <p><font >line+=(char)nChar;</font></p>
        <p><font >pDoc-&gt;lines.AddTail(CString(line));</font></p>
        <p><font >}</font></p>
        <p><font >else{</font></p>
        <p><font >//当前文本行还没有换行结束,因此将文本加入到行末</font></p>
        <p><font >line=pDoc-&gt;lines.GetAt(pos);</font></p>
        <p><font >line+=(char)nChar;</font></p>
        <p><font >pDoc-&gt;lines.SetAt(pos,line);</font></p>
        <p><font >}</font></p>
        <p><font >TEXTMETRIC tm;</font></p>
        <p><font >dc.GetTextMetrics(&amp;tm);</font></p>
        <p><font >dc.TextOut(0,</font></p>
        <p><font >(int)pDoc-&gt;nLineNum*tm.tmHeight,</font></p>
        <p><font >line,</font></p>
        <p><font >line.GetLength());</font></p>
        <p><font >}</font></p>
        <p><font >pDoc-&gt;SetModifiedFlag();</font></p>
        <p><font >dc.SelectObject(oldFont);</font></p>
        <p><font >CView::OnChar(nChar,nRepCnt,nFlags);</font></p>
        <p><font >}</font></p>
          <p><font >  因为编辑器要将用户输入内容加入到文本行缓冲区中,因此首先调用GetDocument()获取指向文档的指针,以便对文档中的数据进行修改。</font></p>
          <p><font >  为了在收到键盘输入消息后在窗口中输入字符,需要定义一个CClientDC类的对象dc。CClientDC是用于管理窗口客户区的设备上下文对象,它在构造函数中调用GetDC()取得窗口客户区设备上下文,在析构函数中调用ReleaseDC()释放该设备上下文。CClientDC同样用于在窗口客户区的输出,它与CPaintDC不同之处在于:</font></p>
        <p><font >CPaintDC专门用于在窗口OnPaint()中的输出,而不能用于其它非窗口重画消息的处理。如果不是在OnDraw或OnPaint()中绘图,则需要创建一个CClientDC对象,然后调用CClientDC的方法来完成绘图输出。</font></p>
          <p><font >  OnChar()接下去处理用户输入。如果输入是一个回车,则将总行数nLineNum加一,否则将输入字符加到当前行行末。最后调用TextOut函数输出当前编辑中的文本行。</font></p>
          <p><font >  最后调用文档的SetModifiedFlag()方法设置文档的修改标志。SetModifiedFlag()函数原型如下:</font></p>
        <blockquote>
            <blockquote>
                <p><font >void SetModifiedFlag( BOOL
                bModified = TRUE );</font></p>
            </blockquote>
        </blockquote>
          <p><font >  从函数原型可以看出,函数缺省参数为TRUE。当调用SetModifiedFlag时,将文档内的修改标志置为真。如果用户执行了Save或Save 
            As操作,则将文档的修改标志置为假。这样,当用户关闭文档的最后一个视图时,框架根据该修改标记决定是否提示用户保存文档中的数据到文件。如果用户上次作了修改还没有存盘,则弹出一个消息框,提示是否保存文件。这些都是框架程序来完成的。</font></p>
          <p><font >  用户如果在视图的其它任何地方修改了文档,也必须调用SetModifiedFlag来设置文档修改标记,以便关闭窗口时让框架提示保存文档。</font></p>
        <p><font color="#3973DE" >菜单消息处理 </font></p>
 

⌨️ 快捷键说明

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