MFC中实现的画箭头算法 (Arrow in MFC)

在codeproject中寻找到一个这样的算法,在这里介绍一下

可以改变三角形大小,顶点角度,是否填充和填充颜色等

但是画出的箭头还是不够美观....呵呵,还好吧

其中填充是代表箭头内是否填充颜色 

先来看声明和实现

 

 

  1. //使用一个结构体来存储相关的信息
  2. //Defines the attributes of an arrow.
  3. typedef struct tARROWSTRUCT {
  4.         int nWidth;     // width (in pixels) of the full base of the arrowhead
  5.         float fTheta;   // angle (in radians) at the arrow tip between the two
  6.                         //  sides of the arrowhead
  7.         bool bFill;     // flag indicating whether or not the arrowhead should be
  8.                         //  filled
  9. } ARROWSTRUCT;
  10.  
  11. ///////////////////////
  12. //函数声明
  13. // Draws an arrow, using the current pen and brush, from the current position
  14. //  to the passed point using the attributes defined in the ARROWSTRUCT.
  15. void ArrowTo(HDC hDC, int x, int y, ARROWSTRUCT *pArrow);
  16. void ArrowTo(HDC hDC, const POINT *lpTo, ARROWSTRUCT *pArrow);
  17.  
  18. ///////////////////////
  19. //画箭头函数实现
  20. void CMyDialog::ArrowTo(HDC hDC, int x, int y, ARROWSTRUCT *pA) {
  21.  
  22.         POINT ptTo = {x, y};
  23.  
  24.         ArrowTo(hDC, &ptTo, pA);
  25. }
  26.  
  27. void CMyDialog::ArrowTo(HDC hDC, const POINT *lpTo, ARROWSTRUCT *pA) {
  28.  
  29.         POINT pFrom;
  30.         POINT pBase;
  31.         POINT aptPoly[3];
  32.         float vecLine[2];
  33.         float vecLeft[2];
  34.         float fLength;
  35.         float th;
  36.         float ta;
  37.  
  38.         // get from point
  39.         MoveToEx(hDC, 0, 0, &pFrom);
  40.  
  41.         // set to point
  42.         aptPoly[0].x = lpTo->x;
  43.         aptPoly[0].y = lpTo->y;
  44.  
  45.         // build the line vector
  46.         vecLine[0] = (float) aptPoly[0].x - pFrom.x;
  47.         vecLine[1] = (float) aptPoly[0].y - pFrom.y;
  48.  
  49.         // build the arrow base vector - normal to the line
  50.         vecLeft[0] = -vecLine[1];
  51.         vecLeft[1] = vecLine[0];
  52.  
  53.         // setup length parameters
  54.         fLength = (float) sqrt(vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1]);
  55.         th = pA->nWidth / (2.0f * fLength);
  56.         ta = pA->nWidth / (2.0f * (tanf(pA->fTheta) / 2.0f) * fLength);
  57.  
  58.         // find the base of the arrow
  59.         pBase.x = (int) (aptPoly[0].x + -ta * vecLine[0]);
  60.         pBase.y = (int) (aptPoly[0].y + -ta * vecLine[1]);
  61.  
  62.         // build the points on the sides of the arrow
  63.         aptPoly[1].x = (int) (pBase.x + th * vecLeft[0]);
  64.         aptPoly[1].y = (int) (pBase.y + th * vecLeft[1]);
  65.         aptPoly[2].x = (int) (pBase.x + -th * vecLeft[0]);
  66.         aptPoly[2].y = (int) (pBase.y + -th * vecLeft[1]);
  67.  
  68.         MoveToEx(hDC, pFrom.x, pFrom.y, NULL);
  69.  
  70.         // draw we're fillin'...
  71.         if(pA->bFill) {
  72.                 LineTo(hDC, aptPoly[0].x, aptPoly[0].y);
  73.                 Polygon(hDC, aptPoly, 3);
  74.         }
  75.  
  76.         // ... or even jes chillin'...
  77.         else {
  78.                 LineTo(hDC, pBase.x, pBase.y);
  79.                 LineTo(hDC, aptPoly[1].x, aptPoly[1].y);
  80.                 LineTo(hDC, aptPoly[0].x, aptPoly[0].y);
  81.                 LineTo(hDC, aptPoly[2].x, aptPoly[2].y);
  82.                 LineTo(hDC, pBase.x, pBase.y);
  83.                 MoveToEx(hDC, aptPoly[0].x, aptPoly[0].y, NULL);
  84.         }
  85. }

再来看调用实现(加一层封装更加适用)

 

  1. /////////////////////
  2. //封装调用函数实现(其实还是有很大的扩展空间的)
  3. void CMyDialog::ArrowTo(
  4.         CDC *pDC,               //画刷
  5.         CPoint point,           //终点坐标
  6.         int nPenStyle,          //线样式
  7.         int nPenWidth,          //线宽度
  8.         COLORREF color, //颜色
  9.         int nWidth,             //三角形底边宽度
  10.         float fTheta,           //三角形顶角角度
  11.         bool bFill              //是否填充颜色
  12.         )
  13. {
  14.         ARROWSTRUCT a;
  15.         a.nWidth = nWidth;      //三角形底边宽度
  16.         a.fTheta = fTheta;      //三角形顶角角度
  17.         a.bFill = bFill;        //是否填充颜色
  18.        
  19.         CPen* pOldPen;
  20.         CPen pen(nPenStyle,nPenWidth,color);
  21.         pOldPen = pDC->SelectObject(&pen);
  22.  
  23.         CBrush br,*pbrOld;
  24.         br.CreateSolidBrush(color);
  25.         pbrOld = pDC->SelectObject(&br);
  26.  
  27.         ArrowTo(*pDC,point.x,point.y,&a)      //调用画箭头函数
  28.  
  29.         pDC->SelectObject(pOldPen);
  30.         pDC->SelectObject(pbrOld);
  31. }

 

 

posted @ 2010-05-16 21:52  wupingzsf  阅读(1414)  评论(0编辑  收藏  举报