1. 程式人生 > >MFC中如何畫帶實心箭頭的直線

MFC中如何畫帶實心箭頭的直線

工作中遇到話流程圖的專案,需要畫帶箭頭的直線,經過摸索,解決;思路如下:

(1) 兩個點(p1,p2)確定一個直線,以直線的一個端點(假設p2)為原點,設定一個角度

(2)以P2為原點得到向量P2P1(P),向量P旋轉theta角得到向量P1,向量P旋轉-theta角得到向量P2

(3)伸縮向量至制定長度,平移變數到直線的末端

(4)現在已經有3個點了,畫線就可

具體程式碼如下:

void CworkflowDlg::DrawLine(CPoint p1, CPoint p2)
{
        CClientDC dc(this);//獲取客戶視窗DC
	CPen pen,pen1,*oldpen;
	int PenLineWidth=2;//為了根據線條寬度設定箭頭的大小
	pen.CreatePen(PS_SOLID, PenLineWidth, RGB(0, 0, 0));
	pen1.CreatePen(PS_SOLID, PenLineWidth, RGB(0, 0, 0));
	oldpen=dc.SelectObject(&pen);
	
	double theta=3.1415926/15*PenLineWidth;//轉換為弧度
	double Px,Py,P1x,P1y,P2x,P2y;
	//以P2為原點得到向量P2P1(P)
	Px=p1.x-p2.x;
	Py=p1.y-p2.y;
	//向量P旋轉theta角得到向量P1
	P1x=Px*cos(theta)-Py*sin(theta);
	P1y=Px*sin(theta)+Py*cos(theta);
	//向量P旋轉-theta角得到向量P2
	P2x=Px*cos(-theta)-Py*sin(-theta);
	P2y=Px*sin(-theta)+Py*cos(-theta);
	//伸縮向量至制定長度
	double x1,x2;
	int length=10;
	x1=sqrt(P1x*P1x+P1y*P1y);
	P1x=P1x*length/x1;
	P1y=P1y*length/x1;
	x2=sqrt(P2x*P2x+P2y*P2y);
	P2x=P2x*length/x2;
	P2y=P2y*length/x2;
	//平移變數到直線的末端
	P1x=P1x+p2.x;
	P1y=P1y+p2.y;
	P2x=P2x+p2.x;
	P2y=P2y+p2.y;

	

	dc.MoveTo(p1.x,p1.y);
	dc.LineTo(p2.x,p2.y);
	dc.SelectObject(&pen1);
	dc.MoveTo(p2.x,p2.y);
	dc.LineTo(P1x,P1y);
	dc.MoveTo(p2.x,p2.y);
	dc.LineTo(P2x,P2y);

	dc.MoveTo(P1x,P1y);
	dc.LineTo(P2x,P2y);

	CPoint ptVertex[3];

	ptVertex[0].x = p2.x;
	ptVertex[0].y = p2.y;
	ptVertex[1].x = P1x;
	ptVertex[1].y = P1y;
	ptVertex[2].x = P2x;
	ptVertex[2].y = P2y;
        //填充三角形區域
	CBrush br(RGB(40,130,170));  
	CRgn rgn; 
	rgn.CreatePolygonRgn(ptVertex,3,ALTERNATE);
	dc.FillRgn(&rgn, &br);  

	dc.SelectObject(oldpen);

	br.DeleteObject();  
	rgn.DeleteObject();
}  


這裡面用到CreatePolyonRgn這個函式,具體用法如下: BOOL CRgn::CreatePolygonRgn(LPPOINT lpPoints, int nCount, int nMode); [說明] 建立一個由一系列點圍成的區域。windows在需要時自動將最後點與第一點相連以封閉多邊形 [引數表] lpPoint -------- POINTAPI,nCount個POINTAPI結構中的第一個POINTAPI結構 nCount --------- Long,多邊形的點數 nPolyFillMode -- Long,描述多邊形填充模式。可為ALTERNATE 或 WINDING常數。nPolyFillMode在預設情 況下為ALTERNATE; 模式ALTERNATE:其從封閉區域中的一個點向無窮遠處水平畫一條射線,只有當該射線穿越奇數條邊框線時,封閉區域才被填充,如為偶數,則不填充該區域; 模式WINDING:方法一樣,如為奇數,填充該區域;如為偶數則要根據邊框線的方向來判斷:如果穿過的邊框線在不同方向的邊框線數目相等,則不填充,如不等,則填充。 [返回值] Long,執行成功為建立的區域控制代碼,失敗則為0

具體效果如下: