2010.9.29 DrawArrow画箭头

引用自:http://wupei.j2megame.org/blog.php/myblog/vc/2008/01/12/arrow-in-mfc

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

在以前做的程序中,曾经需要使用程序来画出一个箭头

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

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

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

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

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


先来看声明和实现


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,完成

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


作者:wupei (VC) :: 阅读(1715) :: 评论(2) :: 引用(0) :: 静态链接网址 :: 2008/01/12 14:32 上一篇: VC下在对话框上直接输入字母或文字的实现 (Input word on CDialog directly)
下一篇: VC下在对话框上实现接受文件拖放 (Drop files)
 Re: 东方红
本来的功能函数是有两个函数的,我又添加了一层封装,这样就是三个函数,根据参数可以看出调用方式
调用关系,为一层一层往里进的..

下面我列一下:

1. 调用:
void CMyDialog::ArrowTo(
CDC *pDC, //画刷
CPoint point, //终点坐标
int nPenStyle, //线样式
int nPenWidth, //线宽度
COLORREF color, //颜色
int nWidth, //三角形底边宽度
float fTheta, //三角形顶角角度
bool bFill //是否填充颜色
)
2. 调用 void ArrowTo(HDC hDC, int x, int y, ARROWSTRUCT *pArrow);
3. 调用 void ArrowTo(HDC hDC, const POINT *lpTo, ARROWSTRUCT *pArrow);

关于你说的起始点问题,如下:
CDC 本身就保留着当前所指示的点的,调用 dc.MoveTo(yourPoint);
原型: CDC::MoveTo
CPoint MoveTo(
int x,
int y
);
CPoint MoveTo(
POINT point
);
Parameters
x
Specifies the logical x-coordinate of the new position.

y
Specifies the logical y-coordinate of the new position.

point
Specifies the new position. You can pass either a POINT structure or a CPoint object for this parameter.

你可能感兴趣的:(raw)