Search code examples
c#winformssystem.drawing

Modify an image at runtime in vs 2010 c# winForms


I need to be able to draw a text on a png file at runtime.(WinForm app 2010 c#)

Application Starts and toolbar is loaded

Customer is retrieved

At this point when a customer is loaded an icon on the toolbar must be modified and add either a number or letter to left botton corner of this icon.(png file)

I have been playing with a noddy app just to see what I can do,but I am having few issues.

  1. How do I get the path for my png file .(I am hardcoding it in my test)
  2. I am able to draw a text but it's not displayed.I guess I need to reload the toolbar,no?
  3. When writing on the icon for 2nd time or more it write on top of my previous letter.I want it to remove/clear previous one and just have the new one.

Any suggestions?

My temp code:

 private void button1_Click(object sender, EventArgs e)
    {

        string filename = @"c:\WinFormTest\Resources\column.png";

        var bitmapImage = new Bitmap(Properties.Resources.column);
        bitmapImage.DrawText("A", new Font("Arial", 8), Brushes.Black, new RectangleF(0, 0, 500, 500), filename);

    }
}

public static class ImageExtensions
{
    public static Bitmap DrawText(this Bitmap image,string textToDraw,Font font,Brush brush,RectangleF rectangleF,string filename="")
    {
        if(image==null) throw new ArgumentNullException();
        if(font==null)throw new ArgumentNullException();
        if (brush == null) throw new ArgumentNullException();
        if (rectangleF == null) throw new ArgumentNullException();

        var format = filename.GetImageFormat();
        var newBitmap = new Bitmap(image, image.Width, image.Height);
        using (var graphics = Graphics.FromImage(newBitmap))
        {
            graphics.DrawString(textToDraw, font, brush, rectangleF);
        }
        if (!string.IsNullOrEmpty(filename))
        {newBitmap.Save(filename, format);}
        return newBitmap;
    }
    public static ImageFormat GetImageFormat(this string fileName)
    {
        if (string.IsNullOrEmpty(fileName))
            return ImageFormat.Bmp;
        if (fileName.EndsWith("jpg", StringComparison.InvariantCultureIgnoreCase) || fileName.EndsWith("jpeg", StringComparison.InvariantCultureIgnoreCase))
            return ImageFormat.Jpeg;
        if (fileName.EndsWith("png", StringComparison.InvariantCultureIgnoreCase))
            return ImageFormat.Png;
        if (fileName.EndsWith("tiff", StringComparison.InvariantCultureIgnoreCase))
            return ImageFormat.Tiff;
        if (fileName.EndsWith("ico", StringComparison.InvariantCultureIgnoreCase))
            return ImageFormat.Icon;
        if (fileName.EndsWith("gif", StringComparison.InvariantCultureIgnoreCase))
            return ImageFormat.Gif;
        return ImageFormat.Bmp;
    }


}

Solution

  • You can do this at run-time without having to worry about files. If you use embedded resources then you don't have to worry about file names and clearing the changes from previous sessions and writing to files. When you create a Toolstrip button by default it will use an embedded resource (and you can refer to a shared resource that is used by other forms if you use a resx file in your project). But once you have this, you don't even need to clone the image (make a new Bitmap) as you are doing. Here's some much simpler sample code that will update the image in-place:

    public partial class Form1 : Form
    {
       public Form1()
       {
          InitializeComponent();
          ((Bitmap)toolStripButton1.Image).DrawText("B", Font, SystemBrushes.ControlText,
             new RectangleF(new PointF(0, 0), toolStripButton1.Image.Size));
       }
    }
    
    public static class ImageExtensions
    {
       public static void DrawText(this Bitmap image, string stringToDraw, Font font,
          Brush brush, RectangleF rectangleF)
       {
          using (Graphics g = Graphics.FromImage(image))
          {
             g.DrawString(stringToDraw, font, brush, rectangleF);
          }
       }
    }
    

    Since the image is not saved to a file, it is automatically reset each time the program runs. That's what you want, right?

    If you need to be able to reset the image while the program is still running you can copy the generated code that sets the image in InitializeComponent. For example:

      private void toolStripButton1_Click(object sender, EventArgs e)
      {
         this.toolStripButton1.Image.Dispose();
         System.ComponentModel.ComponentResourceManager resources =
            new System.ComponentModel.ComponentResourceManager(typeof(Form1));
         this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
         ((Bitmap)toolStripButton1.Image).DrawText("C", Font, SystemBrushes.ControlText,
            new RectangleF(new PointF(0, 0), toolStripButton1.Image.Size));
      }