绘图

作者:jimmy54
邮箱:[email protected]
适用平台: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 ; iCount() ; 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();
          }
}

你可能感兴趣的:(symbian)