MFC第5课

5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】

 

我们仍旧开始直接实践:

★相关的知识是文本编程的知识

5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】

 

我们仍旧开始直接实践:

★相关的知识是文本编程的知识

现在用VC6直接实践一下MFC编程:

1、程序类型MFC AppWizard(exe)类型;

2、选择Single Document单文档应用程序

3、完成

 

第一项功能:创建光标(插入符);

可以在视类里面捕获消息CREATE消息:

首先在View类是覆盖在框架类之上的增加捕获wm_create消息:

第一步:增加create消息响应;

对类名右键:New Window Message and Event handlers for class CMainFrame.

 

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       CreateSolidCaret(20,100);

ShowCaret();

 

       return 0;

}

运行即看到插入符,也就是光标;

但是,问题是目前这个插入符的高度是固定的,怎么办?

 

★提醒:文本的信息在MFC里面有一个TEXTMETRIC结构体来组织的;

★注意:两个高度,升序高度和降序高度,例如g这个字母,圆圈的下边缘是base line,这个base line之上是升序高度,之下是降序高度;字体的高度是两个高度之和;

说明: C:\Users\fujitsu\AppData\Roaming\Tencent\Users\1016834241\QQ\WinTemp\RichOle\$FRNHT56OYJ~T)QKTGAVJMI.jpg

 

修改后的代码为:

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       //获得当前文本度量/字体信息

       CClientDC dc(this);

       TEXTMETRIC tm;

       dc.GetTextMetrics(&tm);

       CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);

//为什么要除于8.就是符合现实的高度。

       ShowCaret();

 

       return 0;

}

 

创建图形插入符

注意:CBitmap bitmap;如果是局部变量,那么函数结束时,该资源要被销毁的,还是看不见这个图形插入符;所以这里要增加一个view类的成员变量,私有变量;

当然:首先我们要用insert菜单,增加一个位图bitmap资源,写上一个文字,这个文字你随便写;

 

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       //获得当前文本度量/字体信息

 

       CClientDC dc(this);

       TEXTMETRIC tm;

       dc.GetTextMetrics(&tm);

      

       bitmap.LoadBitmap(IDB_BITMAP1);

       CreateCaret(&bitmap);

 

       ShowCaret();

 

       return 0;

}

 

 

 5课文本编程之二输出文字【参考资料:孙鑫VC++教学视频】

 

算法:

第一步:准备文字;

第二步:输出文字;

程序实例:

第一步:是在View类里面已经有的ondraw函数:

       CString str;   CString是没有基类的。可变长度。

       str="维新科学技术培训中心";

第二步:

       pDC->TextOut(50,50,str);  pDc是参数传递进来的一个指针。这句的含义是输出。

 

 

 

第二项功能:输出文字

可以在视类里面捕获消息DRAW消息:

View类里面已经有ondraw响应函数:

void CTestView::OnDraw(CDC* pDC)

{

       CTestDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

}

 

增加一些代码,简单的输出文字:

void CTestView::OnDraw(CDC* pDC)

{

       CTestDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

 

       //简单输出文字

       CString str;

       str="维新科学技术培训中心";

       pDC->TextOut(50,50,str);

}

 

 

 在左边的菜单里的底下里有resource,看到一个String Table ,双击下,就能看到一些ID号。

在下面空白地方,双击,添加一个新的。

 

★提醒:字符串在MFC里面也是一个资源,我们同样可以通过insert菜单,插入一个字符串资源,然后我们使用这个资源;

在这里:我们insert一个字符串资源,它的IDIDS_WEIXIN;

void CTestView::OnDraw(CDC* pDC)

{

     CTestDoc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     // TODO: add draw code for native data here

     //简单输出文字

 

     //第一步:

     CString str;

     str.LoadString(IDS_WEIXIN);

     //第二步:

     pDC->TextOut(0,200,str);

}

 

 

 

 

5课文本编程之三路径层【参考资料:孙鑫VC++教学视频】

 

 

 

路径层:可以特殊显示某个部分;就相当于军阀割据,在划线里面。都是我的。

当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用SelectClipPath( int nMode )函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。

步骤:

1、打开路径层;CDC::BeginPath();

