hey all :)
I'm trying to draw an arrow at the runtime in a windows application between two controls
those controls are like a circle and a bar and I need to click a button then select those two controls one after the other then an arrow is drawn from the first selected control to the last

this is a part from a windows application that tries to simulate petri nets so this arrow may be straight or curved

could anybody help me
thx,

Recommended Answers

All 12 Replies

You'll need to throw a contol, like a panel, in the area you want the arrow to be drawn in. Then hook up its paint event. Then use the event's painteventargs object to access the panel's graphics object. and use the graphic's objects drawline method to draw from point to point. Drawing curves are a little more complicated as then you need to draw Arcs and they take a complicated set of params to achieve a desired effect. But all the documentation is there. its just about making it happen.

I could add to the suggestions Diamonddrake has given you, that a Pen object has a StartCap and EndCap property, which are of a LineCap enumeration type. If you choose the value ArrowAnchor for one of those properties, you can draw an arrow by just doing a DrawLine.

thx both of u :))
I tried to create a method to draw the line and thus call it when the button is clicked but it didn't work
this is the code of the method

private void DrawLine(int sx, int sy, int ex, int ey)
        {
            Graphics G = this.CreateGraphics(); 
            Pen P = new Pen(Color.Black, 10);
            P.StartCap = LineCap.Round;
            P.EndCap = LineCap.ArrowAnchor;
            Point p1 = new Point(sx, sy); 
            Point p2 = new Point(ex, ey); 
            G.DrawLine(P, p1, p2); 
            P.Dispose(); 
        }

and that's how I call it when the button is clicked

DrawLine(mouse_pos.X, mouse_pos.Y, mouse_pos_trans.X, mouse_pos_trans.Y);

where mouse_pos and mouse_pos_trans are static public points that's values are changed whenever the first or the second usercontrols are clicked

any suggestions??

regards,
nemoo

Did you read what Diamonddrake told you?
Drop in a Panel control and implement its Paint event.
That way you get a Graphics object for free!
You usually don't create one of your own.
BTW a Graphics object already has a DrawLine method.
But I like your way of experimenting with things:)
Keep on the good work! Questions? We are here!

I read it but after a had already tried my code :S
It works when a tried it in a private project but when I inserted it in the complete project it didn't, even though that i made sure that the two points coordinates are stored before clicking on the button but the line didn't appear

----

I am trying Diamond solution
but I don't know what to write in the button click event
this is my trial

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace DrawArrow
{
    public partial class Form1 : Form
    {
        Point st, end;
        public Form1()
        {
            InitializeComponent();
        }
         private void button1_Click(object sender, EventArgs e)
        {
            ////
        }

        private void label1_MouseDown(object sender, MouseEventArgs e)
        {
            st.X = label1.Right;
            st.Y = label1.Top+label1.Height/2;

        }

        private void label2_MouseDown(object sender, MouseEventArgs e)
        {
            end.X = label2.Left;
            end.Y = label2.Top+label2.Height/2;
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = this.CreateGraphics();
            Pen P = new Pen(Color.Black, 3);
            P.StartCap = LineCap.Round;
            P.EndCap = LineCap.ArrowAnchor;
            Point p1 = new Point(sx, sy);
            Point p2 = new Point(ex, ey);
            G.DrawLine(P, p1, p2);
            P.Dispose();
        }


    }
}

and this is my last trial but it still not working :@

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

namespace DrawArrow
{
    public partial class Form1 : Form
    {
        Point st, end;
        public Form1()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            splitContainer1.Panel2.Paint += new PaintEventHandler(splitContainer1_Panel2_Paint);
        }
        private void label1_MouseDown(object sender, MouseEventArgs e)
        {
            st.X = label1.Right;
            st.Y = label1.Top+label1.Height/2;
        }
        private void label2_MouseDown(object sender, MouseEventArgs e)
        {
            end.X = label2.Left;
            end.Y = label2.Top+label2.Height/2;
        }
        private void splitContainer1_Panel2_Paint(object sender, PaintEventArgs e)
        {
            Graphics G = this.CreateGraphics();
            Pen P = new Pen(Color.Black, 3);
            P.StartCap = LineCap.Round;
            P.EndCap = LineCap.ArrowAnchor;
            Point p1 = new Point(st.X, st.Y);
            Point p2 = new Point(end.X, end.Y);
            G.DrawLine(P, p1, p2);
            P.Dispose();
        }
    }
}

any suggestions :(

You are still creating a graphics object. Don't do that. use the paint events args graphics object.

e.Graphics.DrawLine(.....);

and after your button click refresh the panel.

[I]panelname[/I].Invalidate(false);

Also start with a standard Panel control. get simple working before you move to complicated.

thx Dragon
is that what you mean??

private void button1_Click(object sender, EventArgs e)
        {
            Panel pan = new Panel();
            pan.BackColor = Color.Transparent;
            pan.Paint += new PaintEventHandler(pan_Paint);
            pan.BringToFront();
            pan.Invalidate(false);
        }

        void pan_Paint(object sender, PaintEventArgs e)
        {
            Pen P = new Pen(Color.Black, 3);
            P.StartCap = LineCap.Round;
            P.EndCap = LineCap.ArrowAnchor;
            Point p1 = new Point(st.X, st.Y);
            Point p2 = new Point(end.X, end.Y);
            e.Graphics.DrawLine(P, p1, p2);
            P.Dispose();
        }

but it still not working :S

Why not starting a new formsapp and fill in the code below, you should see an arrow. Now use some of it in your app.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        // you can also put a Panel on the form via the toolbox
        private Panel pan = new Panel();

        public Form1()
        {
            InitializeComponent();
            
            pan.Location = new Point(10, 10);
            pan.Width = 100;
            pan.Height = 100;
            pan.Paint += new PaintEventHandler(pan_Paint);
            this.Controls.Add(pan); //add control to the form
        }

        ////did not put a button on the form
        //private void button1_Click(object sender, EventArgs e)
        //{

        //    pan.Invalidate(); //refresh the whole Panel
        //}

        void pan_Paint(object sender, PaintEventArgs e)
        {
            //this will always happen the first time
            Pen P = new Pen(Color.Black, 5);
            P.StartCap = LineCap.Round;
            P.EndCap = LineCap.ArrowAnchor;
            Point p1 = new Point(30, 30);
            Point p2 = new Point(70, 30);
            e.Graphics.DrawLine(P, p1, p2);
            P.Dispose();
        }

    }
}

thx ddnabe,
but I must use a button
the project is like a small version of visual studio (a toolbox & a space to create petri nets in)
user will select two usercontrols (a circle & a bar) that are already added into the space at runtime and then click the button then a link will be drawn between them from the first selected to the last

... come on guy you're bouncing all around it. The reason you code didn't' work is because you created a new panel but didn't add it to the form's control collection.

The button is IRRELEVANT. you can assign the points and refresh the panel at any event. on load, on button, on mouse down. doesn't matter.

I have included an example project of a finished working solution. It could be adapted to work more toward your purpose. But this is a proof of concept.

thx Diamonddrake, thx ddnabe
sorry for disturbing both of u :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.