一些常规形几何形状的绘制和效果填充(一)

源程序下载

   一些常规形几何形状的绘制和效果填充

                      visualsan@yahoo.cn

     常规几何形状是指三角形,多边形,圆,圆弧,直线,点,文字等的绘制。这些基本几何形状经过组合可以形成各种效果图,包括一些仪表和图表。要实现这些效果,使用opengl是最佳选择。但是对于不熟悉opengl编程的人来说,有些困难,而且学习opengl不是几天的事情,而且opengl使用要遵守一定的编程规则,比较繁琐。

   本人以CDC类的成员函数为基础,经过几天探索和研究以及综合一些前人代码,完成了一个基本几何图形绘制和效果填充的类CShape.现在介绍给大家。下面图形是示例程序时钟和旋转文字运行截图:

 

效果图片1:

一些常规形几何形状的绘制和效果填充(一)

效果图片2:

一些常规形几何形状的绘制和效果填充(一)

 

    CDC类所提供的路径操作和画刷填充是实现这些效果的关键。要实现的具体图形绘制有三种:1.几何轮廓绘制。2.单色几何图形的填充。3.颜色渐变填充。

    几何图形轮廓绘制较简单,它的颜色靠传递的pDC的pen决定,靠MoveTO,LineTo绘制直线,靠Arcd等绘制圆弧。关键在于正确计算各个点的位置。在绘图前创建CPen并正确传递给pDC。单色填充使用路径操作来实现。比如要绘制一个单色三角形,具体步骤为:

1.      根据需要生成指定颜色的画刷或者是位图画刷,并正确传递给pDC。

2.      使用路径画三角形并填充:

            pDC->BeginPath();//开始定义路径

            pDC->MoveTo(p1);//三点定义三角形

            pDC->LineTo(p2);

            pDC->LineTo(p3);

            pDC->LineTo(p1);

            pDC->EndPath();//结束,路径一定要封闭

            pDC->FillPath();//使用当前画刷填充三角形

    对于其他图形比如多边形,一定角度的圆环等几何形状,其绘制关键在于确定形成几何图形的参数个数,然后正确计算各个点的数值,然后BeginPath()和EndPath()创建路径。之后用指定画刷填充FillPath()。对于矩形和圆可以直接用CDC的rectangle和ellipse来绘制填充。但是复杂图形就必须用路径来绘制了。

CDC可以实现单色填充和位图填充,但是不提供颜色渐变。要实现渐变,我目前所知道的方法有两种:

    1.用位图填充。

    2.使用window API函数GradientFill实现矩形和三角形的渐变填充。

具体介绍如下。

    位图填充是指先在内存中绘制一幅覆盖目标区域的位图,然后形成位图画刷进行填充。具体步骤为:

方法1.直接绘制填充位图

      CDC* pDC=GetDC();

      CBitmap bt,*oldbt;

      CDC meDC;

      bt.CreateCompatibleBitmap(pDC, R.Width(), R.Height());

      //生成空间的//内存位图

      meDC.CreateCompatibleDC(pDC);//生成内存DC

      oldbt=meDC.SelectObject(&bt);

       

       形成需要的位图,包括颜色渐变等

           CBrush *old,b(RGB(0,255,0));

           old=meDC.SelectObject(&b);

           meDC.FillRect(R,&b);

           meDC.SelectObject(old);

           b.DeleteObject();

       /

          b.CreatePatternBrush(&bt);//形成位图画刷

          old=pDC->SelectObject(&b);//载入

          pDC->FillRect(R,&b);//使用位图画刷填充图形

          pDC->SelectObject(old);

方法2.直接载入位图作为画刷:

       CBitmap bt,*oldbt;

       bt.LoadBitmap(IDB_BITMAP1);//载入位图

       CRect R;

       GetClientRect(R);

       CBrush *old,b;

       b.CreatePatternBrush(&bt);//形成位图画刷

       old=pDC->SelectObject(&b);

       pDC->FillRect(R,&b);

       pDC->SelectObject(old);

       bt.DeleteObject();

 

 

           一些常规形几何形状的绘制和效果填充(一)  

             填充位图

   一些常规形几何形状的绘制和效果填充(一)

                           填充效果

 

另外一种方法是用GradientFill实现渐变填充,参考了一些网上的代码和文献,现在就GradientFill的使用总结如下:

1.      生成全局变量

    typedef UINT (CALLBACK* LPFNDLLFUNC1)(HDC,CONST   PTRIVERTEX,DWORD,CONST PVOID,DWORD,DWORD);

 

     LPFNDLLFUNC1 handle_GradientFill;

       HINSTANCE hinst_msimg32;

       bool m_bGradientFillInit;

