作者:jimmy54
邮箱:jimmy8854@gmail.com
适用平台:S60 V3 V5
开发工具:carbide C++
摘要:绘图函数, 双缓冲, 直接画屏
一、背景知识:
在SybmianOS中,所有的绘制都是通图形上下文来完成的。
实际的图形上下文的类如下图:
1、类说明:
a.CgraphicsContext:图形上下文的抽象,声明我基本的绘图方法;
b.CbitmapContext:位图化的图形上下文抽象基类;
c.CwindowGc: 窗口图形上下文类(在窗口上操作);
d. CfbsBitGc:位图图形上下文类(在位图上操作);
2、绘图基础:
设置画笔画刷
//获得图形上下文
CWindowGc& gc = SystemGc();
//颜色值类,可以通过SetAlpha()设置透明度
TRgb black(0, 0, 0);
//设置画刷颜色
gc.SetBrushColor(black);
//设置画刷风格(实线,虚线等)
gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
//设置画笔风格
gc.SetPenStyle(CGraphicsContext::ESolidPen);
//设置画笔颜色颜色
gc.SetPenColor(KRgbBlack);
//一个准备画的矩形区域
TRect drawRect(Rect());
注:TRect 类的实用操作函数有:
//1,缩小5个像素点;
drawRect.Shrink(5, 5);
//2,放大5个像素点;
drawRect.Grow(5, 5);
//3,移动矩形
drawRect.Move(5, 5);
//画一个矩形
gc.DrawRect(drawRect);
//画人上圆角的矩形,后面的参数为圆角的大小
gc.DrawRoundRect(drawRect, TSize(5, 5));
//在一个矩形区内画一个椭圆形,如果矩形为正方形则为圆形
gc.DrawEllipse(drawRect);
//通过两点画一个线
gc.DrawLine(drawRect.iTl, drawRect.iBr);
// 画一个多边形,第一个参数为点的集合,第二个为边数
gc.DrawPolygon(triangle, 3);
以上只列出了比较常用的函数,还有很多强大的函数.具体可以参考SDK的CcoeControl类;
下面以一个全自菜单的例子来说明:
例子可在http://www.devdiv.net/bbs/viewth ... mp;extra=#pid174315下载:
void CSudokuMenuControl::DrawItems() const
{
//使用字体
iParent.UseFont(iParent.StatisticFont());
TInt txtHeight = iParent.StatisticFont()->HeightInPixels();
// 画背景
//颜色
TRgb customBlack = TRgb(0, 0, 0);
//设置透明度为90%
customBlack.SetAlpha(90);
//设置画刷
iBgc->SetBrushStyle(CGraphicsContext::ESolidBrush);
iBgc->SetBrushColor(customBlack);
//画一个矩开作为背景
iBgc->DrawRect(Rect());
// 画菜单
iBgc->SetPenColor(KRgbWhite);
//每项的大小
TPoint itemTl = Rect().iTl;
itemTl.iX += KItemCap;
itemTl.iY += KItemCap;
TRect itemRect(itemTl,TSize(iItemWidth,iItemHeight));
//循环画每一项
for (TInt i=0 ; i<iStringArray->Count() ; i++)
{
//这里是画选中行.如果为选中的就画成另一种颜色.也就是设置画刷的颜色来实现
if (iActiveItem == i)
{
iBgc->SetBrushColor(TRgb(173,146,115));
}
else
{
iBgc->SetBrushColor(TRgb(255,243,206));
}
TPtrC16 ptr = (*iStringArray);
TInt txtWidth = iParent.StatisticFont()->TextWidthInPixels(ptr);
TPoint textPoint = itemRect.iTl;
textPoint.iY += (iItemHeight - txtHeight);
textPoint.iX += ((Rect().Width() - txtWidth) /2) - KItemCap;
//画菜单每项的文字
iBgc->DrawText(ptr,textPoint);
//然后移动菜单项的矩形区域,跳到下次做同样的动作
itemRect.Move(0,iItemHeight);
itemRect.Move(0,KItemCap);
}
iBgc->SetBrushStyle(CGraphicsContext::ENullBrush);
}
//循环完毕后.一个菜单就出来了;
好了,下面通过开源游戏泡泡龙来简单介绍下双缓冲和直接屏幕访问;如果还是不明白,麻烦大家GOOGLE!
1、双缓冲
所谓的双缓冲就是先将需要画的东西都画到一个位图上面去.然后再一次性的画到屏幕上.你也可以连续画好几个位图.再依次的画到屏幕上.
这样的操作是在内存的位图上的,所以我们首先要有一个位图对象,也就是CFbsBitmap 类的实例.好了, 有了位图(画布),我们还需要在位图作图的刷和笔等工具.这就位图的图形下下文了. 也就是CfbsBitGc类的实例.最后我们还需要作画的场所,也就是CfbsBitmapDevice类的实例.
具体操作如下:
//为位图对象申请内存空间
bmpBackBuffer = new ( ELeave ) CFbsBitmap();
//创建一个指定大小,和显示模式的位图
bmpBackBuffer->Create( CEikonEnv::Static()->ScreenDevice()->SizeInPixels(), CEikonEnv::Static()->DefaultDisplayMode() );
//申请以上面位图为画布的位图设备对象
iBackBufferDevice = CFbsBitmapDevice::NewL(bmpBackBuffer);
//通过位图设备创建位图上下文
iBackBufferDevice->CreateContext( iBackBufferGc );
好了,上面的工作都完成后.我们就可以像CwindowGc类一样的使用位图上下文作图了!最后作完图后还要将位图画到屏幕上.用:
CWindowGc& gc = SystemGc();
gc.BitBlt(TPoint(0, 0), bmpBackBuffer);
注:以上代码片段在泡泡龙项目的FrozenBubbleAppView.cpp里
源码可到: http://fb-s60.sourceforge.net/下载得到;
2、直接屏幕访问
直接屏幕访问,顾名思义就是不通过窗口服务器,直接绘图;所以绘图效率提高了;
关键类为:CDirectScreenAccess
以下心泡泡龙的源码说明:
void CFrozenBubbleAppView::ConstructL( const TRect& aRect )
{
// 创建窗口
CreateWindowL();
// 设置窗口的大小
SetRect( aRect );
//设置全屏
SetExtentToWholeScreen();
//这就是双缓冲
bmpBackBuffer = new ( ELeave ) CFbsBitmap();
User::LeaveIfError(bmpBackBuffer->Create( CEikonEnv::Static()->ScreenDevice()->SizeInPixels(), CEikonEnv::Static()->DefaultDisplayMode() ));
// Create bitmap device for the bitmap
iBackBufferDevice = CFbsBitmapDevice::NewL(bmpBackBuffer);
User::LeaveIfError(iBackBufferDevice->CreateContext( iBackBufferGc ));
DrawNow();
//实例化一个CdirectScreenAccess对象传入相应的参数
iDirectScreenAccess = CDirectScreenAccess::NewL(iEikonEnv->WsSession(), *iEikonEnv->ScreenDevice(), Window(), *this);
// 激活,准备绘图
ActivateL();
//直接访问屏幕的准备工作
SetupDirectScreenAccessL();
//画背景
BlankScreen();
}
void CFrozenBubbleAppView::SetupDirectScreenAccessL()
{
iDirectEnabled = ETrue;
// 初始化DSA
iDirectScreenAccess->StartL();
//得到直接访问的图形上下文
iGc = iDirectScreenAccess->Gc();
//获得绘图区域
iRegion = iDirectScreenAccess->DrawingRegion();
// 设置要绘图区域
iGc->SetClippingRegion(iRegion);
}
void CFrozenBubbleAppView::FlipBackBuffer(TPoint aTopLeft, TRect aSrcRect)
{
//如果能够直接绘图
if (iDirectEnabled)
{
//将双缓冲的位图画到屏幕上
iGc->BitBlt(aTopLeft, bmpBackBuffer, aSrcRect);
//将窗口缓冲区都画到屏幕上
iEikonEnv->WsSession().Flush();
iDirectScreenAccess->ScreenDevice()->Update();
}
}
绘图
最新推荐文章于 2025-04-12 18:35:16 发布