Click here to Skip to main content
15,121,564 members
Please Sign up or sign in to vote.
5.00/5 (3 votes)
See more:
hi developers:

I want to draw an arrow using C#

I can write the snippet below :

protected override void OnPaint(PaintEventArgs e)
{
   base.OnPaint(e);
   Pen p = new Pen(Color.Blue, 1);
   p.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
   p.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor;
   e.Graphics.DrawLine(p, 20, 20, 100, 100);
}


but the problem is that : the cap is going to be very small , so is there away to get around this problem ((without changing Pen width ))

thanks in advance
Posted
Updated 2-Aug-21 23:11pm
v2

Try this approach for getting a big arrow. You can adjust the size of the arrow in the AdjustableArrowCap constructor to be any size you need, without changing the width of the pen. Be sure to reference System.Drawing.Drawing2D for this.

MIDL
AdjustableArrowCap bigArrow = new AdjustableArrowCap(5, 5);
Pen p = new Pen(Color.Blue, 1);
p.CustomEndCap = bigArrow;
e.Graphics.DrawLine(p, 20, 20, 100, 100);


One advantage here is that the orientation of the arrow will be suitable regardless of whether you're drawing a straight line, curve or whatever. Plus, it's faster than executing your own routine.
   
Comments
Member 9806644 26-Nov-13 23:19pm
   
Thanks for the compact code!
you can write your own little routine.

I just wrote up my own DrawArrow routine:
C#
private void DrawArrow(Graphics g, PointF ArrowStart, PointF ArrowEnd, Color ArrowColor, int LineWidth, int ArrowMultiplier)
{
    //create the pen
    Pen p = new Pen(ArrowColor, LineWidth);

    //draw the line
    g.DrawLine(p, ArrowStart, ArrowEnd);

    //determine the coords for the arrow point

    //tip of the arrow
    PointF arrowPoint = ArrowEnd;

    //determine arrow length
    double arrowLength = Math.Sqrt(Math.Pow(Math.Abs(ArrowStart.X - ArrowEnd.X), 2) +
                                   Math.Pow(Math.Abs(ArrowStart.Y - ArrowEnd.Y), 2));

    //determine arrow angle
    double arrowAngle = Math.Atan2(Math.Abs(ArrowStart.Y - ArrowEnd.Y),Math.Abs(ArrowStart.X - ArrowEnd.X));

    //get the x,y of the back of the point

    //to change from an arrow to a diamond, change the 3
    //in the next if/else blocks to 6

    double pointX, pointY;
    if (ArrowStart.X > ArrowEnd.X)
    {
        pointX = ArrowStart.X - (Math.Cos(arrowAngle) * (arrowLength - (3 * ArrowMultiplier)));
    }
    else
    {
        pointX = Math.Cos(arrowAngle) * (arrowLength - (3 * ArrowMultiplier)) + ArrowStart.X;
    }

    if (ArrowStart.Y > ArrowEnd.Y)
    {
        pointY = ArrowStart.Y - (Math.Sin(arrowAngle) * (arrowLength - (3 * ArrowMultiplier)));
    }
    else
    {
        pointY = (Math.Sin(arrowAngle) * (arrowLength - (3 * ArrowMultiplier))) + ArrowStart.Y;
    }

    PointF arrowPointBack = new PointF((float)pointX, (float)pointY);

    //get the secondary angle of the left tip
    double angleB = Math.Atan2((3 * ArrowMultiplier), (arrowLength - (3 * ArrowMultiplier)));

    double angleC = Math.PI * (90 - (arrowAngle * (180 / Math.PI)) - (angleB * (180 / Math.PI))) / 180;

    //get the secondary length
    double secondaryLength = (3 * ArrowMultiplier)/Math.Sin(angleB);

    if (ArrowStart.X > ArrowEnd.X)
    {
        pointX = ArrowStart.X - (Math.Sin(angleC) * secondaryLength);
    }
    else
    {
        pointX = (Math.Sin(angleC) * secondaryLength) + ArrowStart.X;
    }

    if (ArrowStart.Y > ArrowEnd.Y)
    {
        pointY = ArrowStart.Y - (Math.Cos(angleC) * secondaryLength);
    }
    else
    {
        pointY = (Math.Cos(angleC) * secondaryLength) + ArrowStart.Y;
    }

    //get the left point
    PointF arrowPointLeft = new PointF((float)pointX, (float)pointY);

    //move to the right point
    angleC = arrowAngle - angleB;

    if (ArrowStart.X > ArrowEnd.X)
    {
        pointX = ArrowStart.X - (Math.Cos(angleC) * secondaryLength);
    }
    else
    {
        pointX = (Math.Cos(angleC) * secondaryLength) + ArrowStart.X;
    }

    if (ArrowStart.Y > ArrowEnd.Y)
    {
        pointY = ArrowStart.Y - (Math.Sin(angleC) * secondaryLength);
    }
    else
    {
        pointY = (Math.Sin(angleC) * secondaryLength) + ArrowStart.Y;
    }

    PointF arrowPointRight = new PointF((float)pointX,(float)pointY);

    //create the point list
    PointF[] arrowPoints = new PointF[4];
    arrowPoints[0] = arrowPoint;
    arrowPoints[1] = arrowPointLeft;
    arrowPoints[2] = arrowPointBack;
    arrowPoints[3] = arrowPointRight;

    //draw the outline
    g.DrawPolygon(p, arrowPoints);

    //fill the polygon
    g.FillPolygon(new SolidBrush(ArrowColor), arrowPoints);
}


to test it, I added a panel and two textboxes to a form and added two simple mouse events:
C#
PointF mouseStart;
PointF mouseEnd;
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
    mouseStart = new PointF(e.X, e.Y);
}
private void panel1_MouseUp(object sender, MouseEventArgs e)
{
    mouseEnd = new PointF
(e.X, e.Y);
    panel1.CreateGraphics().Clear(Form1.DefaultBackColor);
    DrawArrow(panel1.CreateGraphics(), mouseStart, mouseEnd, Color.Black,
              Convert.ToInt16(txtLineWidth.Text), Convert.ToInt16(txtArrowMultiplier.Text));
}


worked like a charm. You can change the line width or the size of the arrow independently.

[Modified: changed from Point to PointF for slightly more accurate points, also included a comment on how to change from an arrow to a diamond...(requires changing the code that calculates the arrowPointBack)]
   
v3
Pen p = new Pen(Color.Black, 10);
     p.StartCap = LineCap.Round;
     p.EndCap = LineCap.ArrowAnchor;
     g.DrawLine(p, 30, 30, 80, 30);
     p.Dispose();

You can read this link

Click




Please vote and Accept Answer if it Helped.
   
Comments
William Winner 5-Nov-10 12:31pm
   
he said, "without changing Pen width"

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900