在以前做的程序中,曾經需要使用程序來畫出一個箭頭
但是自己想出的算法又不是太通用
所以在codeproject中尋找到一個這樣的算法,在這裏介紹一下
可以改變三角形大小,頂點角度,是否填充和填充顏色等
但是畫出的箭頭還是不夠美觀....呵呵,還好吧
其中填充是代表箭頭內是否填充顏色
href="http://www.j2megame.org/wupei/plugins/plogeshi/styles/plogeshi.css" type="text/css" rel="stylesheet" />
先來看聲明和實現
-
///////////////////////
-
//使用一個結構體來存儲相關的信息
-
//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);
-
}
OK,完成
源程序地址: 以前找的...現在去找居然找不到了....