2、画图,或者输出文字等等;

3、关闭路径层;CDC::EndPath();

 

第三项功能:路径层

可以在视类里面捕获消息DRAW消息:

View类里面已经有ondraw响应函数:

void CTestView::OnDraw(CDC* pDC)

{

      CTestDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      // TODO: add draw code for native data here

      //简单输出文字

 

      CString str;

      str="维新科学技术培训中心";

    pDC->TextOut(50,50,str);

 

      CSize sz=pDC->GetTextExtent(str); 

 

//返回一个CSize对象。和Size的结构体类似。分别表示宽度和高度。每一个字符串都是不一样的。两个ww和两个ii的长度大小是不一样的。

 

这个函数是特定的,获取当前在屏幕上的字符串的信息。

放的位子也要注意的。有特定的。

      str.LoadString(IDS_WEIXIN);

      pDC->TextOut(0,200,str);

 

      pDC->BeginPath();

      pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);

      pDC->EndPath();

 

}

画了一个矩形,放在路径层里面;如果这个矩形不放在路径层里面,会和文字形成叠加,覆盖了文字;

并且由于这个矩形是用白色填充的,所以就看不到文字;

 

下面,我们要画上网格线,横线和竖线,这些网格线不放在路径层里面:

 

      for(int i=0;i<300;i+=10)

      {

         pDC->MoveTo(0,i);

         pDC->LineTo(300,i);  //画横线

         pDC->MoveTo(i,0);

         pDC->LineTo(i,300);  //画竖线

      }

 

路径层最精华的部分出现在下面:

for循环之前增加一句话:

pDC->SelectClipPath(RGN_DIFF);

函数原型为:

BOOL SelectClipPath( int nMode );

这个函数就是路径层的精华了,它的意思是:把当前的路径层作为特殊的一个剪切区域(绘图区域限定在这个区域内)==绘图的区域 显示出来,显示出来的效果由这个函数的参数决定;

 

这里的参数有:

 

RGN_AND The new clipping region includes the intersection (overlapping areas) of the current clipping region and the current path.

此模式只保留显示路径层所有的内容,其余区域消失;

RGN_COPY The new clipping region is the current path.

RGN_DIFF The new clipping region includes the areas of the current clipping region, and those of the current path are excluded.

此模式只显示路径层部分的内容,其余区域不变,类似于“脱颖而出”;

RGN_OR The new clipping region includes the union (combined areas) of the current clipping region and the current path.

RGN_XOR The new clipping region includes the union of the current clipping region and the current path, but without the overlapping areas.

 

 

完整的代码如下:

void CTestView::OnDraw(CDC* pDC)

{

     CTestDoc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     // TODO: add draw code for native data here

     //简单输出文字

 

     CString str;

     str="维新科学技术培训中心";

 

    pDC->TextOut(50,50,str);

 

     CSize sz=pDC->GetTextExtent(str);

     str.LoadString(IDS_WEIXIN);

    

     pDC->TextOut(0,200,str);

 

     pDC->BeginPath();

     pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);

     pDC->EndPath();

 

     pDC->SelectClipPath(RGN_DIFF);

     for(int i=0;i<300;i+=10)

     {

        pDC->MoveTo(0,i);

        pDC->LineTo(300,i);

        pDC->MoveTo(i,0);

        pDC->LineTo(i,300);

     }

 

}

5课文本编程之四字符输入【参考资料:孙鑫VC++教学视频】

 

主要内容是:移动光标、字符输入、删除字符;

 算法思想就是:

1.输入abc ,按照原来,是先输出a后,在a后面输出b,在b后,以b的后面为原点开始输出c

但是这种算法不好。

2.输入a的时候,按照道理,a当做一个char。输入b的时候,把ab整体当做一个整体的char字符串,当输入c的时候,把abc整体当做一个整体的char字符串。然后刷新,然后客户的肉眼就觉得吧,后一次比前一次多了一个字母,会让人觉得,这个字母是后来弹出来的,后来加上去的。从而达到我们的目的。

So 第二种算法好。

 

算法:

第一步:在view类里面增加两个变量;

新点了一个点,就要把旧的那个点的字符串清空。

就出来了一个m_ptOrigin

