蓝色恋枫

愿风指引你的到来。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

最近刚好做了一个文本滚动的功能,怕忘记,就先记下来了。

当你需要把一大段文本显示在一个固定的区域的时候,就需要实现滚动,才能将文本全部显示出来。首先,我们需要计算出一次性画出文本所需要的区域大小,怎么样计算呢?我们要用到一个win32 api

BOOL GetTextExtentPoint(
HDC hdc,
LPCTSTR lpString,
int cbString,
LPSIZE lpSize
);

那我们开始写代码,

SIZE size;

GetTextExtentPoint( hdc, string,lstrlen( string ),&size);

size返回的是文本string 在hdc上显示的尺寸,size.cx是长度,size.cy是高度,这里的话,高度其实就是一个字符显示在hdc上的高度。

我的文本滚动的主要实现是,先将所有的文本全部画进一个内存DC,然后再设置一个timer定时刷新需要显示文本的区域,再将内存DC中的文本一点点画到目标hdc上。

关键在于创建的内存DC的大小,这里就要用到了刚刚得到的size 结构体。

比如你需要将文本画到hdc上的一个rect里,由于我实现的是向上滚动,所以内存DC的宽度就是rect.right-rect.left,下面就是计算高度,下面是代码,

int nTextLine = size.cx/( rect.right-rect.left );// 这里是计算相对于rect的宽度,文本一共需要多少行,因为文本显示到边缘处,是要换行的。

不过不要忘记,除了这种情况会换行,文本里面还有很多\n,也是换行,这个行数也是要计算上,

int iCountLine = 0;

TCHAR *pFind = string;//定义一个指针指向文本开头。

while(1)

{

     pFind = _tcsstr( pFind,_T("\n"));\\在文本中寻找"\n"

     if( pFind!=NULL )

    {

        pFind+=1;

        iCountLine ++;

    }

    else

    {

        break;

    }

}

那种既是"\n"又刚好到边缘换行处的情况,就忽略不计了。

int nTextHight = ( nTextLine +iCountLine )*size.cy;//计算整个文本显示需要的高度。

在这里,我们可以加上一个判断,如果nTextHight 小于或者等于rect.bottom-rect.top,就不用继续下去了。

下面创建内存DC,

HDC memTextHdc = CreateCompatibleDC(hdc);
HBITMAP memTextBitmap = CreateCompatibleBitmap( hdc,rect.right-rect.left,nTextHight);
int nOldMode = SetBkMode(memTextHdc,TRANSPARENT );
SelectObject(memTextHdc,memTextBitmap);
RECT memRect = {0,0,rect.right-rect.left,nTextHight};

HBRUSH hbrSEL = CreateSolidBrush (RGB(30,144,255 ));//为什么要填充背景?下面解释。
FillRect(memTextHdc, &memRect,hbrSEL);  
DeleteObject( hbrSEL );

DrawText(memTextHdc, string, -1 ,&memRect, DT_EDITCONTROL|DT_WORDBREAK );
SetBkMode(memTextHdc,nOldMode);
DeleteObject( memTextBitmap );
DeleteDC( memTextHdc );

上面就是创建了一个memRect 大小的内存DC,并将文本string全部画进去,中途我填充了背景颜色,这个是为了在画到目标hdc 的时候考虑的,因为如果目标hdc上有背景,直接画上去的画,你会发现内存DC的背景挡住了目标hdc的背景,这里我们需要做的就是,用   

BOOL TransparentBlt(
HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
UINT crTransparent //此处填你填充内存DC的颜色。
);

在画到目标hdc 上的时候,将我们在内存DC上填充的背景过滤掉。这样就只有文本显示在背景上,而没有填充的颜色了,至于设置计时器,然后每次滚动大小,就看自己喜好了,记住一点,每次滚动的越少,滚动的间隔越小,滚动的效果就越好,不过我在windows mobile手机上做过测试,每次滚动字体高度的1/10,每0.1秒滚动一次,有些闪的厉害,不知道是我的问题,还是处理器不行,呵呵。

好了,就写到这里。

posted on 2009-11-11 13:31  蓝色恋枫  阅读(288)  评论(0)    收藏  举报