Click here to Skip to main content
15,851,479 members
Please Sign up or sign in to vote.
3.50/5 (2 votes)
See more:
Dear reader,
I came here with a problem.
I've been working days on a code that draws a grid of dots (6 rows, 8 columns) on the form. It was very hard for me to understand how to get it drawn on the form as my knowledge with Graphics in C# is very poor, but working eventually.
What I'm trying and wanting to do next is to draw a line from a DOT to DOT on mouse clicks events. Unfortunately I couldn't came up with a good approach to do this.
I was thinking of creating a List<point> with a DOT as item, but didn't get any further. Could anyone pretty please help me out?
I added comments to make it easier for the reader to understand without causing any braindamage. Could you pretty please help me?

If so, see below for my code.
And thank you in advance!

Form1.cs:
public partial class Form1 : Form
    {
        private GridDrawing drawing;
        //private Point point1 = new Point(); //First point
        //private Point point2 = new Point(); //Second point
        ////True if point1 must be updated
        ////False if point2 must be updated
        //private bool firstPoint = true;
        private int sizeOfDot;
        private int rows;
        private int columns;
        public Form1()
        {
            InitializeComponent();
            sizeOfDot = 10;     //The size of the dot
            rows = 6;           //The amount of rows for the matrix
            columns = 8;        //The amount of columns for the matrix
            Paint += new PaintEventHandler(Form_Paint);             //Handle the Paint event
            SizeChanged += new EventHandler(Form1_SizeChanged);     //Handle the SizeChanged event to force redraw the form
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);     //to avoid flickering
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);    //to avoid flickering
        }
        private void Form_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.FillRectangle(Brushes.White, ClientRectangle);   //Fill the form in white
            drawing = new GridDrawing(this, rows, columns);             //Control, Rows, Columns
            foreach (var piece in drawing.Pieces)                           //Draws all the dots
            {
                e.Graphics.FillEllipse(Brushes.Black, (piece.Dot.X - sizeOfDot / 2),
                    (piece.Dot.Y - sizeOfDot / 2), sizeOfDot, sizeOfDot);   //Draws the dot
            }
        }
        private void startToolStripMenuItem_Click(object sender, EventArgs e)
        {
        }
        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            //if (firstPoint)             //Update point1 or point2
            //{
            //    point1 = e.Location;
            //}
            //else
            //{
            //    point2 = e.Location;
            //}
            //firstPoint = !firstPoint;   //Change the bool value
            //Invalidate();               //ask to redraw
        }
        private void Form1_SizeChanged(object sender, EventArgs e)
        {
            Invalidate();
        }
    }


GridDrawing.cs:
public class GridDrawing
{
    private int columns;
    private int rows;
    private int sizeOfDot;
    private List<GridPiece> pieces;
    //// private Point position;
    //private Point point1; //point1 to start drawing line from
    //private Point point2; //point2 to end drawing line from
    /// <summary>
    /// Constructs a grid
    /// </summary>
    /// <param name="ctrl"></param>
    /// <param name="rows"></param>
    /// <param name="columns"></param>
    /// <param name="sizeOfDot"></param>
    public GridDrawing(Control ctrl, int rows, int columns)
    {
        this.rows = rows;               // The amount of rows in the matrix.
        this.columns = columns;         // The amount of columns in the matrix.
        this.pieces = new List<GridPiece>();                // Initializes the List GridPieces
        float xOffset = (float)ctrl.ClientRectangle.Width / (columns + 1);  // Floating Point offset for X
        float yOffset = (float)ctrl.ClientRectangle.Height / (rows + 1);    // Floating Point offset for Y
        //Generate the dots
        for (int i = 0; i < rows; i++)          //Matrix with 6 rows
        {
            for (int j = 0; j < columns; j++)   //Matrix with 8 columns
            {
                PointF dot = new PointF((j + 1) * xOffset, (i + 1) * yOffset);  // Center of the dot
                GridPiece p = new GridPiece(dot);  // Creates a piece
                pieces.Add(p);                     // Puts the piece that has to be drawn in the List<GridPiece>pieces
            }
        }
    }
    public List<GridPiece> Pieces   //Property List<GridPiece>pieces
    {
        get { return this.pieces; }
    }
}


GridPiece.cs:
public class GridPiece
{
    private PointF dot;
    /// <summary>
    /// Constructor of GriedPiece
    /// </summary>
    /// <param name="bmpPic"></param>
    /// <param name="position"></param>
    public GridPiece(PointF dot)
    {
        this.dot = dot;
    }
    public PointF Dot
    {
        get { return dot; }
    }
}


PS
Sorry if the comments aren't shown properly on one line.
This is how it looks like Example. The little dot on the right is the image thats been drawn as a grid.
Altho I'm not sure why the dots on the grid are bigger then the original file...

Edit:
The code has now been edited to what I have currently.
Posted
Updated 8-Apr-11 5:33am
v7
Comments
Albin Abel 8-Apr-11 6:12am    
Is it a must you want to represent the dots with an image or a simple dot type is fine?
Makiguso 8-Apr-11 6:14am    
Thank you for reading Albin Abel,
well I thought drawing images would be easier and faster then drawing dots.
I'd rather keep this approach unless you want me to recode everything which will cost me allot of hours again cause I'm really terrible at drawing graphics in C#.