CString m_strLineCPoint m_ptOrigin

第二步:初始化这两个变量,在view类的构造函数里面:

       m_strLine="";

       m_ptOrigin=0;

第三步:让光标跟随鼠标,在左键响应函数里面:

SetCaretPos(point);//静态的函数,point就是一个点。

 

第四步:编写onchar响应函数,键盘响应函数;

     S1:设定字体;

                  CFont   font;                            //创建一个字体

                    font.CreatePointFont(300,"华文行楷",NULL);  //font对象自己的初始化函数

                    CFont *pOldFont=dc.SelectObject(&font);

     S2:获取字体尺寸信息;

                    CClientDC dc(this);   定义一个DC

                    TEXTMETRIC tm;

                    dc.GetTextMetrics(&tm);  获取字体的高度

     S3:是回车吗?是,转到S4;否则,转到S5

     S4:清空字符串,并设定下一行的位置;

           if(0x0d==nChar)    //如果是回车0x0d

            {

                    m_strLine.Empty();

                    m_ptOrigin.y+=tm.tmHeight;

             }

     S5:是退格键吗?是转到S6;否则,转到S7

     S6:消除一个字符;

退格键的算法:

          S6.1:把整个字符串颜色设置成背景色,相当于消除;

          S6.2:把这个字符串左边(Len-1)个字符再输出一遍;

          S6.3:设定原来的颜色;

             else if(0x08==nChar)

             {

                    //用背景色模拟最后一个字符的消失

                COLORREF clr=dc.SetTextColor(dc.GetBkColor());  //获取背景颜色

            dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);  //输出,坐标就是保存的坐标

                m_strLine=m_strLine.Left(m_strLine.GetLength()-1);  

//减少一个字符。m_strLine.Left比如输入5,就是把字符串的前五个输出来。

                dc.SetTextColor(clr);                          //要把文本设置成原来的颜色。

             }

 

     S7:加入新的字符:m_strLine+=nChar;

     S8:将插入符随着字符而移动;

           S8.1、将光标原位置+字符宽度=光标新位置;

           CSize sz=dc.GetTextExtent(m_strLine);

             CPoint pt;

             pt.x=m_ptOrigin.x+sz.cx;

             pt.y=m_ptOrigin.y;

             SetCaretPos(pt);         //移动到这个点。

     S9、输出文字

           dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

             dc.SelectObject(pOldFont);

     S10、设置原来的字体:

           dc.SelectObject(pOldFont);

     S11、结束;

         

 

第四项功能:字符输入

View增加两个成员变量:

CString m_strLine用于存储当前输入行的内容;

CPoint m_ptOrigin用于保存鼠标移动引起插入符改变时的新行开始位置;

CTestView::CTestView()

{

       // TODO: add construction code here

       m_strLine="";

       m_ptOrigin=0;

}

可以在视类里面捕获消息WM_CHAR消息:

并增加消息响应函数onchar函数:

 

void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

      // TODO: Add your message handler code here and/or call default

     

      CView::OnChar(nChar, nRepCnt, nFlags);

}

 

还增加了一个左键响应函数:

void CTestView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      SetCaretPos(point);

 

      CView::OnLButtonDown(nFlags, point);

}

是为了光标和左键跟随着自由移动;

Onchar响应函数完整的功能:

void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

      // TODO: Add your message handler code here and/or call default

      CClientDC dc(this);

      CFont font;

      font.CreatePointFont(300,"华文行楷",NULL);

      CFont *pOldFont=dc.SelectObject(&font);

      TEXTMETRIC tm;

      dc.GetTextMetrics(&tm);

 

      if(0x0d==nChar)//如果是回车

      {

             m_strLine.Empty();

             m_ptOrigin.y+=tm.tmHeight;

 

      }

      else if(0x08==nChar)

      {

             //用背景色模拟最后一个字符的消失

         COLORREF clr=dc.SetTextColor(dc.GetBkColor());

         dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

         m_strLine=m_strLine.Left(m_strLine.GetLength()-1);

         dc.SetTextColor(clr);

      }

      else

      {

      m_strLine+=nChar;

      }

 

      CSize sz=dc.GetTextExtent(m_strLine);

      CPoint pt;

      pt.x=m_ptOrigin.x+sz.cx;

      pt.y=m_ptOrigin.y;

      SetCaretPos(pt);

      dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

      dc.SelectObject(pOldFont);

 

      CView::OnChar(nChar, nRepCnt, nFlags);

}

 

