|            
路径是Win32中新增的一个GDI对象,下面先从概念上谈起。   1 路径的概念   在Windows 95/NT 这样的Win32操作系统中,除了已有的位图,画笔,画刷,字体,调色板和区域之外,还增加了一个新的GDI对象:路径。路径是可以被填充,画出轮廓或同时被画出轮廓并填充的一个或多个图形。路径的引入,大大地丰富了Windows的图形功能,使得应用程序可以方便地建立复杂区域,绘制和填充不规则图形。这里说的不规则图形是指由直线和贝塞尔曲线组成的图形(相对于矩形,多边形,椭圆等规则图形)。   2 路径的使用   与其它原有的GDI对象不同的是,MFC类库没有专门用一个C++类来封装路径对象(或许在以后的版本中会得到支持)。有关路径的定义和使用等各种操作都必须通过调用API函数(或CDC类中对应的成员函数)来实现。   路径的使用过程大致如下:   (1)调用BeginPath()函数开始路径定义;   (2)调用GDI绘图函数来定义路径;   在Win32中,可以用于定义路径的GDI绘图函数包括:   AngleArc Arc ArcTo Chord *CloseFigure   Ellipse *ExtTextOut *LineTo *MoveToEx Pie   *PolyBezier *PolyBezierTo PolyDraw *Polygon *Polyline   *PolyLineTo *PolyPolygon *PolyPolylin Rectangl RoundRect   *TextOut   其中,在Windows 95中只能使用上述带*的GDI函数。   (3)调用EndPath()函数结束路径定义;   完成路径定义后,所定义的路径即被同时选进设备描述表,设备描述表中原有的路径对象在调用BeginPath()函数开始路径定义时即被废弃。   (4)使用路径对象。   完成路径定义工作之后,应用程序便可以利用有关GDI函数来使用路径,这些函数包括绘制路径轮廓StrokePath(),填充路径FillPath(),绘制轮廓并填充StrokeAndFillPath(),把路径转换成区域PathToRegion(),把路径直线化FlattenPath(),提取路径数据GetPath(),加宽路径WidenPath()和设置裁剪路径SelectClipPath()等。这些函数的具体使用方法可参阅有关的SDK文档。   3 应用举例   路径的引入为我们在应用程序中定义复杂区域提供了极大的方便,而不再局限于直线和椭圆弧这两种线形,这一点是很容易理解的。   另外,注意到在定义路径时可以使用TextOut()和ExtTextOut()函数,我们便可以在文字特色显示方面巧妙地使用路径,克服以往文字特显对位图操作的倚赖,从而方便快捷地制作出堪与WPS和Word等文字处理软件相媲美的“艺术汉字”来。   本文下面所提供的这个示例程序执行后,在窗口中显示出按正弦曲线起伏排列的“龙腾虎跃”五个楷体大字。窗口背景为灰色,文字前景则为一幅256色位图,就好象是把彩图剪成文字粘贴在窗口上一样(见下图)。下面具体说明该示例程序的创建方法。   (1)启动VC++,创建一个单文档应用,项目名取为Path,其它选项保留原缺省设置。   (2)在CPathView类中增加一个成员变量:   // PathView.h : interface of the CPathView class   ……   class CPathView : public CView   {   ……   // Implementation   public:   CFont m_fontKaiTi;   ……   并在CPathView类的构造函数中创建该Cfont对象,在CPathView类的析构函数中撤消该Cfont对象:   // PathView.cpp : implementation of the CPathView class   ……   CPathView::CPathView()   {   // TODO: add construction code here   m_fontKaiTi.CreateFont(200 , 0 , 0 , 0 , FW_BLACK ,   FALSE , FALSE , FALSE ,   GB2312_CHARSET ,   OUT_DEFAULT_PRECIS ,   CLIP_DEFAULT_PRECIS ,   DEFAULT_QUALITY ,   FIXED_PITCH | FF_MODERN,   "楷体_GB2312");   }   CPathView::~CPathView()   {   m_fontKaiTi.DeleteObject();   }   (3)在CPathView::OnDraw()函数中添加如下代码:   void CPathView::OnDraw(CDC* pDC)   {   ……   // TODO: add draw code for native data here   RECT rect;   GetClientRect(&rect);   CFont* pOldFont=(CFont*)pDC->SelectObject(&m_fontKaiTi);   pDC->SetBkMode(TRANSPARENT);   //定义路径   pDC->BeginPath();{   pDC->TextOut(0,10,"龙",2);   pDC->TextOut(200,10,"腾",2);   pDC->TextOut(400,10,"虎",2);   pDC->TextOut(600,10,"跃",2); }   pDC->EndPath();   pDC->SelectObject(pOldFont);   //检取路径数据   int nCount=pDC->GetPath(NULL,NULL,0);   CPoint* points=new CPoint[nCount];   BYTE* bytes=new BYTE[nCount];   pDC->GetPath(points,bytes,nCount);   //对路径定义点按正弦曲线进行变换   int i;   for(i=0;i< nCount;i++)>/p>   points[i].y=points[i].y+(int)(80*sin(points[i].x   /300.*3.1415926)+100);   //重建一个新的路径   CPoint ptStart;   pDC->BeginPath();{   for(i=0;i< nCount;i++){>/p>   switch(bytes[i]){   //移动当前点位置   case PT_MOVETO:   pDC->MoveTo(points[i]);   ptStart=points[i];   break;   //画直线   case PT_LINETO:   pDC->LineTo(points[i]);   break;   //画贝塞尔曲线   case PT_BEZIERTO:   pDC->PolyBezierTo(points+i,3);   i=i+2;   break;   //画贝塞尔曲线并封闭图形   case PT_BEZIERTO|PT_CLOSEFIGURE:   points[i+2]=ptStart;   pDC->PolyBezierTo(points+i,3);   i=i+2;   break;   //画直线并封闭图形   case PT_LINETO|PT_CLOSEFIGURE:   pDC->LineTo(ptStart);   break;   }   }   pDC->CloseFigure();   }   pDC->EndPath();   //绘制窗口灰色背景   CBrush* pOldBrush=(CBrush*)(pDC->SelectStockObject(GRAY_BRUSH));   pDC->Rectangle(&rect);   pDC->SelectObject(pOldBrush);   //设置裁剪路径   pDC->SetPolyFillMode(WINDING);   pDC->SelectClipPath(RGN_COPY);   //用位图填充裁剪区域   CBitmap bmp;   CBitmap* pBmpOld;   bmp.LoadBitmap(IDB_BMP);   CDC dcMem;   dcMem.CreateCompatibleDC(pDC);   pBmpOld=dcMem.SelectObject(&bmp);   pDC->StretchBlt(0,0,rect.right,rect.bottom,   &dcMem,0,0,600,100,SRCCOPY);   dcMem.SelectObject(pBmpOld);   dcMem.DeleteDC();   bmp.DeleteObject();   }   (4)在资源中添加文字前景位图,其ID为IDB_BMP。   (5)编译,连接,运行该应用程序。  
 |