在初始化时载入动态链接库:msimg32.dll

       m_bGradientFillInit=false;

       hinst_msimg32=NULL;

       hinst_msimg32 = LoadLibrary( "msimg32.dll" );

       if(hinst_msimg32)

       {

              m_bGradientFillInit = TRUE; 

               handle_GradientFill = ((LPFNDLLFUNC1) GetProcAddress(        

               hinst_msimg32, "GradientFill" ));

       }

2.在程序结束时释放动态链接库:

       f (m_bGradientFillInit)

          {

                  FreeLibrary( hinst_msimg32 );

          }

2.      可利用GradientFill实现的填充图形有两种:三角形和矩形。三角形的效果是指定三个点的颜色,然后实现颜色渐变。矩形有两种效果:从左到右实现颜色渐变和从上倒下实现颜色渐变。经过适当的扩展,我增加了三种效果:中心大左右,中心到上下,以及中心到四周的填充效果。具体做法是将矩形分成若干个三角形或矩形,然后分别填充即可实现不同的填充效果。比如中心到左右的填充效果实现如下:先把矩形分成左右两个矩形,对左边矩形实现从左到右的填充,对右边矩形实现从右向左的填充,如此总体效果是从中心到两边的渐变效果。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #include #include #include #include //////////////////////////////////////////////////////////////functions///////////////////////////////////////////////// void swap(float &m,float &n) { float temp=n; n=m; m=temp; } int sign(float a,float b)//sign() { int t; if(a>b) { t=1;} else if(adx) { swap(dx,dy); Flag=1; } else Flag=0; float Nerror=2*dy-dx; for(int i=1;i=0) { if(Flag) { x=x+sx;} else y=y+sy; Nerror=Nerror-2*dx; } if(Flag) { y=y+sy;} else x=x+sx; Nerror=Nerror+2*dy; } } ///////////////////////////////////四连通种子填充/////////////////////////////////////////////////// void BoundaryFill4(HDC hdc,int x,int y,int FilledColor,int BoundaryColor) { int CurrentColor; CurrentColor=GetPixel(hdc,x,y); if(CurrentColor!=BoundaryColor&&CurrentColor!=FilledColor) { SetPixel(hdc,x,y,FilledColor); BoundaryFill4(hdc,x+1,y,FilledColor,BoundaryColor); BoundaryFill4(hdc,x-1,y,FilledColor,BoundaryColor); BoundaryFill4(hdc,x,y+1,FilledColor,BoundaryColor); BoundaryFill4(hdc,x,y-1,FilledColor,BoundaryColor); } } ////////////////////////////////////////扫描线填充/////////////////////////////////////////////////// //DrawLine()函数:在(x1,y)和(x2,y)两点之间画一条颜色为FilledColor的横线(用来扫描填充) void drawline(HDC hdc, int x1, int x2,int y0, int FilledColor) { for(int n=x1+1;n<x2;n++) { SetPixel(hdc,n,y0,FilledColor); } } //Scan()函数:扫描线函数,将扫描线与图的交点坐标存在数组中 //数组中同行的点即为该行扫描线与图的交点(一般为2个) //数组中的行代表扫描线的纵坐标 void scan(HDC hdc, int boundarycolor) { int currentcolor; int a[300][2]={0}; for (int j=0;j<300;j++) { for(int i=300;i<700;i++) { currentcolor=GetPixel(hdc,i,j); if((currentcolor==boundarycolor)&&(GetPixel(hdc,i+1,j)!=boundarycolor)&&(i500)) {a[j][1]=i;} } } //利用循环调用DrawLine函数逐行填充两交点之间的点 for(int k=0;k<300;k++) { if((a[k][0]!=0)&&(a[k][1]!=0)) drawline(hdc,a[k][0],a[k][1],k,RGB(255,0,0));} } ///////////////////////////////////////////////边界填充////////////////////////////////////// //Contrary()取反函数:如果点的颜色为白,则将点置为填充色;如果点的颜色为填充色,则将点置为白色 //忽略了边界色,即不对边界点作颜色处理 void contrary(HDC hdc, int x, int y,int FilledColor) { for(int h=x;h<280;h++) { if(GetPixel(hdc,h,y)==RGB(255,255,255)) { SetPixel(hdc,h,y,FilledColor); } else if(GetPixel(hdc,h,y)==FilledColor) { SetPixel(hdc,h,y,RGB(255,255,255)); } } } //borderline()边线函数: 先找出图的边界 左边和右边,从右到左的顺序调用contrary()函数进行填充 void borderline(HDC hdc, int boundarycolor) { for(int j=280;j<499;j++) { for(int i=80;i100)) { contrary(hdc,i,j,RGB(0,0,255)); } } } for(int m=280;m<499;m++) { for(int n=80;n<280;n++) { int currentcolor=GetPixel(hdc,n,m); if((currentcolor==boundarycolor)&&(GetPixel(hdc,n+1,m)!=boundarycolor)&&(GetPixel(hdc,n-1,m)!=boundarycolor)&&(n<101)) { contrary(hdc,n,m,RGB(0,0,255)); } } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值