5课文本编程之五卡拉ok文字变色【参考资料:孙鑫VC++教学视频】

 

主要内容是:卡拉ok中歌词平滑变色,这里我们是想在绿色的文字上覆盖红色的文字;

★★★★★算法:

1:33:05

 

第一步:设置定时器,在viewoncreate响应函数中;

SetTimer(1,100,NULL);              //每隔多少时间,发送一个消息。

第一个参数是,返回值。第二个参数是每隔多少时间。是毫秒单位。第三个是回调函数。

 

第二步:给View类添加WM_TIMER消息响应函数;

第三步:给View添加成员变量int m_nWidth用于保存颜色随时间流逝变化的起点;

第四步:在OnTimer中添加如下代码

     S1:获取字体尺寸信息;

     CClientDC dc(this);

      TEXTMETRIC tm;

      dc.GetTextMetrics(&tm);//获取字体属性

 

     S2:设置变化的矩形;

      m_nWidth+=5;//每次位置增加

      CRect rect(0,200, m_nWidth,200+ tm.tmHeight);

 

     S3:设置文字颜色

      dc.SetTextColor(RGB(255,0,0)); 这里是红色

 

     S4:准备文字

      CString str;

      str.LoadString(IDS_WEIXIN);

 

     S5:输出文字

      dc.DrawText(str,rect,DT_LEFT);

 

     S6:如果矩形的宽度>文字的宽度,则转到S7;否则转到S8

     S7:从头开始变色:

          S7.1:设置矩形宽度为0

          S7.2:设置颜色为绿色,以示区别;

          S7.3:直接输出绿色的文字;

      CSize sz=dc.GetTextExtent(str);

      if(m_nWidth>sz.cx)

      {

             m_nWidth=0;

             dc.SetTextColor(RGB(0,255,0)); // 颜色设为绿色

             dc.TextOut(0,200,str);

      }

     S8:结束

 

 

第五项功能:平滑变色

主要使用函数DrawText

函数原型:

int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );

//lpRect局限在一个矩形范围内。超出这个范围的,都截断不显示。

 

说明:

CDC::TextOut()是一个字母一个字母的输出,达不到平滑效果。

CDC::DrawText():将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。

 

OnTimer响应函数中完整代码:

void CTestView::OnTimer(UINT nIDEvent)

{

      // TODO: Add your message handler code here and/or call default

       

      //S1:获取字体尺寸信息;

      CClientDC dc(this);

      TEXTMETRIC tm; 

  //为了调用tm.tmHeight所以,才用TEXTMETRIC tm 就可以获取文字的高度。

      dc.GetTextMetrics(&tm);//获取字体属性

 

      //S2:设置变化的矩形;

      m_nWidth+=5;//每次位置增加

      CRect rect(0,200, m_nWidth,200+ tm.tmHeight);

 

      //S3:设置文字颜色

      dc.SetTextColor(RGB(255,0,0));

 

      //S4:准备文字

      CString str;

      str.LoadString(IDS_WEIXIN);

 

      //S5:输出文字

      dc.DrawText(str,rect,DT_LEFT);

 

      //这个步骤是y方向150的位置,还有另外的一行文字;

//    rect.top=150;

//    rect.bottom=rect.top+tm.tmHeight;

//    dc.DrawText(str,rect,DT_RIGHT);  

 

// DT_RIGHT从字符串的最右边的字符开始输出,视觉就是浮动的,漂移的字符串,从左边飘出。。。。

 

      //S6:如果矩形的宽度超过文字的宽度,则从头再来;

      CSize sz=dc.GetTextExtent(str);

      if(m_nWidth>sz.cx)

      {

             m_nWidth=0;                  //清零。

             dc.SetTextColor(RGB(0,255,0));    //绿色

             dc.TextOut(0,200,str);

      }

 

      CView::OnTimer(nIDEvent);

}

现在用VC6直接实践一下MFC编程:

