可以改变三角形大小,顶点角度,是否填充和填充颜色等
但是画出的箭头还是不够美观....呵呵,还好吧
其中填充是代表箭头内是否填充颜色
先来看声明和实现
- //使用一个结构体来存储相关的信息
- //Defines the attributes of an arrow.
- typedef struct tARROWSTRUCT {
- int nWidth; // width (in pixels) of the full base of the arrowhead
- float fTheta; // angle (in radians) at the arrow tip between the two
- // sides of the arrowhead
- bool bFill; // flag indicating whether or not the arrowhead should be
- // filled
- } ARROWSTRUCT;
- ///
- //函数声明
- // Draws an arrow, using the current pen and brush, from the current position
- // to the passed point using the attributes defined in the ARROWSTRUCT.
- void ArrowTo(HDC hDC, int x, int y, ARROWSTRUCT *pArrow);
- void ArrowTo(HDC hDC, const POINT *lpTo, ARROWSTRUCT *pArrow);
- ///
- //画箭头函数实现
- void CMyDialog::ArrowTo(HDC hDC, int x, int y, ARROWSTRUCT *pA) {
- POINT ptTo = {x, y};
- ArrowTo(hDC, &ptTo, pA);
- }
- void CMyDialog::ArrowTo(HDC hDC, const POINT *lpTo, ARROWSTRUCT *pA) {
- POINT pFrom;
- POINT pBase;
- POINT aptPoly[3];
- float vecLine[2];
- float vecLeft[2];
- float fLength;
- float th;
- float ta;
- // get from point
- MoveToEx(hDC, 0, 0, &pFrom);
- // set to point
- aptPoly[0].x = lpTo->x;
- aptPoly[0].y = lpTo->y;
- // build the line vector
- vecLine[0] = (float) aptPoly[0].x - pFrom.x;
- vecLine[1] = (float) aptPoly[0].y - pFrom.y;
- // build the arrow base vector - normal to the line
- vecLeft[0] = -vecLine[1];
- vecLeft[1] = vecLine[0];
- // setup length parameters
- fLength = (float) sqrt(vecLine[0] * vecLine[0] + vecLine[1] * vecLine[1]);
- th = pA->nWidth / (2.0f * fLength);
- ta = pA->nWidth / (2.0f * (tanf(pA->fTheta) / 2.0f) * fLength);
- // find the base of the arrow
- pBase.x = (int) (aptPoly[0].x + -ta * vecLine[0]);
- pBase.y = (int) (aptPoly[0].y + -ta * vecLine[1]);
- // build the points on the sides of the arrow
- aptPoly[1].x = (int) (pBase.x + th * vecLeft[0]);
- aptPoly[1].y = (int) (pBase.y + th * vecLeft[1]);
- aptPoly[2].x = (int) (pBase.x + -th * vecLeft[0]);
- aptPoly[2].y = (int) (pBase.y + -th * vecLeft[1]);
- MoveToEx(hDC, pFrom.x, pFrom.y, NULL);
- // draw we're fillin'...
- if(pA->bFill) {
- LineTo(hDC, aptPoly[0].x, aptPoly[0].y);
- Polygon(hDC, aptPoly, 3);
- }
- // ... or even jes chillin'...
- else {
- LineTo(hDC, pBase.x, pBase.y);
- LineTo(hDC, aptPoly[1].x, aptPoly[1].y);
- LineTo(hDC, aptPoly[0].x, aptPoly[0].y);
- LineTo(hDC, aptPoly[2].x, aptPoly[2].y);
- LineTo(hDC, pBase.x, pBase.y);
- MoveToEx(hDC, aptPoly[0].x, aptPoly[0].y, NULL);
- }
- }
再来看调用实现(加一层封装更加适用)
- /
- //封装调用函数实现(其实还是有很大的扩展空间的)
- void CMyDialog::ArrowTo(
- CDC *pDC, //画刷
- CPoint point, //终点坐标
- int nPenStyle, //线样式
- int nPenWidth, //线宽度
- COLORREF color, //颜色
- int nWidth, //三角形底边宽度
- float fTheta, //三角形顶角角度
- bool bFill //是否填充颜色
- )
- {
- ARROWSTRUCT a;
- a.nWidth = nWidth; //三角形底边宽度
- a.fTheta = fTheta; //三角形顶角角度
- a.bFill = bFill; //是否填充颜色
- CPen* pOldPen;
- CPen pen(nPenStyle,nPenWidth,color);
- pOldPen = pDC->SelectObject(&pen);
- CBrush br,*pbrOld;
- br.CreateSolidBrush(color);
- pbrOld = pDC->SelectObject(&br);
- ArrowTo(*pDC,point.x,point.y,&a); //调用画箭头函数
- pDC->SelectObject(pOldPen);
- pDC->SelectObject(pbrOld);
- }