Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#
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 5-Nov-10 6:02am
Edited 5-Nov-10 6:13am
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

you can write your own little routine.
 
I just wrote up my own DrawArrow routine:
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:
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)]
  Permalink  
v3
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

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.
 
   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.
  Permalink  
Comments
Member 9806644 at 26-Nov-13 23:19pm
   
Thanks for the compact code!
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

 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.
  Permalink  
Comments
William Winner at 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)

  Print Answers RSS
0 Sergey Alexandrovich Kryukov 668
1 OriginalGriff 396
2 Tadit Dash 345
3 sanket saxena 329
4 Peter Leow 193
0 Sergey Alexandrovich Kryukov 12,109
1 OriginalGriff 7,326
2 Peter Leow 5,003
3 Abhinav S 4,003
4 Maciej Los 3,575


Advertise | Privacy | Mobile
Web03 | 2.8.140421.2 | Last Updated 6 Jul 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Use
Layout: fixed | fluid