调用MoveToEx,LineTo,Ellipse函数,实现如下实例:
使用WTL框架,选择Dialog类型,在MainDlg中定义两个private方法:
// draw arrow
void draw_arrow(int nStartX, int nStartY, int nLength) throw()
{
::MoveToEx(m_hdc, nStartX, nStartY, NULL);
::LineTo(m_hdc, nStartX + nLength, nStartY);
::LineTo(m_hdc, nStartX + nLength - 5, nStartY - 5);
::MoveToEx(m_hdc, nStartX + nLength, nStartY, NULL);
::LineTo(m_hdc, nStartX + nLength - 5, nStartY + 5);
}
// draw node
void draw_node(int nCenterX, int nCenterY, int nRadius, LPCTSTR szTag, BOOL bCurrent = FALSE) throw()
{
::Ellipse(m_hdc, nCenterX - nRadius, nCenterY - nRadius,
nCenterX + nRadius, nCenterY + nRadius);
if(bCurrent)
::Ellipse(m_hdc, nCenterX - nRadius*0.4, nCenterY - nRadius*0.4,
nCenterX + nRadius*0.4, nCenterY + nRadius*0.4);
::TextOut(m_hdc, nCenterX - 15, nCenterY + nRadius + 5, szTag, 2);
}
draw_arrow方法的作用是绘制带箭头的线段。draw_node方法的作用是绘制节点,它包含圆形及其下方的标记字符串。参数bCurrent表示本次所绘制的节点是否为当前阶段,本例选择“青年”为当前阶段,该节点的由两个同心圆与普通节点区分开来。
为MainDlg添加对WM_PAINT的消息处理,其响应方法如下所示:
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
PAINTSTRUCT ps;
BeginPaint(&ps);
m_hdc = ps.hdc;
// draw life stages
TCHAR* strStages[] = { _T("婴儿"), _T("幼儿"), _T("童年"), _T("少年"),
_T("青年"), _T("中年"), _T("老年") };
int nX = 20;
RECT rc;
GetClientRect(&rc);
int nY = rc.bottom / 2;
int nArrowLength = 50;
int nRadius = 18;
int nCurrent = 4; // current is "青年"
draw_node(nX + nRadius, nY, nRadius, strStages[0], nCurrent == 0);
for( int i = 0; i < 6; ++i ) {
draw_arrow(nX + nRadius * 2 + i * nArrowLength + 2 * i * nRadius, nY, nArrowLength);
draw_node(nX + nRadius * 3 + nArrowLength + i * nArrowLength + 2 * i * nRadius,
nY, nRadius, strStages[i+1], nCurrent == i + 1);
} // end for
EndPaint(&ps);
return 0;
}
在绘制的时候,除第一个节点之前不带有arrow外,其余6个节点都含有arrow,因此需对第一个节点进行特殊处理,将它的绘制放在for循环之外。整个工程的源码可点击下列链接下载:
http://pan.baidu.com/netdisk/singlepublic?fid=559720_2849936413