norains的专栏

只专注于WINCE开发

用户操作
[即时聊天] [发私信] [加为好友]
norains
norains的公告
联系方式请看置顶文章
最近评论
晴天:請問一下:
如果要寫成Watchdog timer 納在這這要如何實現呢?
hustpanda:电子书看不了呢?
bobo:“耍大牌”...... 你就该直接拉黑
bulrush:你好,首先先感谢一下。我看了你的音量控制,自己也去实现了一下,但是我个人感觉“AudioUpdateFromRegistry”没有依据注册表的设置来更新控制面板的音量。没有马上更新,我重启系统后才看到更新的结果。也就是说这种方法是可行,但是必须要重启,显然这不合理。上面的兄弟说:引用了这两个类后不起作用
如:
void CSoundDlg::OnSoft()
……
manyanxinlv:尽管我还小 但是 我还是看看
文章分类
收藏
    相册
    动漫
    文章图片
    程序交流
    xumercury的BLOG
    狗友们的博客
    清蒸石斑鱼
    美女如刀锋
    茁茁的BLOG
    魅力老姐的窝
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 文字滚动的技术实现收藏

    新一篇: CTextWnd轻松实现文字的滚动 | 旧一篇: 汉之云通关评析

    //========================================================================
    //TITLE:
    //    文字滚动的技术实现
    //AUTHOR:
    //    norains
    //DATE:
    //    Wednesday  27-February-2008
    //Environment:
    //    VS2005  + SDK-WINCE5.0-MIPSII
    //    EVC 4.0 + SDK-WINCE5.0-MIPSII
    //========================================================================

        在WinCE平台下,使用evc或vs2005写出文字滚动的代码并不是一件难事,甚至可以说非常简单。
       
        大体上来说,程序的失败与否取决于两个关键点:
       
        1.准确计算文本的长度以及宽度;
       
        2.定时刷新窗口。
       
        现在我们来看看这两点分别有什么注意的地方。
       
        首先是计算文本的长度。
       
        其实要做到这点也并非难事,因为WinCE给我们一个现成的函数:GetTextExtentPoint。
       
        函数的原型和解释如下:
       
      BOOL GetTextExtentPoint(
                              HDC hdc,
                              LPCTSTR lpString,
                              int cbString,
                              LPSIZE lpSize
                              );
                             
      hdc
        [in] Handle to the device context (DC).
     
      lpString
        [in] Long pointer to the string of text. The string does not need to be zero-terminated because cbString specifies the length of the string.

      cbString
        [in] Integer that specifies the number of characters in the string.

      lpSize
        [out] Long pointer to a SIZE structure that receives the dimensions of the string.
       
       
        我们需要注意的是lpString形参的解释:The string does not need to be zero-terminated because cbString specifies the length of the string。 翻译为中文的大概的意思是,字符串不需要以0为结尾,因为你可以在cbString形参定义字符串的长度。那么,如果我们以0为结尾又如何呢?该函数会不会自动计算?cbString也没有正式表明如果该值为-1则自动计算。也许你现在的环境依次设置可能会计算出正确的长度,但并不代表以后WinCe的版本甚至是不同CPU环境下也有相同的表现,所以我建议,以在cbString传入字符串个数的方式。
       
        现在我们先来看两段代码:
       
        SIZE size1 = {0};
        GetTextExtentPoint(hdc,TEXT("无换行"),_tcslen(TEXT("无换行")),&size1);
       
        SIZE size2 = {0};
        GetTextExtentPoint(hdc,TEXT("有换行\n\r第二行"),_tcslen(TEXT("有换行\n\r第二行")),&size2);
       
        直觉是不是告诉你,这代码应该为真: size2.cy > size1.cy ?
       
        但事实确实无情的,因为 size2.cy == size1.cy !
       
        也就是说,GetTextExtentPoint是将“TEXT("有换行\n\r第二行")”这个字符串当成一行来计算!所以,如果你想编写一段上移或下移的代码,你无法直接通过该函数获取其所需的高度。
       
        换个角度想,虽然GetTextExtentPoint获取的仅仅是一行的高度,但我们却可以自行判断有多少行,然后再用行数相乘每行的高度不就是所需要的总高度了么?
       
        例如:
        //Get the amount of the "\n"
      TCHAR *pFind = m_pszTxtInfo;
      int iCountLine = 1;
      while(TRUE)
      {
       pFind = _tcsstr(pFind,TEXT("\n"));
       
       if(pFind != NULL)
       {
        pFind += 1;
        iCountLine ++;
       }
       else
       {
        break;
       }
      }
      //所需要的总高度
      m_iTxtInfoHeight = size.cy * iCountLine;

     

        接下来的另一个难点就是采用什么方式刷新文字。
       
        不必说,最基本的自然是首先创建一个线程,然后在该线程中刷新文字。但,采用什么方式来刷新呢?
       
        熟悉SDK编码的朋友都不会陌生,我们可以调用DrawText来绘制文本。也许大家对该函数的lpRect形参比较感兴趣,因为该形参定义了绘制的坐标。一个很自然的想法是,我们在线程中不停调整坐标,然后再强制窗口重绘。
       
        举个简单的例子:
       
        线程代码:
       
        //右移一像素
        m_rcDraw.left += 1;
        //强制重绘
        InvalidateRect(m_hWnd,NULL,FALSE)
       
        在WM_PAINT响应消息中加入如下代码:
        DrawText(hdc,pszText,-1,&m_rcDraw,uFormat);
       
        很简单,也很方便,是不是?但其实这样做有一个问题被我们忽略了,就是调用DrawText耗费的时间!一段不过二十个字的字符串,调用该函数耗费的时间是调用BitBlt的三倍!更不用说绘制一个文本文件的内容了!
       
        我们再换另外一个角度来想,既然调用BitBlt的速度远远比DrawText的快,那么我们为何不先创建一个内存DC,然后在这DC中调用DrawText初始化文本,最后在使用的使用再将该DC绘制到目标DC中去呢?
       
        接下来的问题就出来了,这内存DC应该在哪里创建?大小如何确定?前面我们已经提到,如何计算显示文本的总宽度和总高度,现在这两个数值就能派上用场了。因为我们的内存DC主要是存储文本,所以我们的内存DC的长高完全可以用文本的总宽度和总高度。
       
        所以,在计算完毕文本所需要的区域大小后,我们可以马上创建内存DC:
       
      //Create the memory DC
     CMemDC memDC;
     SIZE size = {m_iTxtInfoWidth,m_iTxtInfoHeight};
     memDC.Create(hdc,&size);
     DrawText(memDC.GetDC(),pszText,-1,&m_rcDraw,uFormat);
     
        接下来我们只需要在WM_PAINT的处理函数中将该DC按坐标绘制出来即可:
        BitBlt(memDC.GetDC(),
          m_rcDraw.left,
          m_rcDraw.top,
          m_iTxtInfoWidth,
          m_iTxtInfoHeight,
          m_DCTxtInfo.GetDC(),
          0,
          0
          SRCCOPY);
          

        只要解决这两个关键问题,文字的滚动并不是一件非常困难的事情。
       
        在我另一篇《CTextWnd轻松实现文字的滚动》文章中,封装了一个CTextWnd窗口类,能够简便地实现文字的滚动,有兴趣的朋友可以参考。 

    发表于 @ 2008年02月27日 21:21:00|评论(loading...)|编辑

    新一篇: CTextWnd轻松实现文字的滚动 | 旧一篇: 汉之云通关评析

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © norains