2

I want to use a PictureBox as a canvas and draw some text on it and save.

I wrote this piece of code but I'm not sure if im doing this the correct way:

        Bitmap b = new Bitmap(pictureBox1.Width, pictureBox1.Height);
        Graphics g = Graphics.FromImage(b);
        g.FillRectangle(new SolidBrush(Color.White), new Rectangle(0, 0, pictureBox1.Width, pictureBox1.Height)); // i used this code to make the background color white 
        g.DrawString("some text", new Font("Times New Roman", 20), new SolidBrush(Color.Red), new PointF(10, 10));
        pictureBox1.Image = b;

This code works well but when I want to change the background color of the image I have to redraw the text.

Is there a way to change the background color without having to redraw the text?

vesan
  • 3,289
  • 22
  • 35
farhad
  • 105
  • 1
  • 9
  • If you want to draw the entire contents of the control yourself, don't use a `PictureBox`. Create a [**User Control** or **Custom Control**](http://stackoverflow.com/q/1322451/119527). – Jonathon Reinhart Jun 01 '15 at 22:44
  • Why are you using a picture box, just out of curiousity? – Icemanind Jun 01 '15 at 22:51
  • 1
    Set the BackgroundColor of the PB, then draw the String in the Paint() event... – Idle_Mind Jun 01 '15 at 22:54
  • 1
    @ Jonathon Reinhart the question is not about creating a control – farhad Jun 01 '15 at 23:25
  • @ Icemanind so how should i do this? i want to create an image , draw some text on it and show it on picturebox, then change the background color of the imgage and save it – farhad Jun 01 '15 at 23:26
  • Why not just use a Label? You can easily set its size and background to achieve this. – vesan Jun 02 '15 at 00:19
  • What is your real aim? The saved file or a displayed image or both? for the latter you must use Paint event and can then use a call to DrawToBitmap when you are ready to create a saveable Bitmap.. Your concern of 'redrawing' the text is misguided; there is not problem in doing this. But if you care you can set the BackColor instead of using FillRectangle. You still need to use DrawToBitmap to get the combination.. – TaW Jun 02 '15 at 08:28
  • @TaW 3 hours : the idea is simple, im trying to create a simple Paint software like the one you see in Windows. so i want to use a picturebox as canvas , then set the background color of the image to white and draw some lines and texts on the image (like what you do in Paint Software in windows) and show the image on the picturebox then change the background color to something else (bule or whatever) and finally save the image as a file on my computer. could you please write the code ?? – farhad Jun 02 '15 at 12:28
  • Not the way you are doing it now, the text is anti-aliased with the anti-aliasing pixels blending the text into the background. Makes it look good. So if you change the background color then you have to redraw the text to correct the anti-aliasing. You'll have options when you make it look bad. Not what anybody ever *really* wants to accomplish. – Hans Passant Jun 02 '15 at 15:46

1 Answers1

3

Writing a Paint program is a lot of fun, but you need to plan ahead for all or most of the features you want.

So far you have these:

  • A background you can change
  • A way to modify an image by drawing text on it
  • The need to save it all to a file

Here are a few more things you will need:

  • Other tools than just text, like lines, rectangles etc..
  • A choice of colors and pens with widths
  • A way to undo one or more steps

Here are few thing that are nice to have:

  • A way to help with drawing and positioning with the mouse
  • Other type backgrounds like a canvas or pergament paper
  • The ability to draw with some level of tranparency
  • A redo feature (*)
  • Rotation and scaling (***)
  • Levels (*****)

Some things are harder (*) or a lot harder (***) than others, but all get hard when you decide to patch them on too late..

Do read this post (starting at 'actually') about PictureBoxes, which explain how it is the ideal choice for a Paint program.

Your original piece of code and your question have these problems:

  • You seem to think that repeating anything, like redrawing the text is wrong. It is not. Windows redraws huge numbers of things all the time..
  • You have mixed two of the tasks which really should be separate.
  • You have not parametrizied anything, most notably the drawing of the text should use several variables:

    • Font
    • Brush
    • Position
    • the text itself

The same will be true once you draw lines or rectangles..

So here are the hints how do get it right:

  • Use the BackgroundColor and/or the BackgroundImage of the Picturebox to dynamically change the background!

  • Collect all things to draw in a List<someDrawActionclass>

  • Combine all drawings by drawing it into he Picturebox's Image

  • Use the Paint event to draw supporting things like the temporary rectangle or line while moving the mouse. On MouseUp you add it to the list..

So, coming to the end, let's fix your code..:

You set the backgound with a function like this:

void setBackground(Color col, string paperFile)
{
   if (paperFile == "") pictureBox1.BackColor = col;
   else pictureBox1.BackgroundImage = Image.FromFile(paperFile);
}

you can call it like this: setBackground(Color.White, "");

To draw a piece of text into the Image of the PictureBox, first make sure you have one:

void newCanvas()
{
   Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
   pictureBox1.Image = bmp;
}

Now you can write a function to write text. You really should not hard-code any of the settings, let alone the text! This is just a quick and very dirty example..:

void drawText()
{
    using (Font font = new Font("Arial", 24f))
    using (Graphics G = Graphics.FromImage(pictureBox1.Image))
    {
        // no anti-aliasing, please
        G.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;
        G.DrawString("Hello World", font, Brushes.Orange, 123f, 234f);
    }
    pictureBox1.Invalidate();
}

See here and here for a few remarks on how to create a drawAction class to store all the things your drawing is made up from..!

The last point is how to save all layers of the PictureBox:

void saveImage(string filename)
{
    using (Bitmap bmp = new Bitmap(pictureBox1.ClientSize.Width,
                                   pictureBox1.ClientSize.Height))
    {
        pictureBox1.DrawToBitmap(bmp, pictureBox1.ClientRectangle);
        bmp.Save("yourFileName.png", ImageFormat.Png);
    }
}
Community
  • 1
  • 1
TaW
  • 53,122
  • 8
  • 69
  • 111