MFC中實現的畫箭頭算法 (Arrow in MFC)

在以前做的程序中,曾經需要使用程序來畫出一個箭頭

但是自己想出的算法又不是太通用

所以在codeproject中尋找到一個這樣的算法,在這裏介紹一下

可以改變三角形大小,頂點角度,是否填充和填充顏色等

但是畫出的箭頭還是不夠美觀....呵呵,還好吧

其中填充是代表箭頭內是否填充顏色 

href="http://www.j2megame.org/wupei/plugins/plogeshi/styles/plogeshi.css" type="text/css" rel="stylesheet" />

先來看聲明和實現

 

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

 

再來看調用實現(加一層封裝更加適用)

 

  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. }

 

OK,完成

源程序地址: 以前找的...現在去找居然找不到了....

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章