Save and restore line drawings in C#

[save and restore]

The example Draw and move line segments in C# shows how to build a simple line editor. This example adds the ability to save and restore drawings.

The first step is to save all of the drawing information in a single object. You can save the information on an array or list, but it’s probably easiest if you save everything in an object from a class that you define.

The previous version of the program stored the end points of the line segments in two lists of points. This example uses the following class to represent a drawing.

// A class to serialize and deserialize drawings.
public class Drawing
{
    public List<Point> Pt1 = new List<Point>();
    public List<Point> Pt2 = new List<Point>();
}

The main program uses the following object to store the lines’ points.

// The points that make up the line segments.
private Drawing TheDrawing = new Drawing();

Most of the main program’s code is similar to the previous version except it uses this object instead of separate point lists.

The following code shows how the program saves a drawing.

// Save a serialization of the drawing.
private void mnuFileSaveAs_Click(object sender, EventArgs e)
{
    if (sfdSave.ShowDialog() == DialogResult.OK)
    {
        // Serialize.
        XmlSerializer xml_serializer =
            new XmlSerializer(TheDrawing.GetType());
        using (StreamWriter stream_writer =
            new StreamWriter(sfdSave.FileName))
        {
            xml_serializer.Serialize(stream_writer, TheDrawing);
            stream_writer.Close();
        }
    }
}

This code displays a SaveFileDialog. If the user selects a file and clicks Save, the code create an XmlSerializer to work with the type of the object TheDrawing. It creates a StreamWriter to write into the desired file and then uses the serializer to write the drawing object’s serialization into the file.

The following code shows how the program loads a saved drawing.

// Load a serialization of a drawing.
private void mnuFileOpen_Click(object sender, EventArgs e)
{
    if (ofdLoad.ShowDialog() == DialogResult.OK)
    {
        try
        {
            XmlSerializer xml_serializer =
                new XmlSerializer(TheDrawing.GetType());
            using (FileStream file_stream =
                new FileStream(ofdLoad.FileName, FileMode.Open))
            {
                Drawing new_drawing =
                    (Drawing)xml_serializer.Deserialize(file_stream);
                TheDrawing = new_drawing;
                picCanvas.Refresh();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }
}

This code displays a OpenFileDialog. If the user selects a file and clicks Open, the code create an XmlSerializer to work with the type of the object TheDrawing. It creates a StreamWriter to read from the selected file and then uses the serializer to deserialize the data in the file, converting the result into a Drawing object. If all of that succeeds, the code saves the new Drawing object in the variable TheDrawing and redraws.

The code works inside a try catch block in case something goes wrong. For example, if the user selects a file that doesn’t hold a line drawing serialization or if the file is corrupted, then the code does not replace the previous drawing.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in drawing, graphics and tagged , , , , , , , , , , , , , , , , , , , , , , , , . Bookmark the permalink.

5 Responses to Save and restore line drawings in C#

  1. Terrence says:

    Dear Rod

    Thank you for the great articles. I am wondering how to save and restore the user’s clicked coordinates on to a grid, which in turns is on a PictureBox. I have already a IList filledSq = new List(); to store the user’s clicks a grid pattern. I just want to save them and when the user wants to reopen, the program reloads the points and draw the points on the grid again.

    Thanks a lot.

    • RodStephens says:

      You could use the same approach used by this program. Create a class to hold the list of points. Then use serialization to read and write the object holding the points in and out of a file.

      • Terrence says:

        Dear Rod

        Thank you very much for the reply. I managed to serialize the points (I also changed IList to List for filledSq; otherwise, serialize has an error) nicely. But when I deserialize, the picturebox can’t show anything. I believe it is due to the way I use “pictureBoxGrid_Paint” event, in which I draw a user selected size( handled by numericUpDownMatrixSize_ValueChanged) grid pattern (e.g. 100 x 100) and the dots are drawn by another event handler “pictureBoxGrid_MouseClick”. How do I handle the redrawing of the saved points with the correct grid size?

        Thank you!!

        • RodStephens says:

          Normally you either (1) draw in Paint or (2) draw on a bitmap and then display the bitmap in the PictureBox’s Image property. Trying to do anything else usually causes problems. For example, if you use CreateGraphics to draw when the user clicks, then you get problems if the form is resized, minimized and then restored, covered by another window, etc.

          A better approach is to make a list of points and then have the Paint event handler draw them. Then when you load the saved points, you just call the PictureBox’s Refresh method and it automatically raises Paint and redraws.

          That’s how the example draws its lines. Just add your code to draw points in the Paint event handler.

          And don’t forget to call Refresh after you load saved points. If you don’t, then it will look like nothing has happened.

          • Terrence says:

            Thank you, Rod. Appreciate your help greatly. My problem was because I drew the grid in _Paint event method while the clicked dots were drawn in _MouseClick event method. I now understand I cannot even draw things in any other method except _Paint.

            I have managed to work around my issue by using a global Boolean variable to check when the file open button is clicked, then drawing the dots again in _Paint event method. Not an ideal solution yet. But starting to get the hang of it. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *