正文

第五课 文本2007-09-23 14:03:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/lym51/29610.html

分享到:

第五课 文本

一、与文本有关的知识点:

1.  WM_CHAR消息:

用户按动一下某个键,系统将发出WM_KEYDOWN, WM_KEYUP,并且参数中提供该键的虚拟扫描码。但有时用户按下某个键, 只想得到一条表示用户输入了某个字符的消息,TranslateMessageWM_KEYDOWN, WM_KEYUP消息对转换成一条WM_CHAR消息,并在消息补充参数中提供该字符的编码。

2.  CString 类:

 在MFC中将对字符串的操作都封装在Cstring类中,用它来操作字符串特别方便。这一课我们要用到的是:

 Empty():  将字符串的内容清空。

 Left():   取字符串的左面几个字符串。

 Format(): 得到一个格式化字符串,它的功能象C语言中的sprintf();

           如: CString str = "Some Data";

str.Format("%s%d", str, 123);  //str现在的值是”SomData123”

二、 文字处理:

1.  Cview类中加入WM_CHAR消息的处理函数OnChar,在其中加入代码:

CClientDC dc(this);

CString str;

dc.TextOut(0,0,str);

这时,只能打出一个字符,因为str是局部变量,将它改为成员变量:

     CString m_strInput;

2.  加入自定义字体:

     CFont fn;

    fn.CreatePointFont(200,"楷体");

  dc.SelectObject(&fn);

其中,CreatePointFont 是产生字体最简单的方法,它的第二个参数是字体的名字,具体你的系统中装了哪些字体,可以打开记事本,在其中的“格式”――“字体”中查到。

3.  设置文字颜色:

dc.SetTextColor(RGB(0,0,255));// 设置文字颜色为红色

4.  加入光标:

a.     CView类中加入WM_CREATE消息的处理函数OnCreate,当窗口产生之后,会发出WM_CREATE消息,如果想让窗口一产生,就拥有光标,就应在OnCreate中加入代码。

  CreateSolidCaret(100,100);//产生一个100象素*100象素大小的实心光标

    ShowCaret();       //显示光标

      注意: WM_CREATE消息只是代表窗口刚刚产生,此时窗口还不可见,因此在OnCreate中不能调用那些依赖于窗口完全激活状态的Windows函数。如:GetClientRect()

b.     调整光标的大小与字体相适应:

   CClientDC dc(this);

      CFont fn;

    fn.CreatePointFont(200,"楷体");

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

    dc.SelectObject(&fn);

    TEXTMETRIC tm;          

    dc.GetTextMetrics(&tm);         //得到DC中当前的字体信息

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

//根据当前的大小产生光标

      ShowCaret();          //显示光标

c.     产生位图光标:

bmp.LoadBitmap(IDB_BITMAP1);  //bmp定义为成员变量,

//IDB_BITMAP1为事先在资源面板中做好的位图的ID

    CreateCaret(&bmp);       //产生位图光标

ShowCaret();          //显示光标

d.     调整光标位置,在OnChar 中加入:

  CPoint pt(tm.tmAveCharWidth*m_strInput.GetLength(),0);

     //用平均字符宽度*字符个数来得到字符串长度

SetCaretPos(pt);        //设置光标位置

这种方法对于有些字体可以,有些字体不可以,会发生光标不在字符末尾的现象,因为在有些字体中,字符宽度并不一样,如W很宽,l很窄。

上段代码改为:

  CSize sz=dc.GetTextExtent(m_strInput); //得到字符串的大小

  CPoint pt(sz.cx,0) ;         //用得到的字符串的长度设置

  SetCaretPos(pt);            //光标位置

5.  处理回车键:

a.     定义成员变量,用于记录字符串的输出位置。

         CPoint  m_ptOrigin;                 //一定要在构造函数中赋初值

b.     OnChar中加入代码:

  if('\15'==nChar)            //如果输入的是回车键

    {

        m_ptOrigin.x =0;

        m_ptOrigin.y += tm.tmHeight;    //将输出字符串的位置加一行

        m_strInput.Empty();         //清空字符串

    }

    else

        m_strInput += nChar;

    CSize sz=dc.GetTextExtent(m_strInput);

    CPoint pt(sz.cx,m_ptOrigin.y);

    SetCaretPos(pt);

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