1、程序类型MFC AppWizard(exe)类型;

2、选择Single Document单文档应用程序

3、完成

 

第一项功能:创建光标(插入符);

可以在视类里面捕获消息CREATE消息:

首先在View类是覆盖在框架类之上的增加捕获wm_create消息:

第一步:增加create消息响应;

对类名右键:New Window Message and Event handlers for class CMainFrame.

 

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       CreateSolidCaret(20,100);

ShowCaret();

 

       return 0;

}

运行即看到插入符,也就是光标;

但是,问题是目前这个插入符的高度是固定的,怎么办?

 

★提醒:文本的信息在MFC里面有一个TEXTMETRIC结构体来组织的;

★注意:两个高度,升序高度和降序高度,例如g这个字母,圆圈的下边缘是base line,这个base line之上是升序高度,之下是降序高度;字体的高度是两个高度之和;

说明: C:\Users\fujitsu\AppData\Roaming\Tencent\Users\1016834241\QQ\WinTemp\RichOle\$FRNHT56OYJ~T)QKTGAVJMI.jpg

 

修改后的代码为:

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       //获得当前文本度量/字体信息

       CClientDC dc(this);

       TEXTMETRIC tm;

       dc.GetTextMetrics(&tm);

       CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);

//为什么要除于8.就是符合现实的高度。

       ShowCaret();

 

       return 0;

}

 

创建图形插入符

注意:CBitmap bitmap;如果是局部变量,那么函数结束时,该资源要被销毁的,还是看不见这个图形插入符;所以这里要增加一个view类的成员变量,私有变量;

当然:首先我们要用insert菜单,增加一个位图bitmap资源,写上一个文字,这个文字你随便写;

 

int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

       if (CView::OnCreate(lpCreateStruct) == -1)

              return -1;

      

       // TODO: Add your specialized creation code here

       //获得当前文本度量/字体信息

 

       CClientDC dc(this);

       TEXTMETRIC tm;

       dc.GetTextMetrics(&tm);

      

       bitmap.LoadBitmap(IDB_BITMAP1);

       CreateCaret(&bitmap);

 

       ShowCaret();

 

       return 0;

}

 

 

 5课文本编程之二输出文字【参考资料:孙鑫VC++教学视频】

 

算法:

第一步:准备文字;

第二步:输出文字;

程序实例:

第一步:是在View类里面已经有的ondraw函数:

       CString str;   CString是没有基类的。可变长度。

       str="维新科学技术培训中心";

第二步:

       pDC->TextOut(50,50,str);  pDc是参数传递进来的一个指针。这句的含义是输出。

 

 

 

第二项功能:输出文字

可以在视类里面捕获消息DRAW消息:

View类里面已经有ondraw响应函数:

void CTestView::OnDraw(CDC* pDC)

{

       CTestDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

}

 

增加一些代码,简单的输出文字:

void CTestView::OnDraw(CDC* pDC)

{

       CTestDoc* pDoc = GetDocument();

       ASSERT_VALID(pDoc);

       // TODO: add draw code for native data here

 

       //简单输出文字

       CString str;

       str="维新科学技术培训中心";

       pDC->TextOut(50,50,str);

}

 

 

 在左边的菜单里的底下里有resource,看到一个String Table ,双击下,就能看到一些ID号。

在下面空白地方,双击,添加一个新的。

 

★提醒:字符串在MFC里面也是一个资源,我们同样可以通过insert菜单,插入一个字符串资源,然后我们使用这个资源;

在这里:我们insert一个字符串资源,它的IDIDS_WEIXIN;

void CTestView::OnDraw(CDC* pDC)

{

     CTestDoc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     // TODO: add draw code for native data here

     //简单输出文字

 

     //第一步:

     CString str;

     str.LoadString(IDS_WEIXIN);

     //第二步:

     pDC->TextOut(0,200,str);

}

 

 

 

 

5课文本编程之三路径层【参考资料:孙鑫VC++教学视频】

 

 

 

路径层:可以特殊显示某个部分;就相当于军阀割据,在划线里面。都是我的。

当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用SelectClipPath( int nMode )函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。

步骤:

1、打开路径层;CDC::BeginPath();