Edit:
The original picture is 28*28 pixels, but its shown bigger when drawn as a grid.
Albin Abel 8-Apr-11 6:34am    
Not exactly. There is nothing in GDI like drawing a point. To draw the dots you can draw a line where as the style of the lines can be set to dots. The would be faster than drawing images. You need to use images when you want stylish dots which can be only represented by image.
Makiguso 8-Apr-11 6:41am    
The fact that you need to use images for "stylish dots" is understandable. Tho at the moment I already got a code that draws the grid. It might not be the best approach but it still works right?
What I'm trying to do is to draw a line from the center of the dot to the other center of the dot. Any tips or examples how to approach this?

1 solution

Is it really necessary to use an image? Can't you draw directly inside your form?

You can use the MouseDown event to get the click position, and Paint event to redraw your line:

C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    //first point
    Point point1 = new Point();
    //second point
    Point point2 = new Point();
    //true if point1 must be updated
    //false if point2 must be updated
    bool firstPoint = true;
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        //draw the line
        e.Graphics.DrawLine(Pens.Black, point1, point2);
    }
    private void Form1_MouseDown(object sender, MouseEventArgs e)
    {
        //update point1 or point2
        if (firstPoint)
            point1 = e.Location;
        else
            point2 = e.Location;
        //change the bool value
        firstPoint = !firstPoint;
        //ask to redraw
        Invalidate();
    }
}


-----------------

To your comment:

Yes I mean that.
In your example, you are using Bitmaps. Unless you want to save those bitmaps to a file (or load them from a file), there are not necessary. And actually it makes your code much more complicated. If your aim is drawing circles and lines inside your form, then just put all your drawing code in the Paint handler (as shown above) and use the DrawLine, DrawEllipse, or any method from the Graphic class. It will be much easier like that.

If you don't need the MouseDown handler then forget about it, it was just to show how to update drawings. Important things are Invalidate to force the form to redraw, the Paint handler to put drawing code, and e.Graphics to draw.

---------------

Here is an example of how to draw your grid:
C#
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //handle the Paint event
        Paint += new PaintEventHandler(Form1_Paint);
        //handle the SizeChanged event to force redraw the form
        SizeChanged += new EventHandler(Form1_SizeChanged);
        //to avoid flickering
        SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    }
    //your grid parameters
    int rows = 5;
    int columns = 8;
    int sizeOfDot = 10;
    //all the drawings are there
    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        //fill the form in white
        e.Graphics.FillRectangle(Brushes.White, ClientRectangle);
        //draw the dot
        float xOffset = (float)ClientRectangle.Width / (columns + 1);
        float yOffset = (float)ClientRectangle.Height / (rows + 1);
        for (int i = 0; i < rows; i++)
            for (int j = 0; j < columns; j++)
            {
                //center of the dot
                PointF dot = new PointF((j + 1) * xOffset, (i + 1) * yOffset);
                //draw the dot
                e.Graphics.FillEllipse(Brushes.Black,
                    dot.X - sizeOfDot / 2, dot.Y - sizeOfDot / 2,
                    sizeOfDot, sizeOfDot);
            }
        //draw a line to connect 2 dots
        PointF dot1 = new PointF(4 * xOffset, 2 * yOffset);
        PointF dot2 = new PointF(2 * xOffset, 3 * yOffset);
        e.Graphics.DrawLine(Pens.Black, dot1, dot2);
    }
    //when the size of the form is changed, force a redraw
    private void Form1_SizeChanged(object sender, EventArgs e)
    {
        Invalidate();
    }
}


---------------------

To connect your dots, you can add something like that at the end of Form_Paint:
//draw the dots in this order (each value is an index in the Pieces list)
int[] sequence = new int[] { 1, 2, 3, 4, 12, 11, 19, 20, 21 };
//build a point list
PointF[] points = new PointF[sequence.Length];
for (int i = 0; i < sequence.Length; i++)
    points[i] = drawing.Pieces[sequence[i]].Dot;
//connect all points
e.Graphics.DrawLines(Pens.Black, points);
 
Share this answer
 
v6
Comments
Makiguso 8-Apr-11 6:46am    
Thank you for your time Olivier Levrey.
I took a look at the example you just gave me and tried it out. As far as I understand the code it draws a line from a specific point (mouse position on click) to the other point.
What I'm trying to do is to draw a line from the center of the dot to the other center of the dot.

With "Is it really necessary to use an image? Can't you draw directly inside your form."
Do you mean:


private void Form_Paint(object sender, PaintEventArgs e)
{
drawing = new GridDrawing(this, bmpPic, 6, 8); // Form, Bitmap, Rows, Columns
foreach (var piece in drawing.Pieces)
{
e.Graphics.DrawEllipse() // Example
}
e.Graphics.DrawLine(Pens.Black, point1, point2);
}
Olivier Levrey 8-Apr-11 7:54am    
Yes I meant that. I updated my answer to explain a little bit more. If you need more code, don't hesitate to ask.
Makiguso 8-Apr-11 8:02am    
Thank you again for your time and your explanation Olivier. I'm gonne backup the code I got right now. Could you please help me out with creating the dots with ellipse in the class GridDrawing to make code less complicated :)

Also tried adding point1 and point2 like:
drawing = new GridDrawing(this, bmpPic, 6, 8, point1, point2);
so I can add the lines that has to be drawn into a list so it won't get cleared with invalidate(); Would that be good?
Olivier Levrey 8-Apr-11 9:00am    
OK I wrote a snippet to help. Try it and tell me if it is OK.
Makiguso 8-Apr-11 9:06am    
Trying the code out. To be honest I never worked with floats.. Had absolutely no idea what it was for. And I prefer to generate the grid in the class GridDrawing.cs . Could you pretty please help me with that?

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