三、箭头实现。
/////////////////////
//画箭头封装调用函数实现
void CButtonTestDlg::ArrowTo(
CDC *pDC, //画刷
CPoint point, //终点坐标
int nPenStyle, //线样式
int nPenWidth, //线宽度
COLORREF color, //颜色
int nWidth, //三角形底边宽度
float fTheta, //三角形顶角角度
bool bFill //是否填充颜色
)
{
CPen* pOldPen;
CPen pen(nPenStyle,nPenWidth,color);
pOldPen = pDC->SelectObject(&pen);
CBrush br,*pbrOld;
br.CreateSolidBrush(color);
pbrOld = pDC->SelectObject(&br);
//开始绘图
POINT pFrom;
POINT pBase;
POINT aptPoly[3];
float vecLine[2];
float vecLeft[2];
float fLength;
float th;
float ta;
// get from point
MoveToEx(*pDC, 0, 0, &pFrom);
// set to point
aptPoly[0].x = point.x;
aptPoly[0].y = point.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]);
if (fLength < 0.1)
{
fLength = 0.1f;
}
th = nWidth / (2.0f * fLength);
ta = nWidth / (2.0f * (tanf(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(*pDC, pFrom.x, pFrom.y, NULL);
// draw we're fillin'...
if(bFill) {
LineTo(*pDC, aptPoly[0].x, aptPoly[0].y);
Polygon(*pDC, aptPoly, 3); //画实体三角形
}
// ... or even jes chillin'...
else
{
LineTo(*pDC, pBase.x, pBase.y);
LineTo(*pDC, aptPoly[1].x, aptPoly[1].y);
LineTo(*pDC, aptPoly[0].x, aptPoly[0].y);
LineTo(*pDC, aptPoly[2].x, aptPoly[2].y);
LineTo(*pDC, pBase.x, pBase.y);
MoveToEx(*pDC, aptPoly[0].x, aptPoly[0].y, NULL);
}
//结束绘图
pDC->SelectObject(pOldPen);
pDC->SelectObject(pbrOld);
}
////////////////////////调用:
dc.MoveTo(points[0].x,points[0].y);
ArrowTo(&dc,points[1],PS_SOLID,1,RGB(0,0,0),10,45,false);
二、刷新画面。
DIALOG 属性:clip children 设置为true。意思是在绘制对话框时剪辑子窗口,
也就是在调用Invalidate();的时候,不会重绘子窗口。可以保证在Invalidate();的时候,界面不会闪。
void CButtonTestDlg::OnPaint()
{
if (IsIconic())
{
///....
}
else
{
Invalidate();//必须先Invalidate,后CPaintDC dc(this);
CPaintDC dc(this); // 用于绘制的设备上下文
CPoint points[2];
GetLinePoints((RFMSStepButton*)GetDlgItem(124),(RFMSStepButton*)GetDlgItem(125),points);
dc.MoveTo(points[0].x,points[0].y);
ArrowTo(&dc,points[1],PS_SOLID,1,RGB(0,0,0),10,45,false);
GetLinePoints((RFMSStepButton*)GetDlgItem(123),(RFMSStepButton*)GetDlgItem(125),points);
dc.MoveTo(points[0].x,points[0].y);
ArrowTo(&dc,points[1],PS_SOLID,1,RGB(0,0,0),10,45,true);
CDialog::OnPaint();
}
}