2、画图,或者输出文字等等;

3、关闭路径层;CDC::EndPath();

 

第三项功能:路径层

可以在视类里面捕获消息DRAW消息:

View类里面已经有ondraw响应函数:

void CTestView::OnDraw(CDC* pDC)

{

      CTestDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      // TODO: add draw code for native data here

      //简单输出文字

 

      CString str;

      str="维新科学技术培训中心";

    pDC->TextOut(50,50,str);

 

      CSize sz=pDC->GetTextExtent(str); 

 

//返回一个CSize对象。和Size的结构体类似。分别表示宽度和高度。每一个字符串都是不一样的。两个ww和两个ii的长度大小是不一样的。

 

这个函数是特定的,获取当前在屏幕上的字符串的信息。

放的位子也要注意的。有特定的。

      str.LoadString(IDS_WEIXIN);

      pDC->TextOut(0,200,str);

 

      pDC->BeginPath();

      pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);

      pDC->EndPath();

 

}

画了一个矩形,放在路径层里面;如果这个矩形不放在路径层里面,会和文字形成叠加,覆盖了文字;

并且由于这个矩形是用白色填充的,所以就看不到文字;

 

下面,我们要画上网格线,横线和竖线,这些网格线不放在路径层里面:

 

      for(int i=0;i<300;i+=10)

      {

         pDC->MoveTo(0,i);

         pDC->LineTo(300,i);  //画横线

         pDC->MoveTo(i,0);

         pDC->LineTo(i,300);  //画竖线

      }

 

路径层最精华的部分出现在下面:

for循环之前增加一句话:

pDC->SelectClipPath(RGN_DIFF);

函数原型为:

BOOL SelectClipPath( int nMode );

这个函数就是路径层的精华了,它的意思是:把当前的路径层作为特殊的一个剪切区域(绘图区域限定在这个区域内)==绘图的区域 显示出来,显示出来的效果由这个函数的参数决定;

 

这里的参数有:

 

RGN_AND The new clipping region includes the intersection (overlapping areas) of the current clipping region and the current path.

此模式只保留显示路径层所有的内容,其余区域消失;

RGN_COPY The new clipping region is the current path.

RGN_DIFF The new clipping region includes the areas of the current clipping region, and those of the current path are excluded.

此模式只显示路径层部分的内容,其余区域不变,类似于“脱颖而出”;

RGN_OR The new clipping region includes the union (combined areas) of the current clipping region and the current path.

RGN_XOR The new clipping region includes the union of the current clipping region and the current path, but without the overlapping areas.

 

 

完整的代码如下:

void CTestView::OnDraw(CDC* pDC)

{

     CTestDoc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     // TODO: add draw code for native data here

     //简单输出文字

 

     CString str;

     str="维新科学技术培训中心";

 

    pDC->TextOut(50,50,str);

 

     CSize sz=pDC->GetTextExtent(str);

     str.LoadString(IDS_WEIXIN);

    

     pDC->TextOut(0,200,str);

 

     pDC->BeginPath();

     pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);

     pDC->EndPath();

 

     pDC->SelectClipPath(RGN_DIFF);

     for(int i=0;i<300;i+=10)

     {

        pDC->MoveTo(0,i);

        pDC->LineTo(300,i);

        pDC->MoveTo(i,0);

        pDC->LineTo(i,300);

     }

 

}

5课文本编程之四字符输入【参考资料:孙鑫VC++教学视频】

 

主要内容是:移动光标、字符输入、删除字符;

 算法思想就是:

1.输入abc ,按照原来,是先输出a后,在a后面输出b,在b后,以b的后面为原点开始输出c

但是这种算法不好。

2.输入a的时候,按照道理,a当做一个char。输入b的时候,把ab整体当做一个整体的char字符串,当输入c的时候,把abc整体当做一个整体的char字符串。然后刷新,然后客户的肉眼就觉得吧,后一次比前一次多了一个字母,会让人觉得,这个字母是后来弹出来的,后来加上去的。从而达到我们的目的。

So 第二种算法好。

 

算法:

第一步:在view类里面增加两个变量;

新点了一个点,就要把旧的那个点的字符串清空。

就出来了一个m_ptOrigin