6.处理退格键:

 if(8==nChar)

  {

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

                  //将文字颜色设置为背景色

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

         //用背景色将字符串再输出一遍,相当于将字符串擦去

      dc.SetTextColor(oldclr);

                  //将文字颜色设置为正常颜色

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

                  //将字符串最后的一个字符去掉

  }

  else if(15==nChar)

   ………………

      ………………

三、 模拟卡拉OK

1.  OnDraw函数:

OnDrawCView 类中的一个虚成员函数,当用户改变了窗口尺寸,或者当窗口恢复了先前被遮盖的部分,应用程序框架都会自动调用OnDraw函数。所以如果在OnDraw函数中加入绘制代码,得到的效果将是绘制的图形在窗口发生改变时还在。

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

  {

      pDC->MoveTo(0,i);

      pDC->LineTo(300,i);

      pDC->MoveTo(i,0);

      pDC->LineTo(i,300);

}

将上面的代码加入OnDraw中,它绘制了由横、竖三十根线组成的网格,而且在窗口改变时不会消失。

2.  在绘制网格之前输出字符:

  CString str1;

    str1.LoadString(IDS_MYSTRING);   

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

其中LoadString的作用是装入一个在资源面板中的String Table 中定义的字符串资源,IDS_MYSTRING是这个字符串资源的ID。使用字符串资源的好处是,可以不修改代码而改变字符的内容。

这时运行程序,会发现先输出的文字被后绘制的网格穿过。

3.  用剪切区保护文字不被网格穿过:

DC中有一个剪切区的概念,在剪切区中的内容将被保护起来,不被后来的绘制操作破坏。产生剪切区有两种方法:

a.     CRgn 来产生剪切区:

CSize sz=pDC->GetTextExtent(str);   //得到字符串的大小信息

  CRgn rn;

    rn.CreateRectRgn(0,50,sz.cx,sz.cy); //产生一个区域覆盖输出的字符串

    pDC->SelectClipRgn(&rn,RGN_DIFF);   //根据区域产生剪切区

b.     Path来产生剪切区:

DC中还有一个路径的概念,在BeginPath()函数和EndPath()函数之间DC上的笔所经过的路线定义了一条路径,可以通过路径来产生剪切区。需要特别强调的是:路径和区域不同,一个DC只对应一条路径。

   pDC->BeginPath();          //开始记录一条路径

    pDC->Rectangle(0,50,sz.cx,sz.cy);    //DC上笔所经过的路线写入路径

    pDC->EndPath();                      //结束记录路径

    pDC->SelectClipPath(RGN_DIFF);       //由路径产生剪切区

4.  模拟卡拉OK的文字输出效果:

a.     OnCreate中,生成定时器。

     SetTimer(1,100,NULL);

其中:

第一个参数是产生的定时器的标识号,一个窗口上可以安装多个定时器,我们可以用一个数字来标识产生的是几号定时器。

第二个参数是产生的定时器的时间间隔(毫秒),当规定的时间间隔到来时,系统会向消息队列里发送一个WM_TIMER消息。

第三个参数是一个指向定时器回调函数的指针。当应用程序取到WM_TIMER消息时就会执行这个函数。如果这个参数赋为NULL,取到WM_TIMER消息时就会定义在窗口中的函数。

        b. CView 中加入成员变量 int m_nIndex,用于记录矩形的边界。

    c.CView 中加入WM_TIMER消息的处理函数OnTimer,在其中加入代码:

    CString str;

    str.LoadString(IDS_MYSTRING);

    CClientDC dc(this);

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

    CRect rect;

    rect.top=50;

    rect.left=0;

    CSize sz=dc.GetTextExtent(str);

    rect.bottom=50+sz.cy;

    rect.right=m_nIndex++;

    dc.DrawText(str,&rect,DT_LEFT);

    if(m_nIndex>sz.cx)

    {

        m_nIndex=0;

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

        dc.TextOut(0,90,str);

    }

说明:

上面的代码利用DrawText函数来实现卡拉OK逐步变色的效果(用上面讲的剪切区也可以实现)。DrawText函数用于在一个矩形范围内输出文本,如果文本长度大于矩形宽度,超出的部分将被裁剪掉。

我们在OnDraw中输出了一次IDS_MYSTRING标识的字符串,在OnTimer中,将文字颜色设置为另一种颜色,然后用DrawText函数在原来的位置再输出一次字符串,开始在一个小矩形上输出,每调用一次OnTimer,矩形的宽度变大一点,所得到的效果就是文字在一点一点的变色,模拟了卡拉OK的逐渐变色的效果。

阅读(4993) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册