引用自: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.