CString m_strLineCPoint m_ptOrigin

第二步:初始化这两个变量,在view类的构造函数里面:

       m_strLine="";

       m_ptOrigin=0;

第三步:让光标跟随鼠标,在左键响应函数里面:

SetCaretPos(point);//静态的函数,point就是一个点。

 

第四步:编写onchar响应函数,键盘响应函数;

     S1:设定字体;

                  CFont   font;                            //创建一个字体

                    font.CreatePointFont(300,"华文行楷",NULL);  //font对象自己的初始化函数

                    CFont *pOldFont=dc.SelectObject(&font);

     S2:获取字体尺寸信息;

                    CClientDC dc(this);   定义一个DC

                    TEXTMETRIC tm;

                    dc.GetTextMetrics(&tm);  获取字体的高度

     S3:是回车吗?是,转到S4;否则,转到S5

     S4:清空字符串,并设定下一行的位置;

           if(0x0d==nChar)    //如果是回车0x0d

            {

                    m_strLine.Empty();

                    m_ptOrigin.y+=tm.tmHeight;

             }

     S5:是退格键吗?是转到S6;否则,转到S7

     S6:消除一个字符;

退格键的算法:

          S6.1:把整个字符串颜色设置成背景色,相当于消除;

          S6.2:把这个字符串左边(Len-1)个字符再输出一遍;

          S6.3:设定原来的颜色;

             else if(0x08==nChar)

             {

                    //用背景色模拟最后一个字符的消失

                COLORREF clr=dc.SetTextColor(dc.GetBkColor());  //获取背景颜色

            dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);  //输出,坐标就是保存的坐标

                m_strLine=m_strLine.Left(m_strLine.GetLength()-1);  

//减少一个字符。m_strLine.Left比如输入5,就是把字符串的前五个输出来。

                dc.SetTextColor(clr);                          //要把文本设置成原来的颜色。

             }

 

     S7:加入新的字符:m_strLine+=nChar;

     S8:将插入符随着字符而移动;

           S8.1、将光标原位置+字符宽度=光标新位置;

           CSize sz=dc.GetTextExtent(m_strLine);

             CPoint pt;

             pt.x=m_ptOrigin.x+sz.cx;

             pt.y=m_ptOrigin.y;

             SetCaretPos(pt);         //移动到这个点。

     S9、输出文字

           dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

             dc.SelectObject(pOldFont);

     S10、设置原来的字体:

           dc.SelectObject(pOldFont);

     S11、结束;

         

 

第四项功能:字符输入

View增加两个成员变量:

CString m_strLine用于存储当前输入行的内容;

CPoint m_ptOrigin用于保存鼠标移动引起插入符改变时的新行开始位置;

CTestView::CTestView()

{

       // TODO: add construction code here

       m_strLine="";

       m_ptOrigin=0;

}

可以在视类里面捕获消息WM_CHAR消息:

并增加消息响应函数onchar函数:

 

void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

      // TODO: Add your message handler code here and/or call default

     

      CView::OnChar(nChar, nRepCnt, nFlags);

}

 

还增加了一个左键响应函数:

void CTestView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      SetCaretPos(point);

 

      CView::OnLButtonDown(nFlags, point);

}

是为了光标和左键跟随着自由移动;

Onchar响应函数完整的功能:

void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

      // TODO: Add your message handler code here and/or call default

      CClientDC dc(this);

      CFont font;

      font.CreatePointFont(300,"华文行楷",NULL);

      CFont *pOldFont=dc.SelectObject(&font);

      TEXTMETRIC tm;

      dc.GetTextMetrics(&tm);

 

      if(0x0d==nChar)//如果是回车

      {

             m_strLine.Empty();

             m_ptOrigin.y+=tm.tmHeight;

 

      }

      else if(0x08==nChar)

      {

             //用背景色模拟最后一个字符的消失

         COLORREF clr=dc.SetTextColor(dc.GetBkColor());

         dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

         m_strLine=m_strLine.Left(m_strLine.GetLength()-1);

         dc.SetTextColor(clr);

      }

      else

      {

      m_strLine+=nChar;

      }

 

      CSize sz=dc.GetTextExtent(m_strLine);

      CPoint pt;

      pt.x=m_ptOrigin.x+sz.cx;

      pt.y=m_ptOrigin.y;

      SetCaretPos(pt);

      dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);

      dc.SelectObject(pOldFont);

 

      CView::OnChar(nChar, nRepCnt, nFlags);

}

 

