I've worked on a few developments that require graphical input form users like CAD, flow control and diagram applications. Here is a snippet of code that draws an arrow head to a line.

This is an example and in real code you might want to pass the arrow head length and width in as parameters.

procedure TMainForm.DrawArrowHead(x1, y1, x2, y2: integer;

Canvas: TCanvas);

var

HeadLength : real;

HeadWidth : real;

xbase : Integer;

xLineDelta : Integer;

xLineUnitDelta : Double;

xNormalDelta : Integer;

xNormalUnitDelta : Double;

ybase : Integer;

yLineDelta : Integer;

yLineUnitDelta : Double;

yNormalDelta : Integer;

yNormalUnitDelta : Double;

OrigBrushColor : TColor;

begin

OrigBrushColor := Canvas.Brush.Color;

Canvas.Brush.Color := clBlack;

xLineDelta := x2 - x1;

yLineDelta := y2 - y1;

xLineUnitDelta := xLineDelta / SQRT( SQR(xLineDelta) + SQR(yLineDelta));

yLineUnitDelta := yLineDelta / SQRT( SQR(xLineDelta) + SQR(yLineDelta));

// (xBase,yBase) is were the arrow line is perpendicular to base triangle.

HeadLength := 12;

HeadWidth := 2;

xBase := x2 - ROUND(HeadLength * xLineUnitDelta);

yBase := y2 - ROUND(HeadLength * yLineUnitDelta);

xNormalDelta := yLineDelta;

yNormalDelta := -xLineDelta;

xNormalUnitDelta := xNormalDelta / SQRT( SQR(xNormalDelta) + SQR(yNormalDelta));

yNormalUnitDelta := yNormalDelta / SQRT( SQR(xNormalDelta) + SQR(yNormalDelta));

//Draw the arrow tip

Canvas.Polygon([Point(x2,y2),

Point(xBase + Round(HeadWidth*xNormalUnitDelta),

yBase + ROUND(HeadWidth*yNormalUnitDelta)),

Point(xBase - ROUND(HeadWidth*xNormalUnitDelta),

yBase - ROUND(HeadWidth*yNormalUnitDelta)) ]);

Canvas.Brush.Color := OrigBrushCOlor;

end;