昨天花了点时间以ListView为基础,为各ListItem添加了连接箭头,模拟出一个简单的流程图界面,拖动图标时亦会调整重绘连线。
重点在绘箭头连接线用的DrawFlowLine函数上,有需要的朋友可自己扩展一下:
//CommCtrl, GraphUtil
procedure DrawFlowLine(ACanvas: TCanvas; SrcItem, DestItem: TListItem);
var
SrcPt, DestPt: TPoint;
SrcRect, DestRect: TRect;
ArrowDirect: TScrollDirection;
begin
//取对象的中点供比较之用
ListView_GetItemRect(SrcItem.ListView.Handle, SrcItem.Index, SrcRect, 0);
ListView_GetItemRect(DestItem.ListView.Handle, DestItem.Index, DestRect, 0);
SrcPt.X := SrcRect.Left + (SrcRect.Right - SrcRect.Left) div 2;
SrcPt.Y := SrcRect.Top + (SrcRect.Bottom - SrcRect.Top) div 2;
DestPt.X := DestRect.Left + (DestRect.Right - DestRect.Left) div 2;
DestPt.Y := DestRect.Top + (DestRect.Bottom - DestRect.Top) div 2;
//通过中点的比较决定箭头方向
if Abs(SrcPt.X - DestPt.X) > Abs(SrcPt.Y - DestPt.Y) then begin
if SrcPt.X <= DestPt.X then ArrowDirect := sdRight
else ArrowDirect := sdLeft;
end else begin
if SrcPt.Y <= DestPt.Y then ArrowDirect := sdDown
else ArrowDirect := sdUp;
end;
//计算线段的起点与终点
case ArrowDirect of
sdLeft: begin
SrcPt := Point(DestRect.Right-16, DestRect.Top + ((DestRect.Bottom-DestRect.Top) div 2));
DestPt := Point(SrcRect.Left+16, SrcRect.Top + ((SrcRect.Bottom-SrcRect.Top) div 2));
end;
sdRight: begin
SrcPt := Point(SrcRect.Right-16, SrcRect.Top + ((SrcRect.Bottom-SrcRect.Top) div 2));
DestPt := Point(DestRect.Left+16, DestRect.Top + ((DestRect.Bottom-DestRect.Top) div 2));
end;
sdUp: begin
SrcPt := Point(DestRect.Left + ((DestRect.Right-DestRect.Left) div 2), DestRect.Bottom+2);
DestPt := Point(SrcRect.Left + ((SrcRect.Right-SrcRect.Left) div 2), SrcRect.Top);
end;
sdDown: begin
SrcPt := Point(SrcRect.Left + ((SrcRect.Right-SrcRect.Left) div 2), SrcRect.Bottom);
DestPt := Point(DestRect.Left + ((DestRect.Right-DestRect.Left) div 2), DestRect.Top);
end;
end;
//绘制连线
ACanvas.Pen.Width := 2;
case ArrowDirect of
sdLeft, sdRight: begin
ACanvas.MoveTo(SrcPt.X, SrcPt.Y);
ACanvas.LineTo(SrcPt.X + 8, SrcPt.Y);
ACanvas.LineTo(DestPt.X - 8, DestPt.Y);
ACanvas.LineTo(DestPt.X , DestPt.Y);
end;
sdUp, sdDown: begin
ACanvas.MoveTo(SrcPt.X, SrcPt.Y);
ACanvas.LineTo(SrcPt.X, SrcPt.Y + 8);
ACanvas.LineTo(DestPt.X, DestPt.Y - 8);
ACanvas.LineTo(DestPt.X, DestPt.Y - 2);
end;
end;
//绘制箭头
case ArrowDirect of
sdLeft: DrawArrow(ACanvas, sdLeft, Point(SrcPt.X - 2, SrcPt.Y - 5), 4);
sdRight: DrawArrow(ACanvas, sdRight, Point(DestPt.X - 2, DestPt.Y - 5), 4);
sdUp: DrawArrow(ACanvas, sdUp, Point(SrcPt.X - 5, SrcPt.Y-2), 4);
sdDown: DrawArrow(ACanvas, sdDown, Point(DestPt.X - 5, DestPt.Y - 4), 4);
end;
end;
![]()
由于各种原因,我们无法获知[ListView模拟的简单流程图界面]原创作者,如侵犯了您的版权,请您及时联系我们!