5课文本编程之五卡拉ok文字变色【参考资料:孙鑫VC++教学视频】

 

主要内容是:卡拉ok中歌词平滑变色,这里我们是想在绿色的文字上覆盖红色的文字;

★★★★★算法:

1:33:05

 

第一步:设置定时器,在viewoncreate响应函数中;

SetTimer(1,100,NULL);              //每隔多少时间,发送一个消息。

第一个参数是,返回值。第二个参数是每隔多少时间。是毫秒单位。第三个是回调函数。

 

第二步:给View类添加WM_TIMER消息响应函数;

第三步:给View添加成员变量int m_nWidth用于保存颜色随时间流逝变化的起点;

第四步:在OnTimer中添加如下代码

     S1:获取字体尺寸信息;

     CClientDC dc(this);

      TEXTMETRIC tm;

      dc.GetTextMetrics(&tm);//获取字体属性

 

     S2:设置变化的矩形;

      m_nWidth+=5;//每次位置增加

      CRect rect(0,200, m_nWidth,200+ tm.tmHeight);

 

     S3:设置文字颜色

      dc.SetTextColor(RGB(255,0,0)); 这里是红色

 

     S4:准备文字

      CString str;

      str.LoadString(IDS_WEIXIN);

 

     S5:输出文字

      dc.DrawText(str,rect,DT_LEFT);

 

     S6:如果矩形的宽度>文字的宽度,则转到S7;否则转到S8

     S7:从头开始变色:

          S7.1:设置矩形宽度为0

          S7.2:设置颜色为绿色,以示区别;

          S7.3:直接输出绿色的文字;

      CSize sz=dc.GetTextExtent(str);

      if(m_nWidth>sz.cx)

      {

             m_nWidth=0;

             dc.SetTextColor(RGB(0,255,0)); // 颜色设为绿色

             dc.TextOut(0,200,str);

      }

     S8:结束

 

 

第五项功能:平滑变色

主要使用函数DrawText

函数原型:

int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );

//lpRect局限在一个矩形范围内。超出这个范围的,都截断不显示。

 

说明:

CDC::TextOut()是一个字母一个字母的输出,达不到平滑效果。

CDC::DrawText():将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。

 

OnTimer响应函数中完整代码:

void CTestView::OnTimer(UINT nIDEvent)

{

      // TODO: Add your message handler code here and/or call default

       

      //S1:获取字体尺寸信息;

      CClientDC dc(this);

      TEXTMETRIC tm; 

  //为了调用tm.tmHeight所以,才用TEXTMETRIC tm 就可以获取文字的高度。

      dc.GetTextMetrics(&tm);//获取字体属性

 

      //S2:设置变化的矩形;

      m_nWidth+=5;//每次位置增加

      CRect rect(0,200, m_nWidth,200+ tm.tmHeight);

 

      //S3:设置文字颜色

      dc.SetTextColor(RGB(255,0,0));

 

      //S4:准备文字

      CString str;

      str.LoadString(IDS_WEIXIN);

 

      //S5:输出文字

      dc.DrawText(str,rect,DT_LEFT);

 

      //这个步骤是y方向150的位置,还有另外的一行文字;

//    rect.top=150;

//    rect.bottom=rect.top+tm.tmHeight;

//    dc.DrawText(str,rect,DT_RIGHT);  

 

// DT_RIGHT从字符串的最右边的字符开始输出,视觉就是浮动的,漂移的字符串,从左边飘出。。。。

 

      //S6:如果矩形的宽度超过文字的宽度,则从头再来;

      CSize sz=dc.GetTextExtent(str);

      if(m_nWidth>sz.cx)

      {

             m_nWidth=0;                  //清零。

             dc.SetTextColor(RGB(0,255,0));    //绿色

             dc.TextOut(0,200,str);

      }

 

      CView::OnTimer(nIDEvent);

}

你可能感兴趣的:(MFC)